MCP server docs / Limits and errors

Limits and errors

StableLast updated View as Markdown

The Queue CallBack MCP server reports a problem in one of two ways: an HTTP error before any tool runs, with a stable code in error.data.code, or a tool result with isError: true and a stable code in structuredContent.error.code. This page lists the limits, every code with its meaning and its fix, and the rules for when an agent may retry.

For AI agents: this page is also available as Markdown at https://queuecallback.com/docs/mcp/errors.md. The whole MCP documentation in one file: https://queuecallback.com/docs/llms-full.txt

Every code on this page has its own anchor, https://queuecallback.com/docs/mcp/errors#<code>, for example #mcp_disabled. Branch on the code, not on the message: messages are written for people and can change.

Limits

These are the limits of the Queue CallBack MCP server and of the Queue CallBack API behind it. The values are the current defaults, and Queue CallBack can change them. A Retry-After header or a retry_after_seconds field in an answer always wins over this table.

Limit Value Answer when exceeded
Request body 1 MiB per HTTP request HTTP 413, not a JSON-RPC body
Requests in flight per credential 8 at once for one API key, or for one person signed in from Claude or ChatGPT; the server also caps its total HTTP 429 concurrency_limited, Retry-After: 1
API requests in flight per organization 4 at once, counting every API key and connected client of the organization; a total cap also applies across the service 429 concurrency_limited, retry after 1 second
API request rate per key 120 requests per minute, bursts of 30, for one API key or one signed-in person. One tool call makes one or more API requests 429 rate_limited with Retry-After
API request rate per organization 300 requests per minute for all of its keys and signed-in people together, bursts of 60 429 rate_limited with Retry-After
Requests per client address a per-address request limit at the edge HTTP 429 rate_limited as a JSON-RPC error, Retry-After: 1
Tool time limit 30 seconds; the reporting tools 40 seconds; edit_flow_draft, publish_flow and restore_flow_version 60 seconds backend_timeout (edit_interrupted for edit_flow_draft). The change may still complete
Result size 100,000 bytes of JSON; validate_flow 200,000; get_flow, diff_flow and edit_flow_draft 300,000 A long list is halved until it fits and marked truncated; otherwise result_too_large
Items per list each list tool has a default and a maximum limit (tool reference) The result carries truncated: true and a truncation object with pointer, returned, total and note
Report date range 400 days from from to to per request date_range_too_long
One edit_flow_draft call 100 operations and 1 MiB together; 64 KiB per node config_json; node id 100 characters, name 255, condition 200, label 255 tool_refused, before anything is changed
Queue changes per organization, through API keys and connected clients: 3 at once, then 1 per minute, counted separately for callback settings changes and for voice and language changes. A settings call that changes nothing is not counted 429 queue_write_limited with Retry-After
Callbacks added with add_callback 30 per rolling hour per organization, including callbacks added in the portal. Callbacks that callers request do not count 429 manual_callback_limit_reached, with retry_after_seconds when the server can tell when a callback can be added again
Requeues with requeue_callback 5 per callback in 24 hours 409 requeue_limit_reached
Renames with set_organization_name about one every 6 seconds 429 without a code (429 without a code)
Confirm token single use, valid 10 minutes confirm_refused
Handle for a long operation 24 hours, only for the credential that received it invalid_handle

HTTP errors

An HTTP error from the Queue CallBack MCP server means the request was refused before any tool ran, so nothing changed. The exceptions are a 500, and a 502 or 504 from the edge, which can come while a tool runs. The server checks a request in this order: the Host name, the browser origin, the credential, the request limits, then the MCP transport rules. A request without a valid credential that passes the first two checks answers 401, even a GET or one with the wrong Content-Type.

Most HTTP errors carry a JSON-RPC error body with "id": null. Its error.code is -32001 for a credential problem (401 and 403) and -32000 for 429 and 5xx. error.data.code is the stable reason. error.data.retry_after_seconds is set, together with a Retry-After header, when waiting and retrying makes sense. Every answer from the server itself carries an X-Request-ID header; quote it when you contact Queue CallBack support. Answers made by the edge (the per-address 429, a 413, a 404 for an unknown path, a 502 or 504) and host_not_allowed have none.

This is the answer to a request without a valid API key or sign-in:

HTTP/1.1 401 Unauthorized
Content-Type: application/json
Cache-Control: no-store
WWW-Authenticate: Bearer resource_metadata="https://mcp.queuecallback.com/.well-known/oauth-protected-resource/mcp", error="invalid_token", scope="ivr:read reports:read callbacks:read queues:read org:read"
X-Content-Type-Options: nosniff
X-Request-ID: <request id>

{"error":{"code":-32001,"data":{"code":"invalid_token"},"message":"The credential is missing, malformed or unknown, or the API key has expired, been revoked or been suspended (a key is suspended while the admin who created it is deactivated or no longer in the organization), or the sign-in has ended. Send a valid Queue CallBack API key as Authorization: Bearer \u003ckey\u003e, or sign in again; an organization admin sees each key's status on the portal's API keys page."},"id":null,"jsonrpc":"2.0"}

\u003c and \u003e are JSON escapes for < and >. The message lists every state that gets this answer, because the server cannot tell them apart. The WWW-Authenticate header tells a client where to sign in: resource_metadata points to the discovery document, and scope names the five read scopes a sign-in asks for. Claude and ChatGPT use it to start the sign-in (OAuth sign-in). A client that sends an API key does not need it.

HTTP status JSON-RPC error.code error.data.code Meaning Fix
400 usually none (plain text) none Accept does not list both application/json and text/event-stream, the body is not valid JSON-RPC, or the MCP-Protocol-Version header names a revision the server does not support. Send Accept: application/json, text/event-stream and a supported protocol revision.
401 -32001 invalid_token For an API key: the key is missing, malformed, expired, revoked or suspended; Queue CallBack has switched API keys off for the whole service; or more than one Authorization header was sent. For a sign-in from Claude or ChatGPT: the sign-in expired or was not accepted, or the signed-in account is not an active user of a Queue CallBack organization. A bearer that is neither a Queue CallBack API key nor an accepted sign-in token gets the same answer. Apart from the case of two Authorization headers ("Send exactly one Authorization header."), the message is the same for every cause, so it does not say which check failed. A client that signs in starts a new sign-in on this answer. API key: check the key's status in the portal (Settings, then Manage API keys), check that QCB_API_KEY is set where the client runs, and send exactly one Authorization: Bearer <key> header. Sign-in: sign in again with your Queue CallBack portal account; if the client keeps asking, see sign-in fails or repeats.
403 -32001 mcp_disabled The organization's API access is off: "API and MCP access is not enabled for this organization". Every request is refused, with a valid key and after a successful sign-in alike. A tool result carries the same code when access goes off during a session; within about 30 seconds every request gets this HTTP 403. Nothing in the key or the client changes this answer. If you see it, contact Queue CallBack support (support@queuecallback.com) with the X-Request-ID.
403 -32001 insufficient_scope Sign-in only: the sign-in token grants none of the five read scopes the server asks for. WWW-Authenticate carries error="insufficient_scope" and scope with those scopes, so the client can sign in again for them. An API key never gets this answer before a tool runs. Remove the connection in the client, add it again, sign in and approve the access (sign-in fails or repeats).
403 -32001 no_organization Sign-in only: the signed-in account belongs to no Queue CallBack organization. Sign in with the account of your organization, or ask an organization admin to add you.
403 -32001 forbidden The Queue CallBack API refused the credential for another reason; the message says why. Follow the message, or contact Queue CallBack support with the X-Request-ID.
403 none (plain JSON) cross_origin_refused, in the body's error field A web page on another site sent the request from a browser. The server sends no CORS headers on /mcp. Call the server from an MCP client or from server-side code, not from a web page.
403 none (plain JSON) host_not_allowed, in the body's error field The request's Host header is not the server's name. Use https://mcp.queuecallback.com/mcp.
404 none none The path is not /mcp, /healthz or the discovery document. Send MCP requests to /mcp.
405 none (plain text) none A GET or DELETE with a valid key. The server is stateless and offers no event stream. The answer carries Allow: POST. Send every request as a POST.
413 none none The request body is larger than 1 MiB. Send less. Split a large edit_flow_draft into several calls.
415 none (plain text) none Content-Type is not application/json. Send Content-Type: application/json.
429 -32000 concurrency_limited More than 8 requests in flight for this credential, the server at its total, or the organization at its API cap while the credential was checked. Retry-After: 1. Wait, then send fewer requests in parallel.
429 -32000 rate_limited The key or the organization exceeded its request rate while the credential was checked. Wait for Retry-After.
429 -32000 rate_limited The per-address request limit at the edge in front of the server. The message reads "Too many requests from this address. Retry in a second." Retry-After: 1 and error.data.retry_after_seconds 1; no X-Request-ID. Wait at least 1 second, then send requests more slowly (Retries).
500 none (plain JSON) internal_error, in the body's error field The server failed while handling the request. Read the current state before you repeat a change. Contact Queue CallBack support with the X-Request-ID if it repeats.
502 -32000 backend_unreachable The credential could not be checked because the Queue CallBack API could not be reached. Retry-After: 5. Retry after Retry-After.
502 -32000 backend_error The credential could not be checked because the Queue CallBack API answered in an unexpected way. Retry after Retry-After, or after a few seconds when it is missing. If it repeats, contact Queue CallBack support with the X-Request-ID.
502, 504 none none The edge in front of the server answered itself, because the server is restarting or did not answer in time. The body is not JSON-RPC and there is no X-Request-ID. If the request was a tool call, the change may have run. Repeat a read after a few seconds. For a change, read the current state first (Retries).
503 -32000 auth_busy Too many credential checks are running. A tool result can carry the same code, with status 503. Retry-After: 1. Retry after 1 second.
503 -32000 backend_unavailable The Queue CallBack API is busy. Retry after Retry-After.
503 -32000 feature_unavailable The Queue CallBack API cannot check API keys right now because of a fault on the service. The message reads "API keys and delegated credentials are not enabled on this Queue CallBack server." Retry-After is usually 5 seconds. Retry after Retry-After. If it repeats, contact Queue CallBack support with the X-Request-ID.
503 -32000 authorization_server_unavailable Sign-in only: the sign-in service's signing keys could not be read, so the sign-in token could not be checked. The token may be valid. Retry-After: 5. Keep the token and retry after the wait. Do not sign in again.
503 -32000 canceled The request was canceled while it waited, usually because the client gave up. Send it again if you still need the answer.
200 (400 with protocol revision 2026-07-28) -32602 none The message reads unknown tool "<name>": the name is not a tool of the Queue CallBack MCP server at all, for example a typo or a tool of another server. A tool of the server that this credential does not see (a missing scope, the Custom IVR add-on, the IVR call reports, a server switch) is not a protocol error: the call is refused as a tool result with a code that says why (Access, scopes and switches). Fetch the tool list again and use a name from it. Check the connection with get_me (check the connection).

Tool errors

A tool error is a normal JSON-RPC result from the Queue CallBack MCP server, not a protocol error. isError is true, the text content says what happened and how to fix it, and structuredContent.error carries the details. The tool did not do what was asked. Whether anything changed depends on the code: see Retries.

The error object

This is a tool error the Queue CallBack API raised (a rate limit):

{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "isError": true,
    "content": [
      {
        "type": "text",
        "text": "HTTP 429 (rate_limited): Too many requests for this credential or organization; retry after the time in Retry-After. Too many requests; retry after 3 seconds."
      }
    ],
    "structuredContent": {
      "error": {
        "status": 429,
        "code": "rate_limited",
        "message": "Too many requests for this credential or organization; retry after the time in Retry-After",
        "retry_after_seconds": 3,
        "details": {
          "error": "Too many requests",
          "code": "rate_limited",
          "message": "Too many requests for this credential or organization; retry after the time in Retry-After",
          "retry_after_seconds": 3
        }
      }
    }
  }
}
Field of structuredContent.error Present Holds
code almost always; missing only when the API refused without a code (answers without a code) The stable reason. Branch on it
message always The reason in plain words
status most API answers The API's HTTP status, or a 502 or 504 that the server sets itself for edit_interrupted and some backend_error answers. Without status, the MCP server answered on its own: either it refused the call before any change (refused, request_refused, tool_refused, confirm_required, confirm_refused, invalid_handle, and the codes for a tool this credential does not see, such as insufficient_scope or writes_disabled), or the API's answer was missing, late or unusable (backend_timeout, backend_unreachable, backend_error, result_too_large, no_answer), and then a change may have happened
required_scope with insufficient_scope The scope the call needs
retry_after_seconds when the API sent Retry-After Seconds to wait before a retry
details API refusals with a 4xx status The API's whole answer, for example a current etag, failed_ops, a validation report, a callback_id or a retry_after time
issued_by with confirm_required The tool that issues the missing token
confirm_token_spent true when the call's confirm token is used up: on any failed call of a tool that took a confirm token, and on confirm_refused for a token an earlier call used The token cannot be sent again. Get a new one before you retry (Confirm tokens are spent on use)
next_step with confirm_token_spent on a failed call How to retry: where the new token comes from and, for requeue_callback, which idempotency_key to send

For an API refusal the text reads HTTP <status> (<code>): <message>. <hint>. For a refusal by the MCP server the text is the message. Read structuredContent.error when it is present; otherwise read the code from the text.

Access, scopes and switches

Code status Meaning Fix
insufficient_scope 403, or none The credential lacks the scope in required_scope. With status 403 the Queue CallBack API refused the call. Without status, the MCP server refused a call to a tool that this credential does not see, before anything was sent, with a message such as "This credential lacks the callbacks:dial scope that requeue_callback needs. The API key was created without it, the organization or the role the credential acts with does not allow it, or this is a sign-in, which can only read. get_me lists the scopes this credential has and its role. For more, an organization admin can create an API key with that scope; signing in again does not add scopes." required_scope can then be a scope the key holds that does not take effect in the organization, for example ivr:write where IVR flows are not edited through drafts, or pii:read for add_callback where caller data stays masked. Without an effective pii:read, it is also the answer to a search made only of digits and phone punctuation, and to the caller filter or sort=caller; a sign-in from Claude or ChatGPT never has pii:read, so it always gets this answer for those. A signed-in connection lists no tool that changes something, and a call to one by name gets this code. A User's sign-in has no ivr:read, so the IVR flow tools answer this code too. Before any tool runs, HTTP 403 with this code means a sign-in token grants none of the five read scopes (HTTP errors). Use an API key that has the scope (scopes); a sign-in cannot gain more scopes. If the key holds the scope but get_me does not list it, an organization setting keeps it from taking effect (When a scope does not take effect). For masked numbers, see caller data.
mcp_disabled 403 The organization's API access went off during the session. See mcp_disabled under HTTP errors.
invalid_credentials 401 The API refused the credential during a session: the key was revoked, expired or suspended moments ago, API keys were switched off for the whole service, or the signed-in person was deactivated or left the organization. Within about 30 seconds, requests get HTTP 401 invalid_token. Replace the key (rotate, revoke and suspension) and restart the client. For a sign-in, sign in again with an active account.
route_not_allowed 403 The operation is not available to API keys. Use the Queue CallBack portal.
custom_ivr_not_enabled 403, or none The organization does not have the Custom IVR add-on (the portal's Billing page sells it as the Custom IVA plan), so the IVR flow tools are unavailable. Without status, the MCP server refused a call to an IVR flow tool that is not listed for the organization. The queue, callback and callback report tools still work. If the message names the Billing page, an organization admin can buy or restore the add-on there. Otherwise ask Queue CallBack support.
ivr_reporting_not_enabled 403, or none The IVR call reports are for organization admins of organizations with the Custom IVR add-on (or of organizations that keep IVR reporting after the add-on lapsed), and this credential is not one: get_me shows ivr_reporting_enabled: false. The five IVR report tools (get_ivr_summary, list_ivr_calls, get_ivr_call, get_flow_decisions, list_ivr_flow_stats) are then not listed. Without status, the MCP server refused the call before anything was sent; with 403, the Queue CallBack API refused it. The message ends: "The callback reports (get_callback_summary, list_callbacks, get_callback_journey, get_live_stats) still work." Use the callback reports, or ask an organization admin. An organization admin's API key or sign-in reads the IVR call reports where the organization has the add-on.
custom_ivr_queue_required 403 The flow belongs to a queue that is not a Custom IVR queue, and the add-on covers only the flows of Custom IVR queues. Reading the flow still works. An organization admin marks the queue as a Custom IVR queue in the portal (each Custom IVR queue uses one license of the Custom IVR add-on), then call again.
writes_disabled none Queue CallBack has switched off changes through the MCP server. While changes are off, the tools that change something are not listed, and a call to one by name, for example from an older tool list, gets this code and sends nothing. The message reads "Queue CallBack has switched off changes through this server for now. Make the change in the Queue CallBack portal; read-only tools still work." Make the change in the portal, or try again later.
queue_writes_disabled none Queue CallBack has switched off changes to a queue's voice and language through the MCP server, apart from the other changes. While they are off, set_queue_voice and set_queue_language are not listed, and a call to either by name gets this code and sends nothing. Change them in the portal, or try again later.
queue_settings_disabled none Queue CallBack has switched off changes to a queue's callback settings through the MCP server, apart from the other changes. While they are off, update_queue_settings is not listed, and a call to it by name gets this code and sends nothing. Change them in the portal, or try again later.

Arguments, confirm tokens and handles

Code status Meaning Fix
refused none The arguments do not match the tool's input schema (an unknown argument, a wrong type, a missing required argument, a value outside its pattern), or are not one JSON object. The text names the argument, sometimes in raw schema-validator wording. Nothing was sent. Fix the argument and call again. The tool reference lists every argument.
request_refused none The request could not be built or was stopped before sending, for example because an idempotency key is longer than 255 characters. Nothing was sent. If the message says the request "did not pass this server's own checks", the arguments are not the cause. Fix the arguments and call again. When the arguments are not the cause, try again later, and contact Queue CallBack support if it repeats.
tool_refused none The tool's own check refused the call, and nothing was changed (the tool may have read the current state first). Examples: an edit_flow_draft call over its limits; an organization that edits its IVR flows live instead of through drafts; an unknown node type in get_node_type; get_live_stats with tz and timezone naming different zones. Follow the message.
confirm_required none publish_flow was called with an empty confirm_token. A call that leaves the argument out is refused earlier with refused, because confirm_token is required. issued_by is validate_flow. Call validate_flow, show the user diff_flow, then call publish_flow with the digest, base version and token (confirm tokens).
confirm_refused none The confirm token is not valid, has expired, was already used, or was issued for another tool, credential, organization or other argument values. Rarely, the server holds too many open tokens. This call changed nothing. A token refused as invalid, expired or issued for other values is not spent. A token that was already used comes back with confirm_token_spent: true, and the message says that the earlier call that used it may have made the change: a call that timed out or got no answer can still have run. With confirm_token_spent: true, read the current state first (get_queue, get_requeue_status or list_callback_queue, list_flow_versions). Then get a new token from the issuing call (validate_flow for publish_flow; the same tool without confirm_token for the others), show the user what will change, and call again; for requeue_callback, send the same idempotency_key as the earlier call. Never invent or reuse a token.
invalid_handle none The handle is unknown, expired (handles last 24 hours) or belongs to another credential. The message says how to check whether the operation already ran, by the kind of handle. For get_requeue_status: do not requeue again yet. Check the callback in list_callback_queue, and requeue it only if it is still expired, failed or cancelled, with the same idempotency_key as before. For get_publish_status: the publish or restore already happened, so do not publish again; list_flow_versions shows the current version. Only the warm-up report is lost.
idempotency_key_reused 422 The idempotency key was already used in this organization for a different request (another queue, number or callback). Nothing was done. Send a new key. Reuse a key only to repeat the identical request.
invalid_idempotency_key 400 The API refused the key's format. Through the MCP server this is rare: a key with characters other than letters, digits, ., _, : and - is refused first with refused, and a key longer than 255 characters with request_refused. Nothing was done. Use letters, digits, ., _, : and -, at most 255 characters.
idempotency_key_in_progress 409 A requeue with this idempotency key is still running. Wait, then check get_requeue_status or list_callback_queue. Keep the same key.

Limits and availability

Code status Meaning Fix
rate_limited 429 The API key or the organization sent requests faster than its rate (Limits). Can also arrive as HTTP 429 before any tool runs, from the credential check or from the edge's per-address limit (HTTP errors). Wait retry_after_seconds, then call again.
concurrency_limited 429 More than 4 API requests were in flight at once for the organization, or the service was at its total for all organizations. Before any tool runs, HTTP 429 with this code can also mean more than 8 requests in flight for the credential at the MCP server. Wait retry_after_seconds (1), and run fewer tool calls in parallel.
queue_write_limited 429 The organization changed queue callback settings (or voices and languages) through API keys and connected clients too often. Wait retry_after_seconds.
auth_busy 503 Too many credential checks were running at the API. Retry after retry_after_seconds (1).
result_too_large none The answer is larger than the tool's result limit, even after a long list was shortened. The API did answer, so for a tool that changes something the change may have happened. Narrow the request: a shorter date range, filters or a smaller limit. After a change, read the current state before you repeat it.
backend_timeout none The Queue CallBack API did not answer within the tool's time limit. The operation may still complete. A read: call again. A change: read the current state first (Retries).
backend_unreachable none The Queue CallBack API could not be reached. Can also arrive as HTTP 502 before any tool runs. A read: retry shortly. A change: read the current state first.
backend_error none, or 502 The API's answer was unreadable or not in the documented shape. One case: edit_flow_draft was accepted but the answer lacked the draft's state, so the operations were most likely applied. Read the current state, then decide whether to repeat.
no_answer none The tool produced no answer. Read the current state, then decide whether to repeat.

Callbacks and reporting

Code status Meaning Fix
requeue_limit_reached 409 The callback was requeued 5 times in the last 24 hours, the most allowed. details.retry_after is the time it can be requeued again. Tell the user, and wait until that time.
requeue_busy 503 Too many requeues are running on the service, so this one was not started. Retry after retry_after_seconds, with a new confirm token (Retries).
date_range_too_long 400 The report's range from from to to is longer than 400 days. Choose a shorter range.
query_timeout 504 A report query took too long and was stopped. Narrow the date range or the filters, then call again.
reporting_busy 503 Too many report requests are running right now. Retry after retry_after_seconds.
interactive_busy 503 Too many quick reads are running right now. This can also answer list_flows, get_callback_journey and get_ivr_call. Retry after retry_after_seconds.
invalid_timezone 400 get_live_stats got a time zone that is not an IANA time zone name. Nothing was read. The other reporting tools refuse an unknown tz with 400 and no code. Send an IANA name such as America/Chicago.

add_callback refuses a callback with one of these codes. None of them adds a callback or places a call. For a 4xx answer, details carries the API's answer, whose texts are written for people.

Code status Meaning Fix
invalid_request 400 The number or the queue is missing. Through the MCP server this is rare: the tool's schema requires both, so a missing one is refused first with refused. Send callback_number and queue_id.
invalid_callback_number 400 The number does not have 8 to 15 digits. Ask the user for the whole number. Never use a masked number.
callback_number_outside_country 400 The number is outside the organization's country; only numbers in that country can be called back. Tell the user. A number with + must be in the organization's country.
queue_not_found 404 No queue with this queue_id in the organization. Another organization's queue, and an id that is not a UUID, get the same answer. Take the id from list_queues.
queue_in_other_organization 403 Only Queue CallBack's own administrators, who can name another organization, get this code. A key or sign-in of your organization gets queue_not_found for another organization's queue. Choose a queue of that organization.
queue_not_running 409 The queue is stopped. Tell the user to start the queue in the portal, then add the callback.
queue_without_extension 409 The queue has no extension to ring. Tell the user to set the queue's extension in the portal.
callback_already_waiting 409 The number already has a callback waiting in that queue. details.callback_id names it. Do not add another. Use the waiting callback.
manual_callback_limit_reached 429 The organization added 30 callbacks by hand in the last hour, in the portal or with add_callback. retry_after_seconds says when a callback can be added again; it is missing when the server cannot tell. Tell the user when they can add one again. Without a wait time, try again later: the limit counts a rolling hour.
callback_queue_unavailable 503 The callback queue of the service is not available right now. Retry later. Contact Queue CallBack support if it repeats.

add_callback can also answer idempotency_key_reused, invalid_idempotency_key and the general codes on this page.

IVR flows (Preview)

These codes belong to the IVR flow tools, which are in Preview while the IVR builder is redesigned. Codes may be added or changed; the changelog records changes. edit_flow_draft can refuse an operation with a code that is not listed here; every such refusal names the operation in details.failed_ops, and nothing of the call is applied. The validation issues that validate_flow reports carry codes of their own, which are not listed here: branch on them and show the user the issue's text (Validate, review and publish). The editing loop is on Edit a flow safely.

Code status Meaning Fix
revision_mismatch 409 The draft changed since you read it, so your etag is stale. Nothing changed. details.etag is the current etag. Read the flow with get_flow, apply your change to the current draft, and send it with the current etag.
node_exists 422 edit_flow_draft was refused at the operation named in details.failed_ops; no operation of the call was applied. The node id is taken. Fix that operation and send the whole edit again with the same etag.
node_not_found 422 edit_flow_draft was refused at the operation named in details.failed_ops; no operation of the call was applied. No node has that id. Fix that operation and send the whole edit again with the same etag.
invalid_body 422 edit_flow_draft was refused at the operation named in details.failed_ops; no operation of the call was applied. The operation's fields or config_json are malformed. Fix that operation and send the whole edit again with the same etag.
no_fields 422 edit_flow_draft was refused at the operation named in details.failed_ops; no operation of the call was applied. An update_node changes nothing. Fix that operation and send the whole edit again with the same etag.
entry_node 422 edit_flow_draft was refused at the operation named in details.failed_ops; no operation of the call was applied. The entry node cannot be deleted. Fix that operation and send the whole edit again with the same etag.
node_referenced 422 edit_flow_draft was refused at the operation named in details.failed_ops; no operation of the call was applied. Other nodes still connect to the node. Fix that operation and send the whole edit again with the same etag.
connection_target_missing 422 edit_flow_draft was refused at the operation named in details.failed_ops; no operation of the call was applied. A connection points to a node that does not exist. Fix that operation and send the whole edit again with the same etag.
invalid_node_type 422 edit_flow_draft was refused at the operation named in details.failed_ops; no operation of the call was applied. The node type is unknown. Get node types from list_node_types (node types), fix that operation and send the whole edit again with the same etag.
edit_interrupted 502 or 504 edit_flow_draft got no answer, or none in time. An edit applies all of its operations or none. Read the flow with get_flow to see which happened before you send the edit again.
no_draft 409, or 404 from diff_flow The flow has no draft: there is nothing to publish, or nothing to compare. To change the flow, start a draft with create_flow_draft, edit it, validate it, then publish. To compare versions only, call diff_flow with from and to set to published or version numbers.
draft_exists 409 restore_flow_version with target live was refused because the flow has a draft and discard_draft is false. Nothing changed. Publish or discard the draft first, or, if the user agrees to lose the draft, start again with a first call that has discard_draft: true and get a new confirm token.
draft_stale 409 The draft was started from an older version than the one now published. Discard the draft (or restore into it) and make the change again.
base_version_mismatch 409 base_version is not the flow's current version: someone published in the meantime. details.current_version is the current one. Read the flow, check the change with diff_flow, then run validate_flow again.
digest_mismatch 409 The draft changed after validate_flow checked it. Run validate_flow again and publish with the new digest and token.
validation_failed 422 The draft has errors; details.validation lists them. Fix them, or acknowledge the acknowledgeable ones, then validate again.
version_not_found 404 No version of the flow has that number. List the versions with list_flow_versions.
draft_publish_disabled 409 The organization edits its IVR flows live, not through drafts, so the MCP server cannot change them. Use the portal's flow builder, or ask Queue CallBack support to switch the organization to drafts.

Answers without a code

Some refusals from the Queue CallBack API carry a status and a message but no code. Branch on status.

status Meaning Fix
400 The API refused an argument value; the message names it. Fix the value and call again.
403 "This credential may not do this." Check the key's role and scopes with get_me, or use the portal.
404 Nothing with that id exists in this organization. complete_callback also answers 404 for a callback that is already completed or cancelled. Get a valid id from the matching list tool, such as list_queues, list_callback_queue or list_flows.
409 The current state does not allow the change. Read the current state, then decide with the user.
422 The API refused the request as a whole; the message says why. Fix the arguments.
429 set_organization_name more than about once every 6 seconds. Wait (retry_after_seconds when present), then call again.
500, 502, 503, 504 The API failed or is busy. A read: retry with back-off. A change: read the current state first.

Retries

These rules tell an AI agent, or any client of the Queue CallBack MCP server, when to repeat a request, how long to wait, and what to read before repeating a change.

Wait as long as the server says

  1. When an answer has a Retry-After header or a retry_after_seconds field (in error.data or structuredContent.error), wait at least that long.
  2. When a 429 or 503 comes without a wait time, back off exponentially with jitter: about 1, 2, 4, 8 and 16 seconds, never more than 60 seconds between attempts.
  3. Stop after about 5 attempts. Tell the user what failed and give the code (and the X-Request-ID header if the client shows it).
  4. After concurrency_limited, run fewer calls at once: at most 4 tool calls in parallel per organization, counting every key.

Repeat reads freely, changes only after reading the state

A read-only tool can be repeated after any error that is about load or availability: rate_limited, concurrency_limited, auth_busy, reporting_busy, interactive_busy, query_timeout (narrow the query first), backend_timeout, backend_unreachable, backend_error, HTTP 5xx.

A tool that changes something is different. After backend_timeout, backend_unreachable, backend_error, result_too_large, no_answer, edit_interrupted, a 5xx status, or a dropped connection, the change may have happened. Never repeat it blindly. Read the state first:

Tool Read this first Then
add_callback list_callback_queue: is a callback for that number waiting in that queue? Repeat with the same idempotency_key. The API replays the first answer instead of adding a second callback.
requeue_callback get_requeue_status with the handle, if the first answer had one; otherwise list_callback_queue: is the callback back in the queue? Repeat only if it was not requeued (see below).
complete_callback list_callback_queue A repeat is harmless: a callback already completed answers 404.
update_queue_settings get_queue: compare the settings If they did not change, start again with the first call and the user's agreement.
set_queue_voice, set_queue_language get_queue: compare the voice, speed or language If they did not change, start again with the first call and the user's agreement.
set_organization_name get_organization Repeat if the name did not change.
create_flow_draft, edit_flow_draft, discard_draft get_flow: the draft and its etag An edit applies all of its operations or none. Resend with the current etag only if they are missing.
publish_flow, restore_flow_version list_flow_versions: is there a new version? With a handle, also get_publish_status. For restore_flow_version with target draft, which creates no version, read get_flow instead: does the draft now match the restored version (diff_flow from that version number to draft)? If nothing was published, run validate_flow again (for restore_flow_version, the first call again), then repeat with the user's agreement.

An answer that refused the call before it ran (rate_limited, concurrency_limited, auth_busy, queue_write_limited, requeue_busy, any HTTP error other than a 500 or a 502 or 504 without a JSON-RPC body) changed nothing, and the change can be repeated after the wait.

Confirm tokens are spent on use

A confirm token is spent the moment the server accepts it, before the Queue CallBack API answers, even if the change then fails or is refused by a limit. Every repeat of a confirmed change therefore needs a new token: from validate_flow for publish_flow, and from a first call without confirm_token for requeue_callback, restore_flow_version, update_queue_settings, set_queue_voice and set_queue_language. Show the user what will change and get their agreement again.

A call that fails after its token was accepted says so. Its structuredContent.error carries confirm_token_spent: true and a next_step with the retry steps, and its text ends with the same steps:

The failed call next_step says
publish_flow Call validate_flow again for a new token, then call publish_flow with it
requeue_callback with an idempotency_key Call requeue_callback again without confirm_token for a new token, then call it again with that token and the same idempotency_key, so a requeue that already ran is not run twice
requeue_callback without an idempotency_key Check the current state first, because the requeue may have run. Then get a new token the same way and send an idempotency_key with the retry
Any other tool with a confirm token Call the tool again without confirm_token for a new token, then call it again with that token

A confirm_refused answer changed nothing. With confirm_token_spent: true, the token was used by an earlier call, which may have made the change: read the current state before you get a new token. See confirm tokens.

Requeues place real calls

Every requeue_callback makes the system ring an agent and then call the customer. Never repeat a requeue without checking get_requeue_status first.

get_requeue_status status What it means Next step
pending, running The requeue is still in progress. Check again in a few seconds. Do not requeue again.
succeeded The callback is back in the queue. Nothing to repeat.
failed, conflict The callback was not requeued. Read the answer and tell the user before trying again. A new attempt needs a new first call and a new idempotency_key.
interrupted The server stopped before it recorded the outcome. Check the callback with list_callback_queue before any new requeue.

If get_requeue_status answers invalid_handle, check the callback with list_callback_queue instead of starting the requeue again. To learn what happened to the first attempt, call requeue_callback again with the same idempotency_key and a new confirm token: when the API recorded the first attempt, it replays the recorded request instead of dialing again. A first attempt that never reached the API runs now, so get the user's agreement for this call too. If the replayed status is failed or conflict and the user agrees to try again, use a new confirm token and a new idempotency_key: the old key only replays the failed attempt.

Idempotency keys

add_callback and requeue_callback take an idempotency_key argument: letters, digits, ., _, : and -, at most 255 characters. A client can send _meta.idempotencyKey on the request instead; the argument wins.

  1. Make one new random key, such as a UUID, for each action you intend.
  2. Send the same key with every repeat of that action. A repeat returns the recorded answer instead of acting twice, even when that answer was a failure: a requeue recorded as failed or conflict needs a new key to be tried again.
  3. Never use the key for a different action. Keys are unique per organization, across all of its keys, and a reused key gets idempotency_key_reused.
  4. Send your own key with add_callback. Without one, the server makes a key for that single call only, so a repeat call gets a different key.

For symptoms rather than codes (cannot connect, a tool is missing, numbers are masked), see troubleshooting.