Error codes
A failed request returns an HTTP status and this body:
{ "error": { "code": "INSUFFICIENT_SCOPE", "message": "api key requires scope 'write'" } }message is a developer-facing description and may change. Codes do not change, so branch on code. Some errors carry extra fields (for example unknown_keys on INVALID_LABELS).
| Code | Status | Meaning and what to do |
|---|---|---|
UNAUTHORIZED |
401 | The key is missing or wrong. Calling a request that is not open to API keys with a key also returns this. |
API_KEY_REVOKED |
401 | The key was revoked. Create a new one. |
API_KEY_EXPIRED |
401 | The key has expired. Create a new one. |
AGENT_KEY_REVOKED |
401 | The AI agent key was revoked. Check the agent’s status with the operator. |
TOKEN_REVOKED |
401 | The token belongs to a CLI or AI coding tool connection that was disconnected. Sign in again (reconnect) from that tool. |
TOKEN_EXPIRED |
401 | The CLI or AI coding tool token has expired. The CLI and AI coding tools refresh it on their own — when calling directly, get a new token with the refresh token. |
FORBIDDEN |
403 | Not allowed. Also returned when the person who created the key has left the workspace. |
ACCOUNT_SUSPENDED |
403 | The account of the person who created the key is suspended. |
ACCOUNT_DELETION_PENDING |
403 | The account of the person who created the key is scheduled for deletion (grace period). The key works again if that person signs in and cancels the deletion. |
ACCOUNT_DELETED |
403 | The account of the person who created the key has been deleted. The key will not work again — have someone else create a new key. |
INSUFFICIENT_SCOPE |
403 | The key lacks the scope this request needs (read, write, or metrics:ingest). |
WORKSPACE_MISMATCH |
403 | The x-workspace-slug header does not match the key’s workspace. Drop the header or fix it. |
DEV_TOOLS_DISABLED_FOR_WORKSPACE |
403 | A workspace admin turned off developer tool connections (CLI and AI coding tools) for this workspace, or disconnected this CLI sign-in from this workspace. REST requests made with a personal key (gtk_) keep working. |
WRITER_ROLE_REQUIRED |
403 | The person who created the key (for an agent key, the agent) is now a viewer and cannot write. |
AGENT_NOT_ASSIGNED |
403 | This issue is not assigned to this AI agent. Agent keys write only to assigned issues; reads still work. |
WORKSPACE_SUSPENDED_FULL |
403 | The workspace is suspended; both reads and writes are blocked. Contact your workspace admin. |
WORKSPACE_SUSPENDED_READ_ONLY |
403 | The workspace is suspended in read-only mode. Reads work; writes are blocked. |
SYSTEM_SOURCE_FORBIDDEN |
403 | A key cannot store values with source: "system_etl". Leave source out. |
VALIDATION |
400 | The body or query does not match the expected shape. Unknown fields also return this. |
WORKSPACE_REQUIRED |
400 | A CLI sign-in token works across workspaces, so every request must pick one. Send the x-workspace-slug header (-W <slug> in the CLI). |
INVALID_LABELS |
400 | labels contains a dimension the metric does not define. Check unknown_keys. |
METRIC_LABEL_EMPTY |
400 | A value in labels is empty or only whitespace. Fill in the dimensions listed in empty_keys, or leave those keys out. |
REF_NOT_IN_WORKSPACE |
400 | A reference such as a team or project belongs to another workspace (field names it). |
NOT_IN_WORKSPACE |
400 | A label you passed when creating an issue (label_ids) is not in this workspace (field names the field). If any one is missing, the issue is not created. |
LABEL_IS_GROUP |
400 | label_ids contains a label group itself. Groups can’t be applied — pick a label inside the group. |
LABEL_GROUP_EXCLUSIVE |
400 | label_ids contains more than one label from the same label group. Pick one per group (group_id names the group). |
INVALID_PARENT |
400 | The parent issue (parent_id) cannot go there (another team, or an issue that cannot have a parent). Check reason. |
CYCLE_IN_OTHER_TEAM |
400 | The cycle belongs to a different team than the issue. Pick a cycle of the issue’s team. |
MILESTONE_NOT_IN_PROJECT |
400 | The milestone does not belong to the issue’s project (including when the issue has no project). Set the issue’s project and pick one of its milestones. Changing only the project clears a milestone that no longer fits. |
STATUS_IN_OTHER_TEAM |
400 | The status is dedicated to a different team (field: "status_id"). Pick a shared status or one of the issue’s team. |
STATUS_ARCHIVED |
400 | The status was deleted (archived) (field: "status_id"). Pick a usable status again with GET /api/v1/workflow_states?available_for_team=<team_id>. |
INVALID_STATUS_MAPPING |
400 | A status in the status_map you sent with a restore is not usable by that team (another team’s only · deleted · outside this workspace), or a key is not a status of this workspace (field: "status_map" · status_ids). The issue was not changed. Pick again from the candidates of STATUS_MAPPING_REQUIRED. |
AI_AGENT_REVOKED |
400 | A revoked AI agent cannot be the assignee. |
PRECONDITION_REQUIRED |
412 | The PATCH body has no expected_version. Read the issue and send its version. |
NOT_FOUND |
404 | The target does not exist or this key cannot see it. The two are not distinguished. |
VERSION_CONFLICT |
409 | Someone changed it after you read it. Read it again and send the new version. |
STATUS_MAPPING_REQUIRED |
409 | The status in the version you are restoring (or of a sub-issue that moves back with it) was deleted (archived) or is not usable by the resulting team. The issue was not changed. required lists those statuses (archived: true = deleted), candidates the statuses you can pick and suggested same-name matches. Pick one per source status and send the request again with status_map ({ source status_id: target status_id }). |
NO_TARGET_STATES |
422 | A mapping is needed but the resulting team has no status to pick. Create statuses in the workflow settings first. |
CONCURRENT_MOVE |
409 | The request overlapped with another change being processed. Send the same request again shortly. |
METRIC_ARCHIVED |
409 | Archived metrics do not accept values. Unarchive it on the Metrics screen. |
SYSTEM_METRIC_READONLY |
409 | The value is computed by the system and cannot be overwritten. |
LOCK_TIMEOUT |
503 | Another operation on the same target overlapped. Retry shortly. |
STATEMENT_TIMEOUT |
503 | The query took too long and was stopped. Narrow it (limit, filters). |
Rate limited (429)
Section titled “Rate limited (429)”Going over a limit returns 429. That response may not carry a code in the format above, so judge by the status and wait for the Retry-After header (seconds) before retrying. The limits are listed under API keys.