Errors
Every error is RFC 9457 application/problem+json:
{
"type": "https://docs.akteora.com/errors/validation_failed",
"title": "Validation failed",
"status": 422,
"detail": "title: Too small: expected string to have >=1 characters",
"request_id": "01K5C2B7N4Q8S2V6X0Z4B8D2F6",
"errors": [{ "field": "title", "code": "too_small", "message": "Too small: expected string to have >=1 characters" }]
}
- Branch on
type(orstatus), never ontitleordetail: those are for people and are reworded.typeis stable, and each one has a section below. - Show
detailto a person as it is. It says what went wrong and, where there is one, what to do. - Quote
request_idwhen you contact support. It identifies the exact request in our logs. It is also in theX-Request-Idheader of every response, successful or not.
4xx means the request needs changing — except 429, which means later. 5xx means the problem
is ours: retry with backoff, with an Idempotency-Key on a POST (idempotency).
| Status | type |
|
|---|---|---|
| 401 | unauthenticated |
no key or session, or a key that is not valid |
| 402 | plan_limit_exceeded |
the plan does not cover it |
| 403 | insufficient_scope |
the key lacks the route's scope |
| 403 | forbidden |
not with this role, or not with a key at all |
| 404 | not_found |
no such thing — or not yours |
| 409 | conflict |
clashes with something that exists |
| 409 | idempotency_key_reused |
a key reused with another body |
| 409 | billing_unavailable |
payments are not taken yet |
| 410 | link_closed |
a collect link no longer takes testimonials |
| 410 | invitation_expired |
an invitation past its date |
| 422 | validation_failed |
the body or query is not acceptable |
| 422 | transcript_correction_too_large |
a correction rewrites too much |
| 429 | rate_limited |
too many requests; wait and retry |
| 500 | internal_error |
something failed on our side |
| 502 | billing_provider_error |
the payment provider failed |
unauthenticated
401. There is no API key or session, or the key is not valid, was revoked, or has expired —
detail says which. See authentication.
insufficient_scope
403. The API key does not have the scope this route needs. required_scope names it:
{ "type": "https://docs.akteora.com/errors/insufficient_scope", "status": 403, "required_scope": "links:write", "…": "…" }
Keys cannot be changed: make a key with the scope, then revoke the old one.
forbidden
403. Either a signed-in member's role does not allow this (an editor revoking an API key), or the
route is not available to API keys at all (billing, members, API keys). detail says which.
not_found
404. Nothing with that id exists in your organisation — including when it exists in another
organisation, or in the other mode (test or live). The API never says whether an id belongs to
someone else.
conflict
409. The request clashes with something that already exists or with the state a thing is in: a
brand slug already taken, a public wall address already someone's, a reel already rendering, a
webhook endpoint that is switched off. detail says which and what to do.
idempotency_key_reused
409. The Idempotency-Key was already used with a different body, or its first request is still
running. Use a new key for a new request; wait and retry for the second case.
plan_limit_exceeded
402. The organisation's plan does not include this, or this month's allowance is used up. limit
says which limit, what the plan allows, and the plan that raises it, with a link to upgrade:
{
"type": "https://docs.akteora.com/errors/plan_limit_exceeded",
"status": 402,
"limit": { "name": "api_access", "plan": "starter", "allowed": 0, "requested": 1, "upgrade_to": "core", "upgrade_url": "https://app.akteora.com/billing?upgrade=core" },
"…": "…"
}
In test mode, upgrade_to is null when test mode's own allowance is what stopped it. See
plans and billing.
billing_unavailable
409. Checkout or the billing portal was asked for while payments are not taken. Nothing was
charged.
billing_provider_error
502. The payment provider did not complete the request. Nothing was charged. Try again in a
minute.
link_closed
410, from the capture routes. The collect link is inactive, expired, at its limit, or paused, and
reason says which. A respondent sees a friendly page; this is for code that opens links itself.
invitation_expired
410. An invitation to join an organisation passed its date. Ask for a new one.
invitation_already_accepted
409. The invitation has already been used.
invitation_email_mismatch
409. The invitation was sent to another address. Sign in as that address to accept it.
validation_failed
422. The body or query string does not match the route's schema, or asks for something the
resource's state does not allow. errors lists each field that failed, with a machine-readable
code and a sentence. The API reference shows every field's rules.
transcript_correction_too_large
422. A transcript correction changes more than fixing mistranscribed words needs. A respondent's
words are theirs: a correction may change up to a quarter of the original's words.
challenge_failed
403, from the capture routes. The anti-abuse check on a public collect link failed. The capture
page shows the check again.
webhook_signature_invalid
401, on Akteora's own inbound billing webhook. It never concerns your integration.
rate_limited
429. Too many requests. Retry-After says how many seconds to wait. See
rate limits.
internal_error
500. Something failed on our side; we are alerted. Retry with backoff, and quote the
request_id if it persists.