Skip to main content

Error Codes

Every error response follows the same format. Parse it once, handle it everywhere.

Response format

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or expired API key",
    "request_id": "req_a1b2c3d4"
  }
}
The code field is a machine-readable string. The message field is human-readable. The request_id maps to the audit trail.

Status codes

StatusCodeDescription
400BAD_REQUESTMalformed JSON, missing required fields
401UNAUTHORIZEDInvalid API key, expired key, revoked key
403FORBIDDENInsufficient scope, plan limit reached
404NOT_FOUNDResource doesn’t exist
429RATE_LIMITEDToo many requests. Check Retry-After header
500INTERNAL_ERRORSomething went wrong on our end. Contact support
502BAD_GATEWAYUpstream AI provider returned an error
503SERVICE_UNAVAILABLEGateway overloaded or coordinator unreachable

Handling 429 Rate Limited

When you hit rate limits, the response includes headers telling you when to retry:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1710360000
HeaderWhat it means
Retry-AfterSeconds to wait before retrying
X-RateLimit-LimitMax requests per window
X-RateLimit-RemainingRequests left in current window
X-RateLimit-ResetUnix timestamp when the window resets
Back off for the number of seconds in Retry-After. Don’t retry in a tight loop.

Handling errors in code

const response = await fetch("https://gateway.takumo.io/v1/shield", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${apiKey}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ content: code })
});

if (!response.ok) {
  const { error } = await response.json();

  switch (error.code) {
    case "UNAUTHORIZED":
      // Key is bad. Check config.
      break;
    case "RATE_LIMITED":
      // Wait and retry.
      const retryAfter = response.headers.get("Retry-After");
      await sleep(Number(retryAfter) * 1000);
      break;
    case "BAD_GATEWAY":
      // AI provider issue, not Takumo. Check provider status.
      break;
    default:
      console.error(`Takumo error: ${error.code} - ${error.message}`);
  }
}
Always include the request_id when contacting support. It maps directly to the audit trail.