Error Codes & Rate Limits
Error Handling
The API uses standard HTTP status codes and returns all responses in a consistent JSON envelope with success, data, error, and meta fields.
ENVELOPE
Response Format
All API responses — both success and error — follow this standard envelope:
Success Response
{
"success": true,
"data": { ... },
"error": null,
"meta": {
"requestId": "req_a1b2c3",
"timestamp": "2026-03-17T10:30:00Z",
"version": "v1"
}
}Error Response
{
"success": false,
"data": null,
"error": {
"code": "INVALID_PARAMETER",
"message": "The \"code\" parameter is required.",
"details": "Provide a valid contract code (e.g., AAPL_NASDAQ). Use GET /v1/market/exchanges/{symbol} to find available exchanges."
},
"meta": {
"requestId": "req_x9y8z7w6",
"timestamp": "2026-03-17T10:30:00Z",
"version": "v1"
}
}SCHEMA
Envelope Fields
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the request was successful |
data | object | array | null | The response payload (varies by endpoint) |
error | ApiError | null | Error details when success is false |
meta | ApiMeta | Request metadata (requestId, timestamp, version) |
ApiError Object
| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code (e.g., "INVALID_PARAMETER") |
message | string | Human-readable error message |
details | string | null | Additional context about the error |
ApiMeta Object
| Field | Type | Description |
|---|---|---|
requestId | string | Unique request identifier for debugging |
timestamp | datetime | Server timestamp of the response |
version | string | API version (e.g., "v1") |
STATUS CODES
HTTP Status Codes
| Code | Name | Description | How to Fix |
|---|---|---|---|
400 | Bad Request | The request body or parameters are invalid. | Check required fields and data types match the schema. |
401 | Unauthorized | Missing or invalid API key / JWT token. | Include a valid X-Api-Key header or JWT Bearer token. |
403 | Forbidden | The API key lacks permission for this action. | Use an active API key with sufficient permissions. |
404 | Not Found | The requested resource does not exist. | Verify the symbol, keyId, or endpoint path. |
405 | Method Not Allowed | The path exists but not for this HTTP method. This is rejected by the framework before the response envelope is applied, so a 405 carries an EMPTY body — do not try to parse it as JSON. | Check the method for the route (for example POST /v1/portfolio/analyze is POST-only). |
429 | Too Many Requests | Rate limit exceeded. | Wait and retry. Check your usage limits via GET /v1/account/usage. |
500 | Internal Server Error | An unexpected error occurred on the server. | Retry the request. Contact support if it persists. |
503 | Service Unavailable | A backing service this endpoint depends on — the news pipeline, the Nova ML engine, or the graph analysis service — is temporarily unreachable. The request itself was valid. | Retry after a short delay. The error code names the subsystem (for example NEWS_UNAVAILABLE, NOVA_UNAVAILABLE, REPORT_UNAVAILABLE). |
RATE LIMITS
Rate Limiting
The API enforces per-account rate limits to ensure fair usage and platform stability. Rate limit information is included in every response via HTTP headers. Check your limits via GET /v1/account/usage.
Per-Minute Limit
A sliding one-minute window, applied per API key. The allowance is set by your subscription tier and ranges from 60 requests/minute on Free to 1,000 on Business. Exceeding it returns 429 RATE_LIMIT_EXCEEDED with a Retry-After header.
Daily Limit
A calendar-day (UTC) quota, also set by your tier — from 1,000 requests/day on Free up to unlimited on Business and Enterprise. It resets at 00:00 UTC.
The same limits apply to every endpoint — there is no separate allowance for market data. Every request that carries your X-Api-Key counts against your quota, including requests made from the Try It console on this site. Requests sent without an API key are bucketed by IP address instead, at 30 requests/minute and 500 per UTC day. Your own effective limits are returned by GET /v1/account/usage and may be higher than your tier default if custom limits are set on your account; the full tier table is at GET /v1/account/tiers.
Rate Limit Headers
| Header | Description |
|---|---|
X-RateLimit-Limit | Your daily request quota, or "unlimited" on tiers without one |
X-RateLimit-Remaining | Requests left in the current UTC day, or "unlimited" |
X-RateLimit-Reset | Unix timestamp of the next daily reset (00:00 UTC) |
X-RateLimit-Tier | The subscription tier the limits were resolved from |
X-RateLimit-Minute-Limit | Your per-minute allowance |
X-RateLimit-Minute-Remaining | Requests left in the current minute window |
HANDLING
When Rate Limited
When you exceed the rate limit, the API returns a 429 Too Many Requests response:
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Per-minute rate limit exceeded.",
"details": "Tier: Free. Retry after 55 seconds. Upgrade your plan at /v1/account/tiers for higher limits."
},
"meta": { "requestId": "req_x9y8z7", "timestamp": "2026-07-28T02:10:05Z", "version": "v1" }
} Note that this response omits the data key altogether rather than sending "data": null. The message distinguishes which limit you hit — Per-minute rate limit exceeded. or Daily rate limit exceeded.
Recommended strategy: Implement exponential backoff with jitter, and honour the Retry-After header — it carries the exact number of seconds until the limit you hit clears (seconds remaining in the minute, or until 00:00 UTC for the daily limit). X-RateLimit-Reset is the daily reset timestamp, so it is the wrong signal to wait on after a per-minute 429.
TROUBLESHOOTING
Common Issues
401 on Every Request
Ensure you're sending the X-Api-Key header (not Authorization). Check that your key has not been revoked.
CORS Errors
The API supports CORS for authenticated requests. For browser-based calls, ensure your origin is allowed. Server-to-server calls bypass CORS.
Request Timeouts
The API has a 30-second timeout. If you experience timeouts, check your network connection and retry the request.