Errors
The API uses standard HTTP status codes. Error bodies are JSON with a detail field — a string for most errors, or FastAPI's structured validation-error array for 422s.
| Status | Meaning | What to do |
|---|---|---|
400 | Chat completions request is missing return_markdown. It has no default — every request must explicitly choose true or false. | Add return_markdown (boolean) to the request body. See Quickstart. |
401 | Missing or invalid credential — X-API-Key for chat completions/transcription, or the bearer token for the Genesys connector. | Check the key is present, unrevoked, and sent as X-API-Key, not Authorization (Genesys is the one exception — see Authentication). |
402 | Free-tier quota exhausted — chat completions' token pool or transcription's 5-minute lifetime pool, independently. | Upgrade the org's plan, or (chat only) wait for the daily reset (midnight UTC) — transcription's free pool doesn't refill. See Rate Limits. |
422 | Request body failed validation — e.g. temperature out of [0, 2], messages missing or malformed, user over 256 characters, an unrecognized actor on a Genesys conversation turn. | Fix the field(s) named in detail; each entry includes the offending field path and the constraint that failed. |
429 | Too many requests for your plan's per-minute limit. Chat completions and transcription each have their own window on the same key. | Back off and retry after the number of seconds in the Retry-After header. See Rate Limits. |
502 | The upstream model failed to generate a response. | Safe to retry; if it persists, contact support. |
503 | Either your org's MCP integration is configured but unreachable (chat completions), or the transcription service itself couldn't be reached. | Safe to retry; if it persists, contact support — this is on r-mad.ai's (or your MCP server's) side, not your request. |
Example: validation error (422)
{
"detail": [
{
"type": "less_than_equal",
"loc": ["body", "temperature"],
"msg": "Input should be less than or equal to 2",
"input": 3.5
}
]
}
Example: rate limited (429)
{"detail": "Rate limit exceeded: max 60 requests per 60s"}
with a Retry-After header giving the number of seconds to wait.
There is no 403 from this API — an API key either authenticates as a valid org (in which case every request it sends is authorized for that org) or it doesn't (401). Role-based permissions (Admin/Member/Viewer) only apply to the dashboard, not to API key requests.