Errors
RFC 9457 problem+json, and every status code the API returns.
Errors are RFC 9457 problem details, served as
Content-Type: application/problem+json.
{
"type": "https://www.cruxal.in/docs/errors#rate-limit-exceeded",
"title": "Too Many Requests",
"status": 429,
"detail": "Rate limit of 300 requests per minute exceeded. Limits are measured in fixed one-minute windows.",
"instance": "/v1/filings"
}
type is a URL that resolves to a page explaining that specific error. Branch your code on
type or on the HTTP status — never on the wording of detail, which may be reworded.
Status codes
| Status | type | Meaning |
|---|---|---|
400 | bad-request | Malformed request — most often a cursor reused after a filter changed. |
400 | invalid-request | A parameter failed validation. Carries an errors array. |
401 | unauthorized | Missing, malformed, unknown, revoked or expired key. |
403 | quota-exceeded | Monthly quota exhausted. Retrying will not help. |
404 | not-found | No such filing, company or article — or it is outside your plan's freshness window. |
405 | method-not-allowed | Wrong HTTP verb. Every endpoint here is GET. |
429 | rate-limit-exceeded | Per-minute rate exceeded. Honour Retry-After. |
500 | internal-error | Our fault. Carries a trace_id — quote it when you contact support. |
Validation errors
A 400 from validation carries an errors array naming each offending field:
{
"type": "https://www.cruxal.in/docs/errors#invalid-request",
"title": "Invalid Request",
"status": 400,
"detail": "One or more request parameters are invalid.",
"instance": "/v1/filings",
"errors": [
{ "field": "limit", "message": "Input should be less than or equal to 200", "type": "less_than_equal" }
]
}
A note on 404
A 404 on a specific filing can mean either that it does not exist, or that it exists but is
newer than your plan's freshness window allows. These are deliberately indistinguishable —
otherwise a delayed plan could confirm that a filing had landed and read its timing, which is
exactly the real-time signal the plan does not include.
Retrying
429— wait forRetry-After, then retry. Safe.500— retry with backoff. All endpoints areGETand idempotent.400,401,403,404,405— do not retry. Nothing will change until you change the request.
Error reference
Each heading below is the target of the type URL on that error.
bad-request — 400
The request could not be processed as sent. The most common cause is reusing a pagination cursor after changing a filter; see pagination. Do not retry without changing the request.
invalid-request — 400
A parameter failed validation. The errors array names each offending field and why it was
rejected. Fix the parameter and retry.
unauthorized — 401
The key was missing, malformed, unknown, revoked or expired. These cases are deliberately
indistinguishable — see authentication. Check that you are sending
Authorization: Bearer ck_live_… and that the key is still active on your
API Keys page.
forbidden — 403
The key is valid but is not permitted to do this. Check the scopes on the key.
quota-exceeded — 403
Your monthly quota is exhausted. Retrying will not help — that is why this is a 403 and
not a 429, and why it carries no Retry-After. Upgrade your plan, or wait for the next
billing month, which begins at midnight IST on the 1st. Check consumption at
/v1/usage.
not-found — 404
No such filing, company or article — or it exists but is newer than your plan's freshness window. The two are deliberately indistinguishable; see limits and caveats.
method-not-allowed — 405
Wrong HTTP verb. Every endpoint in this API is a GET.
rate-limit-exceeded — 429
You exceeded your per-minute rate. Honour the Retry-After header and retry — this limit
recovers on its own. See rate limits.
internal-error — 500
Our fault. The response carries a trace_id; quote it when you contact support. Retry with
backoff — every endpoint is a GET and safe to repeat.