Errors & limits

Errors & limits

Every request to the hosted service — REST or MCP — either succeeds with data or fails with a structured error envelope. Learn the envelope, the error codes, and the rate-limit semantics and you can handle every failure mode.

1. The error envelope

Every error is a JSON object with an error field that always carries a code and a message:

{
  "error": {
    "code": "invalid_input",
    "message": "expected number, received undefined at birthData.year"
  }
}

On MCP tool calls, failure is a normal result object with isError: true and the envelope under structuredContent.error. Check isError before parsing anything else — it is the only reliable success/failure signal.

2. Error codes

CodeStatusFires whenWhat to do
invalid_input400A field is missing, the wrong type, or out of range; also a method that isn't on the toolFix the payload — a field name, type, or range
invalid_birth_data400Birth-data constraints fail, e.g. a year out of the −4000..4000 rangeFix the birth data fields
unknown_tool404The tool slug doesn't exist on the REST surfaceCheck the slug against GET /v1/tools
missing_api_key401No key was sentAdd Authorization: Bearer <key> (or x-api-key)
invalid_api_key401The key is unknown, revoked, or malformedCheck the key at your account page, or create a new one
tier_denied403The method is paid-tier and your key's tier doesn't include itUpgrade the key's tier when paid tiers launch
rate_limited429Your key is over its monthly call limitWait — the response includes a reset time (below)
internal_error500The service failed while computingRetry; if it persists, report the full message

3. isError on MCP results

MCP failures look like this:

{
  "isError": true,
  "structuredContent": {
    "error": {
      "code": "internal_error",
      "message": "…"
    }
  }
}

Rules:

  1. Check isError before reading anything else. Absent or false means the call succeeded; true means read structuredContent.error.
  2. Prefer structuredContent over content[0].text when your client surfaces it — the text field is the same JSON as a string.
  3. invalid_input and invalid_birth_data are almost always caller bugs: a string timezone instead of a number, birthData nested into a flat tool, or a method that belongs to a different tool. Fix the payload, not the service.

4. Rate limits

All keys are currently issued at paid tier with full access during the beta, so the paid limit is the one to plan against today. Limits are enforced per key with a monthly window.

When your key exceeds the limit the API returns 429 with code: "rate_limited" and an X-RateLimit-Reset response header. The reset value is a Unix timestamp (seconds since the epoch) — the time when the monthly window resets and calls count again. Retry before that time, and the same 429 is the expected response.

Related