Every error — from auth failures to validation errors to 429s — follows the same JSON shape. Client code can pattern-match on error_code rather than parsing HTTP status alone.
"error" : " short_error_slug " ,
"error_code" : " specific_machine_readable_code " ,
"message" : " Human-readable description of what went wrong. " ,
"field" : " optional, present on validation errors "
error — short category slug (unauthorized, not_found, validation_error, rate_limit_exceeded, server_error).
error_code — machine-readable code for programmatic handling. Stable across versions.
message — human-readable description. Safe to show to developers; not intended for end users.
details — optional context. Present on validation errors (offending field, received value) and rate-limit errors (limit, reset time).
Status Category Common causes 400 Validation error Invalid query parameter, malformed date, unknown ticker, per_page out of range 401 Unauthorized Missing API key, invalid key, revoked key 403 Forbidden Account suspended, key disabled 404 Not found No data for the requested ticker / CBSA / FIPS / industry code 422 Unprocessable entity Semantic validation failure (e.g., date range outside covered period) 429 Rate limited Daily or burst cap exceeded — see Rate limits 500 Server error Something broke on our side. Transient — retry with backoff. Report persistent 500s to support@thesma.dev with the response body. 503 Service unavailable Upstream data source (SEC, Census, BLS, SBA) is temporarily unreachable. Transient.
error_codeFix missing_api_keyPass the key via X-API-Key or Authorization: Bearer header invalid_api_keyKey does not exist or has been revoked. Generate a new key in the portal. account_suspendedContact support — account is suspended
error_codeFix invalid_parameterCheck the details.field — parameter value is malformed or out of range unknown_tickerTicker not in the SEC EDGAR universe. See SEC EDGAR coverage . unknown_cbsaCBSA code not recognised. See US Census coverage . date_out_of_rangeRequested date is outside the dataset’s covered period
error_codeFix daily_limit_exceededWait until midnight UTC or upgrade tier. See Rate limits . burst_limit_exceededWait 1 second and retry. Usually means you’re paginating too fast.
error_codeFix internal_errorRetry with exponential backoff. Report persistent cases. upstream_unavailableUpstream data source is down. Retry later.
Even on 500s the response is JSON with the above shape — the API never returns a bare HTML error page. If you get one, it’s from a layer in front of the API (your proxy, a load balancer, a caching CDN) and worth investigating there.
4xx are your problem — don’t retry unless the cause is transient (e.g., 429).
5xx are our problem — retry with exponential backoff (the Python SDK does this automatically).
429 — respect Retry-After and retry after the specified number of seconds.