Errors
When the v3 API refuses a request it answers with a 4xx or 5xx status and the same JSON body every time. The message is written for whoever has to act on it — it says what was wrong and, usually, what would have to change — so it is worth logging and, where a person is waiting, showing.
The Error Body
{
"error": {
"code": "VALIDATION_ERROR",
"message": "match must be 'equals' or 'contains'",
"requestId": "req_0c5e2b7a9f1d4e36b8a0d7c4e2f19a53",
"field": "fields[0].match"
}
}
| Field | Type | Description |
|---|---|---|
code | string | A stable, machine-readable code from the catalogue below. Branch on this, never on the message. |
message | string | A sentence explaining the refusal. Its wording can change; do not parse it. |
requestId | string | The request's id — the same value as the X-Request-Id response header. Quote it to support. |
field | string | The request property, query parameter or header at fault. Absent when the problem is not with one input. |
violations | array | Every problem with a template document. Only on TEMPLATE_INVALID. See Template Documents. |
retryAfterSeconds | integer | How long to wait before retrying, at least 1. Only on RATE_LIMIT_EXCEEDED. |
url | string | The same request on the correct regional address. Only on WRONG_REGION. |
Like every v3 response, the error body leaves out properties that have no value.
Handling Errors
| Status | Retry unchanged? | What to do |
|---|---|---|
400 | No | Fix the input named in field, using the message. |
401 | No | Fix the key. See Authentication. |
403 | No | The acting member is not allowed to do this, or nobody is (a write to a system Data Set, say). The message says which permission or setting is in the way. Use a key that acts as someone who is allowed, or have an Administrator grant the permission. |
404 | No | Check the key or id. Something that belongs to another workspace answers 404 too, whoever the key acts as. |
409 | Sometimes | The state changed or is in the way. Read the resource again, then decide. For an idempotency conflict, see Idempotency. |
421 | No | Send it to the address in url. |
422 | No | Fix every entry in violations and send the document again. |
429 | Yes, later | Wait Retry-After seconds. |
500 | Yes | Retry with backoff. Send an Idempotency-Key on writes so a retry cannot duplicate work. |
Error Codes
Authentication and Access
| Code | Status | Meaning |
|---|---|---|
MISSING_API_KEY | 401 | The X-API-KEY header is missing or empty. |
INVALID_API_KEY | 401 | No workspace has this key. |
API_KEY_REVOKED | 401 | The key was revoked on the Team page. |
API_KEY_EXPIRED | 401 | The key is past its expiry date. |
API_KEY_ACTOR_UNAVAILABLE | 401 | The member the key acts as has been deactivated, removed or made a Guest since the key was created. |
API_KEY_ACTS_AS_WORKSPACE | 403 | A key that acts as the workspace was used on a route about a person — the Tasks grid, a snooze or a saved view. |
FORBIDDEN | 403 | The member the key acts as is not allowed to do this: they lack a permission such as Template.Creator, their permission on the template or its Library folder does not allow it, or the action is limited to Administrators. Also returned for an action that is refused to everybody, such as a write to a system Data Set. See Who a Key Acts As. |
ENTERPRISE_PLAN_REQUIRED | — | The workspace is not on the Enterprise plan. Only the MCP server returns this, inside an MCP response rather than as an HTTP status. |
WRONG_REGION | 421 | The key's workspace is in the other region. url says where to send the request. |
Not Found
Each resource has its own code, so that when a request names several things you can tell which one was missing.
| Code | Status | Meaning |
|---|---|---|
CHECKLIST_NOT_FOUND | 404 | No checklist with that key in this workspace. A checklist of this workspace that the acting member may not see is 403 FORBIDDEN instead. |
TASK_NOT_FOUND | 404 | No checklist task or standalone task with that key. |
FIELD_NOT_FOUND | 404 | No field (input control) with that key on the task. |
FILE_NOT_FOUND | 404 | No uploaded file with that id. |
COMMENT_NOT_FOUND | 404 | No comment with that id on the task. |
TEMPLATE_NOT_FOUND | 404 | No template with that key in this workspace. A template of this workspace that the acting member may not read is 403 FORBIDDEN instead. |
DRAFT_NOT_FOUND | 404 | No draft with that key in this workspace, or it expired. Drafts expire 30 days after they were last changed — start a new one. |
USER_NOT_FOUND | 404 | No member (or group) with that id. |
DATA_SET_NOT_FOUND | 404 | No Data Set with that key or slug. |
DATA_SET_FIELD_NOT_FOUND | 404 | No field (column) with that key on the Data Set. |
DATA_SET_RECORD_NOT_FOUND | 404 | No record with that key on the Data Set. |
DATA_SET_VIEW_NOT_FOUND | 404 | No view with that key on the Data Set. |
SCHEDULE_NOT_FOUND | 404 | No schedule with that id. |
SCHEDULE_RUN_NOT_FOUND | 404 | No run with that id on the schedule. Check you have not swapped the schedule id and the run id. |
WEBHOOK_NOT_FOUND | 404 | No webhook subscription with that id. |
NOT_FOUND | 404 | Something the request named does not exist, and no more specific code applies. |
Invalid Requests
| Code | Status | Meaning |
|---|---|---|
VALIDATION_ERROR | 400 | The request is malformed, a required value is missing, or a value is not allowed. field names the input. |
TEMPLATE_INVALID | 422 | A template document cannot be stored as written. violations lists every problem, each with a path. |
CONFLICT | 409 | The request is valid but the current state will not accept it, or an Idempotency-Key was reused for a different request or is still in progress. Retrying may succeed once the state changes. |
METHOD_NOT_ALLOWED | 405 | The route does not answer this HTTP method. Only /mcp returns it, to GET and DELETE. |
Limits and Faults
| Code | Status | Meaning |
|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | The workspace has spent its rate limit budget for this window, or too many invalid keys were sent from your address. retryAfterSeconds and the Retry-After header say how long to wait. |
INTERNAL_ERROR | 500 | Something failed on our side. Retry, and quote the requestId if it persists. |
COMMIT_INTERRUPTED | — | Never an HTTP response. Recorded on a draft commit whose background work stopped part-way. Check whether the template was created before committing again. |
Template Violations
TEMPLATE_INVALID is the one error that lists more than one problem, because a template document can be wrong in many places at once and one request should be enough to find them all:
{
"error": {
"code": "TEMPLATE_INVALID",
"message": "The template document has 2 problems.",
"requestId": "req_7d2a91c4e5b04f6e8a3c1b0d9e7f2a64",
"violations": [
{
"path": "$.tasks[2].fields[0].type",
"code": "unknown_content_type",
"message": "'Checkbox' is not a kind of control.",
"severity": "error"
},
{
"path": "$.tasks[4].dueDate.rule",
"code": "property_required",
"message": "A due date says what it is counted from, or names a calendar date.",
"hint": "Leave 'dueDate' out altogether for a task with no due date.",
"severity": "error"
}
]
}
}
Each violation has a path into the document, a code, a message, an optional hint and a severity of error or warning. Warnings never cause a refusal on their own. The full list of violation codes is on Template Documents.
Errors in the MCP Server
The MCP server uses the same codes and the same error body. Because MCP clients report HTTP errors as connection failures, the server returns refusals inside the MCP response — as a tool result with isError set — so that the AI model reads the message and can correct itself. See How the MCP Server Works.
Related Pages
- Authentication — the five
401codes and how to fix each. - Idempotency — the two situations that answer
409 CONFLICTon a retry. - Rate Limits — the budgets behind
RATE_LIMIT_EXCEEDED. - Template Documents — every violation code a document can produce.