> TickerLayer documentation for AI agents and LLMs, the Markdown version of https://tickerlayer.com/docs/errors
> REST base URL https://api.tickerlayer.com, API key in the `x-api-key` header. WebSocket wss://stream.tickerlayer.com?apiKey=YOUR_API_KEY.
> Any docs page reads as Markdown at its URL plus `.md`. Index: https://tickerlayer.com/llms.txt · Full API reference: https://tickerlayer.com/llms-full.txt

# Errors

Use HTTP status codes, JSON bodies on REST 429/503, and WebSocket error frames to branch retries, backoff, and user messaging.

## REST errors

| Status | Meaning |
| --- | --- |
| `400` | Invalid path or query parameters; the message lists the valid values. |
| `401` | Missing or invalid key. |
| `403` | Inactive key, a key not entitled for REST, or a plan that leaves out the data. On stocks, ETFs, indices, commodities and bonds the plan case carries `"error": "NOT_IN_PLAN"` and `product`, plus `market` on a stock; other products name themselves in `message`. |
| `404` | The route exists but the symbol or resource does not: `{ "statusCode": 404, "message": "…" }`, with an optional `error` field. |
| `429` | The per-second limit or the monthly quota; the `error` field says which, and a quota answer gives `resetsAt`, when the allowance renews (UTC). |
| `503` | Usage metering is unavailable, so the request fails closed. |

**Rate limit (429)**

```json
{
  "statusCode": 429,
  "message": "rate limit exceeded",
  "error": "REST_RATE_LIMIT_EXCEEDED",
  "limitRps": 10,
  "retryAfterMs": 250
}
```

**Monthly quota (429)**

```json
{
  "statusCode": 429,
  "message": "rate limit exceeded",
  "error": "REST_QUOTA_EXCEEDED",
  "limit": 3000,
  "resetsAt": "2026-11-02T14:05:31.000Z"
}
```

**Not in plan (403)**

```json
{
  "statusCode": 403,
  "message": "unauthorized",
  "error": "NOT_IN_PLAN",
  "product": "stocks",
  "market": "DE"
}
```

The per-second `429` also sends `Retry-After`, and every REST response carries `X-RateLimit-Limit` and `X-RateLimit-Remaining`: see [Rate limit headers](https://tickerlayer.com/docs/limits#headers).

## WebSocket upgrade errors

Invalid keys and connection caps are refused before any frame is exchanged. Every upgrade status is listed on [Connection](https://tickerlayer.com/docs/websocket/connection#upgrade-outcomes).

**Account connection limit (429)**

```json
{
  "error": "WS_CONNECTION_LIMIT_EXCEEDED",
  "message": "rate limit exceeded"
}
```

## WebSocket frame errors

After connect, a failed subscribe returns a `type: "error"` frame with a machine-readable `code`. Every code is listed on [Errors & troubleshooting](https://tickerlayer.com/docs/websocket/troubleshooting#frame-errors).

**Symbol limit exceeded**

```json
{
  "type": "error",
  "event": "subscribe_failed",
  "code": "SYMBOL_LIMIT_EXCEEDED",
  "message": "rate limit exceeded"
}
```
