Errors: the one error shape
Every REST refusal has the same shape: a code with its HTTP status, a sentence you can show a person, a reason where one applies, and a request id for support.
Last updated 6 min read
On this page · 4 sections
Every refusal from the REST API comes back in one shape. A code keeps one HTTP status, except bad_request: 400, or 405 for a method the address does not take, or 413 for a body over 64 KB. The OAuth endpoints answer in the standard OAuth error shape, and the MCP server answers with JSON-RPC errors.
{
"error": {
"code": "conflict",
"message": "Someone changed this first. Read it again, then retry.",
"reason": "owner_moved",
"request_id": "3d9a6c1e-8f42-4b07-9e5d-2c7a1f4b6e93"
}
}- code: what went wrong, one of the codes below.
- message: one sentence written for a person. It never carries database text, so you can show it as it is.
- reason: a narrower reason beside some refusals, or null. Your code can branch on it.
- request_id: quote it when you contact support.
Every code and status
| Status | Code | What it means |
|---|---|---|
| 400 | bad_request | The request was not in the expected shape. |
| 401 | unauthorized | This token was not accepted. |
| 403 | not_allowed, frozen, module_off | This agent is not allowed to do that. This workspace is read only right now, so nothing can be changed. The API is not switched on for this workspace. |
| 404 | not_found | Nothing was found with that id, or this agent cannot see it. |
| 405 | bad_request (method_not_allowed) | That address does not accept this method. The Allow header lists the ones it does. |
| 409 | conflict | Someone changed this first. Read it again, then retry. |
| 413 | bad_request (body_too_large) | The request body is larger than 64 KB. |
| 429 | rate_limited, send_capped | Too many requests from this token. Wait, then try again. This token has sent its limit of customer emails for now. Try again later. |
| 503 | degraded | Current is busy. Try again in a minute. |
What to do
| When you see | Do this |
|---|---|
| 401 unauthorized | Check the key, its expiry and its allowed addresses. A key from outside its allowlist gets this same answer. |
| 403 not_allowed | The agent's role does not allow it. Give the agent a role that does. |
| 403 module_off or frozen | The API, or the workspace, is switched off or paused. Nothing to retry until a tenant admin changes it. |
| 404 not_found | The record does not exist, this agent cannot see it, the key lacks the scope, or writes are switched off. These answers are the same on purpose. |
| 409 conflict | Someone changed it first, or a request_id was reused with different details. Read it again, then retry with a new request_id. |
| 429 rate_limited | Wait for the seconds in Retry-After, then try once more (see Limits). |
| 503 degraded | Current is busy. Try again in a minute. |
| 504 degraded | Current took longer than 90 seconds to start answering, so the API's edge stopped waiting. Try again in a minute. |
Every reason
| Reason | What it means |
|---|---|
| request_id_missing | Send a request_id (a uuid you mint) with every change. |
| request_id_reused | That request_id was already used for a different change. Mint a new one. |
| in_progress | That request is still being worked on. Wait a moment, then send it again. |
| body_length | The text must be 1 to 15,000 characters. |
| nothing_to_change | Give a status, a priority or both. |
| use_close | Close a ticket with tickets_close, not by setting its status. |
| waiting_reason_needs_waiting | A waiting reason goes only beside a waiting status. |
| finished | That ticket is resolved or closed. Take the close back first, or ask a person to reopen it. |
| changed | The ticket changed since you read it. Read it again, then retry. |
| owner_moved | Someone changed who has this ticket since you read it, so nothing moved. |
| assignee_not_allowed | That person cannot own desk tickets here. Pick a desk staff member, yourself or nobody. |
| already_closed | That ticket is already closed. |
| not_holder | Only the ticket's owner, the person who raised it, or a desk manager can take a close back. |
| not_finished | That ticket is not resolved or closed, so there is nothing to take back. |
| not_closed | That ticket is not closed, so it cannot go back to resolved. |
| merged | That ticket was merged into another one, so its close can't be taken back here. A person can undo the merge. |
| undo_window_passed | The 24 hours to take this back have passed. A person can reopen the ticket. |
| resolved_needs_person | This workspace surveys after every close, so a person takes a close back to resolved. |
| resolved_has_ask | The customer's "Did this fix it?" question would come back, so a person takes this close back to resolved. Take it back to open instead. |
| same_ticket | Name two different tickets. |
| not_native | Only tickets made in Current can be merged. |
| no_company | Both tickets need a company before they can be merged. |
| different_company | The two tickets are on different companies, so they cannot be merged. |
| merge_closed | The ticket to fold in is already closed. |
| keep_closed | The ticket to keep is closed. |
| merge_already_merged | The ticket to fold in was already merged. |
| keep_already_merged | The ticket to keep was already merged into another ticket. |
| psa_in_flight | The ticket to fold in is being sent to the PSA right now. Try again in a minute. |
| time_in_flight | Time on the ticket to fold in is being sent to the PSA right now. Try again in a minute. |
| psa_twin_pending | The ticket to fold in is still being copied to the PSA. Try again shortly. |
| keep_not_in_psa | Work on the ticket to fold in is waiting for the PSA, and the ticket to keep is not in the PSA. Keep the other ticket instead. |
| not_allowed | This agent's role cannot do that. |
| not_desk_staff | That person cannot own desk tickets here. |
| work_columns | This agent's role cannot change that field. |
| stale_owner | Someone changed who has this ticket since you read it, so nothing moved. |
| cursor_invalid | That cursor was not issued for this list or this workspace. Start again from the first page. |
| secret_not_accepted | Current makes every key and secret itself. Remove the field that carries one. |
| not_json | The request body must be a JSON object. |
| body_too_large | The request body is larger than 64 KB. |
| method_not_allowed | That address does not accept this method. The Allow header lists the ones it does. |
| bad_arguments | One of the fields is missing or not in the expected shape. The message names it. |
What does a Current API error look like?
A REST refusal is always the same shape: error with code, message, reason and request_id. Each code keeps one HTTP status: 400 bad_request (405 for a wrong method, 413 for a body over 64 KB), 401 unauthorized, 403 not_allowed, module_off or frozen, 404 not_found, 409 conflict, 429 rate_limited, 503 degraded. The OAuth endpoints use the standard OAuth error shape and the MCP server uses JSON-RPC errors. See the current-api-errors article. The Current API is not open yet.
Why does the Current API answer 404 for a ticket I know exists?
Because the agent's role cannot see it. The API answers not_found for a record that does not exist and for one the agent may not see, so a key can never learn what lies outside its reach. The Current API is not open yet.
