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"
}
}
code— a stable string you can switch on (the table below).message— a human-readable explanation; include it in any bug report.
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
| Code | Status | Fires when | What to do |
|---|---|---|---|
invalid_input | 400 | A field is missing, the wrong type, or out of range; also a method that isn't on the tool | Fix the payload — a field name, type, or range |
invalid_birth_data | 400 | Birth-data constraints fail, e.g. a year out of the −4000..4000 range | Fix the birth data fields |
unknown_tool | 404 | The tool slug doesn't exist on the REST surface | Check the slug against GET /v1/tools |
missing_api_key | 401 | No key was sent | Add Authorization: Bearer <key> (or x-api-key) |
invalid_api_key | 401 | The key is unknown, revoked, or malformed | Check the key at your account page, or create a new one |
tier_denied | 403 | The method is paid-tier and your key's tier doesn't include it | Upgrade the key's tier when paid tiers launch |
rate_limited | 429 | Your key is over its monthly call limit | Wait — the response includes a reset time (below) |
internal_error | 500 | The service failed while computing | Retry; 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:
- Check
isErrorbefore reading anything else. Absent orfalsemeans the call succeeded;truemeans readstructuredContent.error. - Prefer
structuredContentovercontent[0].textwhen your client surfaces it — the text field is the same JSON as a string. invalid_inputandinvalid_birth_dataare almost always caller bugs: a string timezone instead of a number,birthDatanested into a flat tool, or a method that belongs to a different tool. Fix the payload, not the service.
4. Rate limits
- Free tier: 500 calls per month.
- Paid tier: 50,000 calls per month.
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
public-connect.md— get a key and connect Claude Code, Claude Desktop, or plain REST.public-quickstart.md— first successful calls.