Errors

Every refusal has the same shape and a stable code. Program against the code, never against the message.

code is machine-readable and will not change within a version. message is for a human and may be reworded at any time. details carries context that differs per code and is useful while debugging, but it is not a contract to branch on. request_id also comes back as the X-Request-Id header; quote it in a support request and we can find the exact call.

{
  "error": {
    "code": "INVALID_SHARED_WITH",
    "message": "shared_with only accepts members who can sign in: emp_4b2a91",
    "request_id": "baa58c77-4b95-434d-bdbb-4ac3d04ac03b",
    "details": {
      "invalid": ["emp_4b2a91"]
    }
  }
}

Two responses do not carry this envelope

A 429 is refused at the edge before it reaches the API. And the PUT that uploads audio goes straight to storage, so a rejected signature comes back as XML. Everything else, without exception, is the shape above.

A broken request beats a missing scope

Validation runs before the scope check, so an invalid body plus a missing scope answers 400 INVALID_REQUEST and not 403 INSUFFICIENT_SCOPE. Do not conclude from a 400 that the key is fine.

Every code

32 codes, grouped by the status they arrive with.

400Something about the request is wrong

BAD_REQUEST
The request was refused and no more specific code applies.
INVALID_CURSOR
`cursor` was not produced by a previous page of this list.
INVALID_DATE
A date is not a calendar date in YYYY-MM-DD form.
INVALID_DATE_RANGE
`date_from` lies after `date_to`.
INVALID_EMAIL
The email address is not a valid address.
INVALID_EXTERNAL_ID
`external_id` is empty or longer than allowed.
INVALID_LIMIT
`limit` is not a whole number within the allowed range.
INVALID_REQUEST
The request body or the combination of query parameters is not valid. `details.fields` names the offending fields where the body is at fault.
INVALID_SHARED_WITH
`shared_with` names members who cannot be shared with, because they have no account or are an integration. `details.invalid` lists them.
INVALID_TIME
`time` is not a time of day in HH:MM form.

401The key did not authenticate

UNAUTHENTICATED
The Authorization header is missing, malformed, or the key is unknown, expired or revoked.

402Quota is spent

QUOTA_EXHAUSTED
The organisation's quota for this period is spent. `details.next_reset_at` says when it replenishes.
TRANSCRIBE_QUOTA_EXHAUSTED
Not enough transcription credit left for this recording. `details.next_reset_at` says when the quota replenishes.

403Authenticated, but not allowed

API_ACCESS_DISABLED
The organisation does not have API access, or the integration behind this key is no longer active.
FORBIDDEN
The action is not allowed for this caller.
INSUFFICIENT_SCOPE
The key is valid but does not carry the scope this endpoint requires.
IP_NOT_ALLOWED
The key has an IP allowlist and this caller's address is not on it.
ORGANISATION_EXPIRED
The organisation's access has expired.
ORGANISATION_SUSPENDED
The organisation is blocked.
PERSONAL_API_KEYS_DISABLED
The organisation does not have personal API keys enabled, so this personal key cannot be used.

404Absent, or invisible to this integration

NOT_FOUND
No such resource, or it is not visible to this integration. A private meeting of another member is answered as absent rather than as forbidden, so its existence is not revealed.

409The resource is not in a state that allows this

AUDIO_ALREADY_PRESENT
This meeting already has audio. A recording is uploaded once; create a new meeting to start over.
CONFLICT
The resource is not in a state that allows this action.
EMAIL_TAKEN
Another member already uses this address. `details` names the member that holds it.
EXTERNAL_ID_TAKEN
Another meeting in this organisation already carries this `external_id`.
MEMBER_LIMIT_EXCEEDED
The organisation has reached the maximum number of member records.
MINUTES_NOT_READY
The minutes have not been generated yet. Poll the meeting until its status says so.
NOT_READY
The content is not available yet. Try again later.
PARTICIPANTS_LOCKED
Participants steer transcription, so they can only be changed while the meeting has no audio yet.
TRANSCRIPT_NOT_READY
Transcription has not finished. Poll the meeting until its status says so.
VOCABULARY_FULL
The vocabulary already holds the maximum number of terms.

500Ours to fix

INTERNAL_ERROR
Something went wrong on our side. The response carries a `request_id`; quote it in a support ticket.