Errors and rate limits
Who can use this feature?
- Applies to every Chatty API. Creating the keys these limits apply to requires the Pro or Plus plan.
Every limit at a glance
Build your integration against these numbers rather than discovering them in production.
| Where | Limit |
|---|---|
| GraphQL Customer API | Metered by query cost, not request count. The budget is not published and responses carry no rate limit headers |
| Chat Conversations API | 120 requests/min per API key |
| Chat Conversations API | 300 requests/min per source IP |
| Chat Conversations API conversation lists | 20 per page by default, 100 maximum |
| Chat Conversations API message lists | 50 per page by default, 100 maximum |
| Chat Conversations API related conversations | 6 per page by default, 50 maximum |
| Chat Conversations API customer conversations | 20 per page by default, 100 maximum |
| API keys | 5 active keys per store |
| Webhook subscriptions | 10 per store |
| Webhook delivery timeout | 10 seconds |
| Webhook payload | above 80,000 bytes, data is replaced with {"truncated": true, "originalSize": N}; metadata is rejected above 2,048 bytes |
| Chat Conversations API message | 5,000 characters of text |
| Chat Conversations API note | 150 characters |
| Chat Conversations API tag | 100 characters, longer tags are dropped from the request; a request where every tag is too long returns 400 |
| Chat Conversations API browsed pages | the 50 most recent pages of the session, kept about 24 hours |
| Chat Conversations API attribute | name 255 characters, value 1,000 characters |
| MCP server | No request rate limit |
MCP update_tags | 50 characters per tag, longer tags are truncated without an error, and 100 tags are kept per conversation |
MCP list_conversations | limit defaults to 20 and has no maximum |
| SDK message sending | 15 messages/min, 5,000 characters each |
| SDK typing indicator | 30 calls/min |
| SDK commerce context | 8 KB |
The per-IP limit matters when several integrations share one server. Two keys sending 200 requests a minute each stay under the key limit but trip the IP limit together.
Reading rate limit headers
Chat Conversations API responses carry X-RateLimit-Limit and X-RateLimit-Remaining. Watch X-RateLimit-Remaining and slow down before it reaches zero. That is cheaper than recovering from a block.
The GraphQL Customer API returns no such headers, so there is no counter to watch there. Pace that API with modest page sizes and backoff instead.
Both counters expire 60 seconds after your last request, not 60 seconds after the first one. Calling again while you are blocked pushes the expiry back, so a blocked key or IP has to go quiet for a full minute before the count resets.
How each API reports an error
Chatty has four API surfaces and they do not share one error format. Handle each one on its own terms.
Chat Conversations API and webhook management
A JSON body with a code you can branch on. The full status and code table lives on the Chat Conversations API page.
{ "error": { "code": "RATE_LIMITED", "message": "Rate limit exceeded" } }GraphQL Customer API
Standard GraphQL: HTTP 200 with an errors array. Check errors[].extensions.code, not the HTTP status.
{ "errors": [ { "message": "Missing x-api-id or x-api-secret", "extensions": { "code": "UNAUTHENTICATED" } } ] }The codes confirmed on this endpoint are BAD_REQUEST, GRAPHQL_PARSE_FAILED, GRAPHQL_VALIDATION_FAILED and UNAUTHENTICATED. Chatty does not publish a code for exceeding the cost budget, so branch on extensions.code, treat any code you do not recognise as retryable after a wait, and log the raw envelope so you can see what came back.
MCP server
Tool results and most failures come back as JSON-RPC. Authentication failures do not. They return HTTP 401 with a plain object instead.
{ "error": "Invalid or revoked API key." }Check for a top-level error string before you try to parse a JSON-RPC response.
Storefront SDK
The SDK reports nothing back. Commands return no value and there is no error callback, so a rejected command is silent. Validate input on your side before you push it. See Error handling in the SDK reference.
What to do when a request fails
| You see | Do this |
|---|---|
429 / RATE_LIMITED | Wait, then retry with exponential backoff. Retrying immediately extends the block. |
401 / UNAUTHENTICATED | Check the header name. Each API expects a different one. See Authentication. |
401 right after deleting a key | Expected. Key deletion takes up to 5 minutes to propagate. |
401 right after creating a key | Expected for up to 30 seconds. Wait, then retry. |
403 / FORBIDDEN | Reserved for a future permission split on resolve, assign, mark read, and typing. Every key issued today carries full access, so a valid key should never see this. |
404 on a resource you believe exists | The resource belongs to another store, or the ID is wrong. Chatty returns the same 404 for both. |
409 / CHANNEL_UNAVAILABLE | The channel cannot deliver right now, for example a WhatsApp session that has expired. Do not retry blindly. |
400 / INVALID_PARAMS | Read the message; it names the parameter at fault. |
Webhook delivery and retries
Webhooks follow their own rules, because Chatty is calling you rather than the other way around.
Your endpoint has 10 seconds to respond. Return 2xx as soon as you have stored the event and process it afterwards. Doing the work before you reply is the most common cause of failed deliveries.
Chatty makes 7 delivery attempts in total: the first one, then 6 retries spread over about 9 hours. The waits between them are roughly 10 seconds, 1 minute, 5 minutes, 30 minutes, 2 hours, and 6 hours. After the seventh attempt fails, the subscription is switched off and you have to turn it back on.
Returning 410 Gone disables the subscription immediately, with no retries. Use it deliberately when an endpoint is permanently retired, never as a generic error response.
Because deliveries retry, the same event can reach you more than once. Store the event ID and ignore repeats.
Need help?
If you keep hitting a limit that blocks a legitimate integration, contact the Chatty support team from your dashboard with your App ID and an example request.
Chatty Help Center