Errors & Status Codes
The finlight API uses conventional HTTP status codes to signal the outcome of a request. A 2xx status means success; 4xx means the request was rejected (usually something you can fix); 5xx means a problem on our side. Every error returns a JSON body describing what went wrong.
Note: REST and WebSocket requests authenticate with the
X-API-KEYheader. A missing or invalid key returns401. (Webhook delivery auth — the headers finlight sends to your endpoint — is separate; see Webhook Authentication.)
Status codes at a glance
| Status | Meaning | When it happens |
|---|---|---|
200 | OK | Successful request. |
400 | Bad Request | Invalid parameters or malformed query syntax. |
401 | Unauthorized | Missing or invalid X-API-KEY. |
403 | Forbidden | Your plan doesn't include the requested capability. |
404 | Not Found | The requested resource doesn't exist (e.g. unknown article link). |
422 | Unprocessable Entity | Request body/params failed validation (global validator). |
429 | Too Many Requests | Monthly quota or burst rate limit exceeded. |
500 | Internal Server Error | Unexpected error on finlight's side. |
400 — Bad Request
Returned when query parameters or the request body fail validation, or when the query string uses invalid field-level syntax.
Invalid parameter:
{
"statusCode": 400,
"message": ["pageSize must not be greater than 100"],
"error": "Bad Request"
}
Invalid query syntax (POST /v2/articles):
{
"statusCode": 400,
"message": [
{
"property": "query",
"constraints": { "query": "Invalid query syntax near 'ticker:'" }
}
],
"error": "Bad Request"
}
See Advanced Query Building for the correct query syntax.
401 — Unauthorized
The X-API-KEY header is missing, malformed, or not a valid key.
{
"statusCode": 401,
"message": "Unauthorized"
}
Grab or rotate your key in the finlight dashboard.
403 — Forbidden
The request is authenticated, but your plan doesn't include the requested capability — for example, requesting full article content on a plan that doesn't include it.
{
"statusCode": 403,
"message": "Your subscription does not allow calling the extended article content"
}
See Rate Limits & Quotas for which capabilities each plan includes.
404 — Not Found
The requested resource doesn't exist — most commonly GET /v2/articles/by-link with a link finlight hasn't indexed.
{
"statusCode": 404,
"message": "Article not found"
}
422 — Unprocessable Entity
Some endpoints validate through the global validator, which returns a field-keyed error map. Each key is the offending field; the value lists the failed constraints.
{
"status": 422,
"errors": {
"language": "language must be a string"
}
}
Note: Validation failures may surface as
400(on the article endpoints) or422(global validator), depending on the route — both indicate a malformed request. Inspect the body to see which field failed.
429 — Too Many Requests
You've exceeded a usage limit. There are two distinct cases, each with a specific message:
Monthly request quota exceeded:
{
"statusCode": 429,
"message": "Throttling Exception: Exceeded token limit of 5000 for the current period."
}
Burst (short-term) rate exceeded:
{
"statusCode": 429,
"message": "Throttling Exception: Exceeded rate limit of 10 requests per 10 seconds."
}
Note: finlight does not currently return
Retry-Afteror rate-limit headers. For a burst429, back off and retry after ~10 seconds. For a monthly quota429, requests will succeed again at the start of your next billing period (or after an upgrade). See Rate Limits & Quotas.
500 — Internal Server Error
An unexpected error occurred on finlight's side. These are transient — retry with backoff, and if it persists, reach out via Support.
{
"statusCode": 500,
"message": "Internal server error"
}
Handling errors well
- Always check the status code first, then read the JSON body for specifics.
4xx(except429) are your bug — fix the request; retrying unchanged won't help.429and5xxare retryable — use exponential backoff. For burst429, ~10s is enough.- WebSocket errors arrive as an
errorserver message on the socket rather than an HTTP status — see WebSocket Basics. - Webhook delivery failures (to your endpoint) are tracked in the dashboard, not returned to you synchronously — see Testing Webhooks.