Errors and rate limits
The errors the REST API and the kanman MCP server return, the request limits, and how to retry, including webhook delivery retries.
This page covers what kanman’s programmatic interfaces return when something goes wrong: the REST API and the kanman MCP server. Tool errors of the MCP server are listed in MCP tools. How kanman retries webhook deliveries is described under Delivery rules.
REST API errors
Every error has the same shape:
{ "error": { "code": "not_found", "message": "Run run-7f3k does not exist in this workspace." } }
code is stable and meant for your code; message is meant for people and may change.
| Status | code |
When |
|---|---|---|
400 |
invalid_request |
A parameter or the body is invalid, for example an unknown filter value, a bad cursor or an option that is not part of the decision. |
401 |
unauthorized |
The token is missing, unknown, revoked or expired, its workspace was deleted, or its owner left the workspace. The answer carries WWW-Authenticate: Bearer. |
403 |
forbidden |
The token lacks the permission of the endpoint, or the audit log was requested by a token of a person who is not an owner or admin. |
404 |
not_found |
The endpoint or the object does not exist in the token’s workspace. |
405 |
method_not_allowed |
The path exists, but not with this method. |
409 |
conflict |
The decision was already answered. |
410 |
gone |
An endpoint of the first API version that was removed (projects and tasks). |
429 |
rate_limited |
Too many requests. See Rate limits. |
500 |
internal_error |
Something went wrong on kanman’s side. Try again. |
MCP server errors
The MCP server answers in JSON-RPC 2.0. A request it cannot accept gets an error object:
{ "jsonrpc": "2.0", "id": null, "error": { "code": -32600, "message": "Unauthorized" } }
A tool that fails does not return a protocol error. It returns a normal tool result marked isError: true with a readable message, so the coding agent can react to it.
HTTP status codes
| Status | When |
|---|---|
200 |
The request was handled. Tool errors also come back with 200. |
202 |
A notification was accepted. |
400 |
The body is not valid JSON. |
401 |
The token is missing, unknown, revoked or expired, or the story in the address is not in the token’s workspace. The response carries WWW-Authenticate: Bearer. |
405 |
The method is not POST. The server is stateless and offers no event stream. |
413 |
The request body is larger than 256 KB. |
500 |
Something went wrong on kanman’s side. Try again. |
Error codes
| Code | Message | Meaning |
|---|---|---|
-32700 |
Parse error | The body is not valid JSON. |
-32600 |
Unauthorized, Request too large, Invalid JSON-RPC message | The request was refused before it was handled. Send one JSON-RPC message per request; batches are not accepted. |
-32601 |
Method not found | The JSON-RPC method is not one the server knows. |
-32602 |
Unknown tool | tools/call named a tool the server does not have. |
-32603 |
Internal error | Something went wrong on kanman’s side. |
Rate limits
The REST API allows 120 requests per minute per token. The window starts at the full minute. Every answer carries:
| Header | Meaning |
|---|---|
X-RateLimit-Limit |
Requests allowed per minute. |
X-RateLimit-Remaining |
Requests left in the current minute. |
X-RateLimit-Reset |
Unix time in seconds when the next minute starts. |
Over the limit, the API answers 429 with Retry-After in seconds. kanman does not publish request limits for the MCP server; coding agents call it a few times per story, far below any limit you would notice.
Retrying
- Retry
500responses and network errors after a short pause, with growing intervals. - After a
429, wait the number of seconds inRetry-After. - Do not retry
400,401,403,404,409or410: change the request or the token first. - Tool results with
isError: trueare answers, not failures. Read the message: it tells the agent what to do next, for example “No run is active for this story yet. Call start_work first.” - Webhook deliveries are retried by kanman up to four times. See Delivery rules.
Use fewer requests
- Subscribe to webhooks instead of polling the API for new runs or decisions.
- Page with a
limitof 100 when you read a long history, and stop whennextCursorisnull. - Call
get_storyonce at the start instead of before every step. - Send
report_progresswhen the stage changes, not for every file.
Last updated: January 1, 0001
Open kanman