Errors
Error format, HTTP status codes, and the entitlement reason codes.
Errors return a JSON body with an error message and an appropriate HTTP status.
{ "error": "a valid API key is required for this endpoint" }#Status codes
| Status | Meaning | Typical body | Fix |
|---|---|---|---|
400 | Malformed request | { "error": "missing stripe-signature" } | Check the body, query params, and headers |
401 | Missing or invalid API key | { "error": "a valid API key is required for this endpoint" } | Send a valid x-api-key (Authentication) |
402 | Plan limit reached (metered call) | { "error": "USAGE_LIMIT_REACHED", "entitlement": { ... } } | Enable metered billing or raise limits (Billing) |
404 | Unknown route or entity | { "error": "not found" } or { "error": "unknown product" } | Check the path or slug |
429 | Anonymous trial limit reached | { "error": "anonymous trial limit reached (8/hour). Get a free API key for more." } | Get a free key (Rate Limits) |
500 | Internal error | { "error": "..." } | Retry with backoff; report if it persists |
503 | Billing not configured | { "error": "..." } | Only on checkout or portal when Stripe is not set up |
#Entitlement reason codes
A 402 on a metered primitive carries an entitlement object with a reason. The reason
tells you why the call was blocked.
| Reason | Meaning |
|---|---|
OK | Allowed. Not an error. |
USAGE_LIMIT_REACHED | The plan's included quantity for this event type is used up and overage is off |
HARD_LIMIT_REACHED | A hard usage cap on this event type was reached |
SPEND_LIMIT_REACHED | Your monthly spend hard limit was reached (Limits) |
The entitlement object also reports included, used, remaining, and meteredEnabled,
so an agent can decide whether to enable billing or wait for the next period.
#MCP errors
The hosted MCP speaks JSON-RPC. A missing or invalid key returns:
{ "jsonrpc": "2.0", "error": { "code": -32001, "message": "a valid StackResolve API key is required (x-api-key header)" }, "id": null }A blocked metered tool call returns a tool error whose message names the reason and your used-versus-included counts.
#Resilience
The research primitives are built to degrade, not fail. If a scrape or a single source
fails, the call still returns the facts it could gather rather than erroring out, and the
freshness block shows what it could and could not refresh.