Skip to main content

Error Codes

Every error response from the Roam developer API includes a machine-readable error code. Branch on the code rather than parsing the human-readable message.

Response shape (v0 / Alpha API)

On /v0/... paths the human-readable sentence stays in error, and the catalog code is additive in code:

{
"error": "The bearer token is unknown, malformed, or expired; obtain a new token.",
"code": "invalid_token"
}

Clients that only read error continue to work. Prefer branching on code.

v1 shape

On /v1/... paths the body is {"ok": false, "error": "<code>"} — the catalog code is the value of error (there is no separate code field). Full details and success-envelope rules: Responses and Errors. The catalog below is shared across v0 and v1.

HTTP status codes

StatusMeaning
400 Bad RequestInvalid request parameters or body
401 UnauthorizedMissing or invalid authentication
403 ForbiddenValid auth but insufficient access or scope
404 Not FoundResource does not exist (or is invisible to the caller)
405 Method Not AllowedHTTP method not supported
408 Request TimeoutServer timed out reading the request
409 ConflictConflicts with current resource state
410 GoneEndpoint has been removed
413 Payload Too LargeRequest body or message text too large
415 Unsupported Media TypeContent-Type not supported
429 Too Many RequestsRate limit exceeded
500 Internal Server ErrorUnexpected server failure; retrying may succeed
501 Not ImplementedOperation not supported for the given input
504 Gateway TimeoutTimed out waiting on an upstream service

Some codes can appear with more than one status (for example a *_not_found code on a 400 when a referenced resource is missing). Always check both the status and the code field.

Catalog

Codes use Slack-style snake_case spellings where there is a well-known equivalent (ratelimited, not_authed, msg_too_long, …).

Generic (by status class)

CodeTypical statusDescription
invalid_arguments400One or more request arguments are invalid or malformed
invalid_auth401Authentication failed (generic)
access_denied403Caller is not permitted to perform this action
not_found404Resource could not be found (generic)
method_not_allowed405HTTP method not supported
request_timeout408Server timed out reading the request
conflict409Conflicts with current resource state
method_deprecated410Endpoint removed; see docs for replacement
request_too_large413Request payload exceeds allowed size
invalid_content_type415Content-Type not supported; use application/json
ratelimited429Rate limit exceeded; retry after a delay
internal_error500Unexpected server-side failure; retrying may succeed
not_implemented501Operation not supported for the given input

Request validation

CodeTypical statusDescription
invalid_json400Request body is not valid JSON
missing_parameter400A required parameter or field is missing
invalid_parameter400A parameter or field has an invalid value
invalid_cursor400Pagination cursor invalid or expired; restart without a cursor
invalid_expand400An expand= field is not recognized
cannot_unfurl_url400A requested URL is absent from the message or outside the app's registered unfurl domains

Authentication and authorization

CodeTypical statusDescription
not_authed401No bearer token was provided
invalid_token401Token unknown, malformed, or expired; obtain a new token
token_revoked401Token permanently unusable (e.g. owner archived); discard and re-authenticate — do not retry with the same token
missing_scope403Token lacks a required scope; body includes needed (any-of) and provided
access_mode_not_supported403Token access mode (personal vs organization) cannot use this endpoint
not_in_chat403Caller is not a member of the specified chat
not_in_group403Caller is not a member of the specified group
user_not_in_chat400The targeted user is not a member of the specified chat (e.g. /chat.postEphemeral to a non-member)

invalid_token and token_revoked responses also include:

WWW-Authenticate: Bearer error="invalid_token"

token_revoked vs invalid_token: both are 401, but token_revoked means the credential is permanently dead (owner archived/deleted, client archived). Do not retry with the same token — discard it and re-authenticate. See also Authentication failures.

Resource not found

CodeTypical statusDescription
chat_not_found404Chat could not be found
user_not_found404User could not be found
group_not_found404Group could not be found
meeting_not_found404Meeting could not be found
meeting_link_not_found404Meeting link could not be found
message_not_found404Message could not be found
scheduled_message_not_found404Scheduled message could not be found (or was scheduled by a different credential)
event_not_found404On-Air event could not be found
guest_not_found404On-Air guest could not be found
address_not_found404Address could not be found
lobby_not_found404Lobby could not be found
magicast_not_found404Magicast could not be found
transcript_not_found404Meeting has no transcript, or it is not yet available
recording_not_found404Recording could not be found
webhook_not_found404Webhook subscription could not be found
item_not_found404Item could not be found
asset_not_found404Asset could not be found
handle_not_found404Handle could not be found
session_not_found404Agent session could not be found (reserved)
connection_not_found404Agent connection could not be found (reserved)
file_not_found404File could not be found (reserved)
stream_not_found404Stream could not be found

Message and resource conditions

CodeTypical statusDescription
msg_too_long413Message text exceeds maximum length; truncate and retry
name_taken400A resource with that name already exists
is_archived400Target resource is archived and cannot be modified
scheduled_message_already_sent409Scheduled message was already sent (or delivery has begun) and can no longer be canceled
CodeTypical statusDescription
transcript_pending404Transcript not ready yet (meeting in progress or still processing); retry later (may include Retry-After)
transcript_unavailable404Meeting was not transcribed; stop retrying
upstream_timeout504Timed out waiting on an upstream service; retry

Client guidance

  1. Branch on code, not on free-text error strings.
  2. Treat token_revoked as terminal for that credential — discard it and run your re-auth flow.
  3. Treat transcript_unavailable as terminal for that meeting; treat transcript_pending as retryable.
  4. For ratelimited (429), honor Retry-After and use exponential backoff. See Rate Limiting.
  5. For missing_scope (403), read needed (any-of array) and provided (granted scopes, post-alias) to decide what to request on the next authorization — do not parse the human-readable message. See Responses and Errors.