What the API returns when a call fails - the error body, HTTP status codes, the full error code table, and the permission each endpoint checks.
Errors
A failed call returns a non-2xx status and a JSON body with a message:
{ "message": "Organisation ID is required." }
Errors that map to a known condition also carry a code and sometimes an action:
{
"code": "CB001",
"message": "Payment method required",
"action": "Add a payment method in Billing settings."
}
message is written for a person to read. code is the one to branch on - messages get reworded, codes do not.
Status codes#
| Status | Means | Do |
|---|---|---|
400 | The body was wrong - a missing id, a bad value | Fix the request; retrying will not help |
401 | No token, or an expired one | Refresh the session token and retry once; an API key that returns this is revoked or expired |
402 | Billing is blocking the action, or the plan does not include API keys | See Billing and Authentication |
403 | Authenticated, but not allowed | Check the role and the permission below |
404 | No such resource, or not yours | Do not distinguish these - the API deliberately does not |
409 | Conflicts with what already exists | Usually a duplicate name |
429 | Rate limited | Honour Retry-After when present |
5xx | The platform, not you | Retry with backoff; if it persists, contact us |
The default for a rejected request is 400, not 422.
Error codes#
The first letter is the service (C for console), the second the category, then a number.
Deploy#
| Code | Status | Message |
|---|---|---|
CD001 | 500 | Container deployment failed |
CD002 | 400 | Container deployment failed due to invalid configuration |
CD003 | 500 | Container build failed |
CD004 | 500 | Failed to push container image |
CD005 | 500 | Failed to deploy container to cloud |
CD006 | 504 | Deployment timed out |
CD007 | 500 | Failed to delete container deployment |
CD010 | 500 | Static site deployment failed |
CD011 | 500 | Static site build failed |
CD012 | 500 | Failed to upload static files |
CD003 and CD011 are your build, not the platform - read the deployment logs.
Auth#
| Code | Status | Message |
|---|---|---|
CA001 | 401 | Authentication failed |
CA002 | 403 | You do not have permission to perform this action |
CA003 | 403 | You do not have access to this organisation |
CA001 with an API key means the key is wrong, revoked, or expired - the API does not distinguish between them.
CA003 usually means the wrong targetOrganisationId, not a missing role. With a key it means the body named an organisation the key does not belong to; omit the field and it is filled in correctly.
Billing#
| Code | Status | Message |
|---|---|---|
CB001 | 402 | Payment method required |
CB003 | 402 | Usage limit exceeded |
A 402 on every request made with an API key, rather than on one particular action, means the organisation's plan no longer includes keys - the entitlement is re-checked on each call, so a downgrade stops existing keys working. Move to a paid plan, or use the MCP server, which works on every account.
General#
| Code | Status | Message |
|---|---|---|
CG001 | 500 | Something went wrong |
CG002 | 400 | Invalid request |
CG003 | 404 | Resource not found |
CG004 | 409 | This action conflicts with existing data |
CG005 | 429 | Too many requests |
CG006 | 503 | Service temporarily unavailable |
Platform services#
| Code | Status | Message |
|---|---|---|
CR001 | 503 | Deployment service is temporarily unavailable |
CR002 | 502 | Deployment service returned an error |
CR003 | 504 | Deployment service timed out |
CS001 | 503 | Database connection failed |
CS002 | 500 | Database operation failed |
CX001 | 502 | Failed to connect to GitHub |
CX002 | 502 | Payment service error |
All of these are worth retrying with backoff. CR003 in particular does not mean the deploy failed - it means the answer was slow. Poll environment status before retrying the deploy, or you will start a second one.
Permissions#
403 with CA002 means your role in that organisation lacks the permission the endpoint checks:
| Permission | Endpoints |
|---|---|
read:projects | Every list, get, status, logs, metrics, and activity call |
create:projects | Creating applications, environments, and databases |
update:projects | Update, scale, deploy, rollback, rename, move, domains, password rotation |
delete:projects | Deleting applications, environments, and databases |
read:users | Listing organisation members |
read:billing | Invoices, usage, and payment methods |
update:all | Organisation-level settings |
Read your role from /api/auth/profile. An API key holds one of two access levels rather than a role: read-only maps to read:projects, deploy-and-manage adds create, update, and delete. No key holds billing or organisation permissions, so those endpoints answer 403 to every key.
Retrying safely#
Creates are not idempotent - there is no idempotency key yet, so a retried create after a timeout can leave you with two applications. On a timeout, list first and check before retrying.
Deletes and updates are safe to repeat.