> ## Documentation Index
> Fetch the complete documentation index at: https://docs.moritosh.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate limits

> Request limits and how to handle them

Rate limits protect the API for everyone. Limits are applied per API key.

## Default limits

| Endpoint group      | Limit                          |
| ------------------- | ------------------------------ |
| `POST /messages`    | 100 requests/second, burst 300 |
| All other endpoints | 25 requests/second, burst 75   |

Limits scale automatically as your sending volume grows. If you're hitting limits during normal operation, contact us — we'll usually raise them before you ask.

## Response headers

Every response includes your current limit status:

```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1718721600
```

| Header                  | Description                            |
| ----------------------- | -------------------------------------- |
| `X-RateLimit-Limit`     | Requests allowed in the current window |
| `X-RateLimit-Remaining` | Requests left in the current window    |
| `X-RateLimit-Reset`     | Unix timestamp when the window resets  |

## When you exceed a limit

You'll receive a `429` with a `rate_limit_error` and a `Retry-After` header (seconds to wait):

```json theme={null}
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded, retry after 2 seconds",
    "param": null
  }
}
```

## Handling rate limits

Back off and retry rather than failing the request outright:

```javascript theme={null}
async function sendWithRetry(payload, attempt = 0) {
  try {
    return await pulsewave.messages.send(payload);
  } catch (err) {
    if (err.type === 'rate_limit_error' && attempt < 5) {
      const delay = Number(err.retryAfter ?? 1) * 1000;
      await new Promise((r) => setTimeout(r, delay));
      return sendWithRetry(payload, attempt + 1);
    }
    throw err;
  }
}
```

Official SDKs implement this backoff automatically.
