When a request cannot be completed, the Tooken API returns a structured error response alongside an appropriate HTTP status code. All error responses use the same JSON shape, making it straightforward to handle them consistently in your code.
Every error response body contains three fields:
{
"error": "not_found",
"message": "Token tok_abc123 not found",
"status": 404
}
| Field | Type | Description |
|---|
error | string | A machine-readable error code you can use in conditional logic |
message | string | A human-readable description of what went wrong |
status | integer | The HTTP status code, mirrored in the response body for convenience |
HTTP status codes
The table below lists every status code the API returns, the corresponding error code, and what it means for your request.
| Status | Error code | Meaning |
|---|
400 | bad_request | The request body or query parameters are malformed or missing required fields |
401 | unauthorized | The Authorization header is missing or the API key is invalid |
403 | forbidden | The API key is valid but does not have the scope required for this operation |
404 | not_found | The requested resource does not exist or is not accessible in your workspace |
409 | conflict | A token with the same name already exists in your workspace |
422 | unprocessable_entity | The request is well-formed but contains invalid values (for example, an unparseable date) |
429 | rate_limited | You have exceeded 1,000 requests per minute for your workspace |
500 | internal_error | An unexpected error occurred on Tooken’s servers |
400 Bad request
You receive this when the API cannot parse your request. Common causes include sending an invalid JSON body, omitting a required field, or passing a parameter with the wrong type. Check the message field for specifics on what was rejected.
401 Unauthorized
Your request did not include a valid API key. Make sure the Authorization header is present and formatted as Bearer tok_live_xxxxxxxxxxxxxxxxxxxx. If you recently rotated your key, ensure you are using the new one.
403 Forbidden
Your API key is recognized but lacks the required scope for the endpoint you called. For example, calling DELETE /tokens/:id with a key that only has tokens:read scope returns a 403. Grant the necessary scope from the Tooken dashboard or generate a key with the correct permissions.
404 Not found
The resource you requested either does not exist or belongs to a different workspace. Verify the token ID in your request matches one in your workspace.
409 Conflict
Token names must be unique within a workspace. If you attempt to create a token using a name that is already in use, the API returns 409. Choose a different name or revoke the existing token first.
422 Unprocessable entity
The request structure is valid, but one or more field values failed validation. A common example is supplying an expires_at value that is not a valid ISO 8601 datetime string. The message field identifies which field failed and why.
429 Rate limited
You have sent more than 1,000 requests within the current one-minute window. See handling rate limits below.
500 Internal error
Something went wrong on Tooken’s end. These errors are logged automatically. If you see repeated 500 responses, check the Tooken status page or contact support.
Handling rate limits
When you approach or hit the rate limit, use the response headers to manage your request cadence:
- Check
X-RateLimit-Remaining before sending each request. If it is 0, stop immediately.
- Read
X-RateLimit-Reset to get the Unix timestamp when the window resets.
- Wait until that timestamp before retrying. Sending requests earlier will continue to return
429.
A minimal example of retry logic:
async function requestWithBackoff(url, options) {
const response = await fetch(url, options);
if (response.status === 429) {
const resetAt = response.headers.get("X-RateLimit-Reset");
const waitMs = (Number(resetAt) * 1000) - Date.now();
await new Promise((resolve) => setTimeout(resolve, Math.max(waitMs, 0)));
return requestWithBackoff(url, options);
}
return response;
}
Idempotency
DELETE requests are idempotent in design, but the API does not suppress 404 responses for already-deleted resources. If you call DELETE /tokens/:id on a token that has already been revoked or does not exist, the API returns 404 not_found. Your application should treat a 404 on a DELETE as a successful outcome — the token is no longer active regardless of whether it existed.