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

# Rate Limits & Errors

> Per-Space rate limits on the Cometly MCP endpoint, the structured `[error_class]` envelope, and how connected AI clients recover from failures.

## Rate limits

The MCP endpoint sits behind a per-Space throttle, shared across all MCP clients connected to that Space.

| Limit                         | Value  |
| ----------------------------- | ------ |
| Requests per Space per minute | **60** |

That's enough headroom for typical Ask-AI-style flows where each user message triggers one to a handful of tool calls. If you're driving the MCP server from an automated agent that fans out across many tool calls per turn, you may hit the limit during a heavy iteration.

Limits are returned in standard response headers:

```
X-RateLimit-Limit:     60
X-RateLimit-Remaining: 42
X-RateLimit-Reset:     1734567890
```

When you exceed the limit you get a `429 Too Many Requests` JSON-RPC error and a `Retry-After` header. MCP-aware clients (Claude Desktop, Cursor) back off automatically on `429` and retry once the window clears.

## Underlying API limits

Each MCP tool delegates to a [Public API V1](/api-reference/endpoint/list-events) endpoint, and those endpoints have their own per-Space throttles:

| Tool                            | Underlying endpoint limit |
| ------------------------------- | ------------------------- |
| `list_events`, `get_event`      | 7/minute                  |
| `list_contacts`, `get_contact`  | 15/minute                 |
| `list_companies`, `get_company` | 15/minute                 |
| `query_ad_metrics`              | 30/minute                 |

The MCP endpoint throttle (60/minute) is hit first in most cases, but a chatty single tool can still trip its own per-endpoint limit before the MCP throttle catches it.

## Error envelope

Every error from an MCP tool returns a structured envelope so the model can recover deterministically without parsing prose:

```
[<error_class>] <human-readable message>
Reference ID: <correlation_id>
```

The `[error_class]` prefix is one of:

| Class                  | When it fires                                                            | What the model should do                                                  |
| ---------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------- |
| `validation_error`     | Bad parameter shape, enum, or type.                                      | Re-call with corrected args (e.g. valid date format, supported operator). |
| `authorization_error`  | Token doesn't grant the requested scope, or user lost Space access.      | Stop. Surface "I lost access to this Space" to the user.                  |
| `not_found`            | Record (event/contact/company by ID) doesn't exist.                      | Surface "no record with that ID" to the user. Don't retry.                |
| `rate_limited`         | Per-Space or per-endpoint throttle hit.                                  | Wait, back off, then retry.                                               |
| `upstream_unavailable` | SingleStore or an ad-platform API is temporarily down.                   | Retry once after a short wait.                                            |
| `internal_error`       | Unhandled exception. Already logged to Sentry with the `correlation_id`. | Stop. Surface "something went wrong" to the user.                         |
| `unknown_tool`         | Tool name doesn't exist on this server.                                  | Drop the call; the model probably hallucinated the tool.                  |

The `Reference ID: …` is the row ID in `mcp_audit_log` for this call. Include it in support requests so the Cometly team can trace the failure end-to-end.

## Validation error detail

Validation errors include the field-by-field reasons, formatted for the model:

```
[validation_error] The given data was invalid.
- custom_field_filters.0.field: The custom field profile_field_19 is not configured for this space. Configure a label in the Cometly dashboard before filtering by it.
- custom_field_filters.0.operator: The operator "greater_than" is not supported for text fields. Allowed: equal_to, not_equal_to, contains, not_contains, starts_with, ends_with, contains_word, any, unknown.
Reference ID: 5a8d1e29-...
```

Validation errors are **not** reported to Sentry — they're user-input failures. Other 5xx-mapped failures are.

## Best practices for client builders

1. **Always parse the `[error_class]` prefix**, not the message text. Messages may evolve; the class won't.
2. **Honour `Retry-After`** on `429`. Cometly doesn't bill for retries, but a hot loop will keep you locked out.
3. **Surface the `Reference ID`** to end users when an error escapes. It's the fastest way to get a real diagnosis from support.
4. **Don't cache `401` responses.** When OAuth tokens expire, the next call has to walk the flow.
