Effective error handling is essential for ensuring a smooth developer experience and building robust applications. This guide provides an overview of the errors you may encounter when interacting with IXO API.
Client Errors (4xx)
Errors that occur due to client-side issues.
- 400 Bad Request: Malformed request or invalid parameters
- 401 Unauthorized: Authentication required or failed
- 403 Forbidden: Insufficient permissions
- 404 Not Found: Resource not found
- 429 Too Many Requests: Rate limit exceeded
Server Errors (5xx)
Errors that occur due to server-side issues.
- 500 Internal Server Error: Unexpected server condition
- 502 Bad Gateway: Invalid response from upstream
- 503 Service Unavailable: Server temporarily unable to handle request
Error Response Structure
IXO API provides informative error responses in JSON format:
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"details": [
{
"field": "entityId",
"error": "Missing required parameter"
}
]
}
}Response Fields
- code: HTTP status code
- message: Human-readable error description
- details: Additional error information
Docs API errors
The /api/* routes on docs.ixo.world answer with JSON, never an HTML page, so an agent can parse the failure without scraping. The envelope extends the structure above with a stable machine-readable code and a resolution hint:
/mcp speaks JSON-RPC 2.0 and uses a different error shape — see MCP errors below. Do not match on error.status there.
{
"error": {
"code": 404,
"status": "NOT_FOUND",
"message": "No API route at /api/unknown.",
"hint": "Available routes: /api/assistant/session, /api/assistant/message, /api/assistant/abort, /api/try.",
"documentation": "https://docs.ixo.world/api-reference/errors"
}
}Envelope fields
| Field | Type | Meaning |
|---|---|---|
code | integer | The HTTP status code, repeated in the body. |
status | string | Stable machine-readable code. Match on this, not on message. |
message | string | What went wrong, in one sentence. |
hint | string | How to resolve it. Present whenever a resolution exists. |
documentation | string | URL of the page describing this class of error. |
Status codes
BAD_REQUEST · UNAUTHENTICATED · PERMISSION_DENIED · NOT_FOUND · METHOD_NOT_ALLOWED · PAYLOAD_TOO_LARGE · RESOURCE_EXHAUSTED · BAD_GATEWAY · UNAVAILABLE
Rate limits
Every /api/* and /mcp response carries RFC 9331 rate-limit headers, so an agent can pace itself from the published quota:
| Header | Example | Sent on | Meaning |
|---|---|---|---|
RateLimit-Policy | "mcp";q=120;w=60 | every response | The quota (q) per window of w seconds. |
RateLimit | "mcp";r=0;t=60 | 429 only | Requests remaining (r) and seconds until the window resets (t). |
Retry-After | 60 | 429 only | Seconds to wait before retrying. |
Current quotas: 120 requests per minute per IP on /mcp (policy name mcp), 10 per minute per IP on /api/* (policy name api).
RateLimit is sent only on a 429. The edge limiter reports allow/deny, not a live counter, so a remaining count is published only when it is known to be exactly 0 — an invented number would be worse than none. Pace from RateLimit-Policy.
A 429 on /api/* uses the envelope above with status: "RESOURCE_EXHAUSTED"; on /mcp it uses the same HTTP envelope, because the limiter runs before the JSON-RPC layer.
MCP errors
/mcp implements JSON-RPC 2.0, so protocol failures use the JSON-RPC error object rather than the envelope above — there is no status, hint, or documentation field:
{
"jsonrpc": "2.0",
"id": 1,
"error": { "code": -32601, "message": "Method not found: tools/invoke" }
}| JSON-RPC code | Meaning |
|---|---|
-32700 | Parse error — the body was not valid JSON. |
-32600 | Invalid request — not a JSON-RPC 2.0 envelope. |
-32601 | Method not found. |
-32602 | Invalid params, including an unknown tool name. |
A tool that fails does not produce a JSON-RPC error. It returns a normal result with isError: true and the reason as text content, which is how MCP reports tool-level failures:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [{ "type": "text", "text": "No page at /nope. Use search_docs to find the right URL." }],
"isError": true
}
}Transport-level failures before the JSON-RPC layer — a 429 from the rate limiter, or a GET/DELETE on /mcp when no stream is available — use HTTP status codes with the JSON envelope documented above.
A path that does not exist returns a real HTTP 404, never a 200 with an app shell. Clients that do not ask for HTML get a short Markdown body listing the sitemap, llms.txt, the MCP server, and the docs index, so an agent can recover in one more request.
Best Practices
Use HTTP Status Codes
Rely on HTTP status codes to understand error types and handle them appropriately.
Implement Retry Logic
For 5xx errors, implement retry logic with exponential backoff.
Validate Input
Validate all input parameters before sending requests to minimize 400 errors.
Respect Rate Limits
Monitor and respect rate limits to avoid 429 errors.
Common Error Solutions
Solution: Double-check request syntax and parameters
Solution: Verify access token and re-authenticate if needed
Solution: Verify user permissions and roles
Solution: Retry after delay or contact support
Always log and monitor errors to identify patterns and improve error handling in your applications.