DOCS
Dashboardnorth_eastGet an API keyvpn_key
PAI Chat·Error codes

PAI Chat API errors

PAI Chat returns a JSON body with a message field on every error. API-key failures also include a symbolic code; validation failures include an errors array.

Response shape

Middleware and route errors return { message }; API-key authentication errors return { message, code }; schema validation failures return { message, errors }.

{
  "message": "Forbidden: API key not valid for this chatbot"
}

HTTP status + messages

HTTPMessageWhen it happens
400Organization could not be determinedx-organization-id is missing or does not match a known organization.
400Chatbot could not be determinedThe chatbot lookup failed before x-chatbot-id was resolved.
400Request validation failedThe request body or query failed schema validation; see the errors array.
401UnauthorizedNo session and no valid x-api-key were provided.
401Invalid API key / INVALID_API_KEYThe key is missing, malformed, or not recognised.
401API key is disabled / KEY_DISABLEDThe key exists but has been disabled.
401API key has expired / KEY_EXPIREDThe key has passed its expiresAt time.
403Forbidden: session not valid for this chatbotA user session is scoped to a different chatbot than the one being called.
403Forbidden: API key not valid for this organizationAn organization-scoped key was used against a different organization.
403Forbidden: API key not valid for this chatbotA chatbot-scoped key was used against a different chatbot.
403ForbiddenThe authenticated user lacks the required organization or chatbot permission.
404Chatbot not foundx-chatbot-id, the request origin, and the fallback chatbot all failed to resolve.
429RATE_LIMITEDThe API key exceeded its configured request window (default: 1000/day).
429Too Many RequestsThe IP-based request rate limit was exceeded (separate from the per-key limit).
500Internal server errorAn unhandled error occurred while processing the request.

Handling 429 rate limits

Two independent limits can return 429: the per-key daily limit (better-auth, RATE_LIMITED) and a general per-IP limit enforced on every route. Neither response currently guarantees a Retry-After header — back off with exponential delay and jitter.

JavaScript
// Exponential backoff with jitter
async function withRetry(fn, { max = 5 } = {}) {
  for (let i = 0; i < max; i++) {
    const res = await fn();
    if (res.status !== 429 && res.status < 500) return res;
    await new Promise(r => setTimeout(r, 2 ** i * 250 + Math.random() * 250));
  }
  throw new Error('retry budget exhausted');
}

Debugging checklist

  • Confirm x-api-key is set and the key is enabled in the dashboard.
  • For chatbot-scoped calls, confirm x-chatbot-id is set and matches the key's scope.
  • For organization-level calls, confirm x-organization-id matches the key's organization.
  • A 403 almost always means the key or session is valid but scoped to a different org/chatbot.
support_agent
Reporting a problem? Include the endpoint, HTTP method, timestamp, and the exact message value — there is no request id to trace by yet.