Errors return the HTTP status that fits, a short reason, and a message written for a person. Where a client can do something specific about it, data.code names the situation.
Error response
{
"statusCode": 403,
"error": "Forbidden",
"message": "Plan limit reached for monitors (15)",
"data": { "code": "PLAN_LIMIT", "key": "monitors", "limit": 15 }
}Status codes
| Status | Meaning |
|---|---|
| 400 | The request is malformed or a value is invalid. The message says which. |
| 401 | Missing or invalid credentials. The key may have been revoked. |
| 403 | The credentials are valid but lack the permission, or a plan limit was reached. |
| 404 | The resource does not exist, or it belongs to another organisation. The two are deliberately indistinguishable. |
| 409 | The action conflicts with the resource's state: deleting a published incident, editing a maintenance window that already started, demoting the last owner. |
| 429 | Rate limited (public endpoints only). Honour Retry-After when present. |
| 500 | Something failed on our side. Retry with backoff; nothing was partially applied. |
Codes
| Code | Status | When |
|---|---|---|
PLAN_LIMIT | 403 | A create would exceed the plan. data.key names the limit (pages, monitors, workspaces, team_members, api_keys) and data.limit its value. |
INVALID_INPUT | 400 | Billing endpoints: a field failed validation. data.issues lists { field, message }. |
MAINTENANCE_STATUS | 409 | A start, complete or cancel that lost a race with the window's automatic transition. data.status is the window's real status. |
SUBSCRIPTION_EXISTS | 409 | Checkout attempted while a live subscription exists. |
SUBSCRIPTION_PAST_DUE, SUBSCRIPTION_PAUSED, SCHEDULED_CHANGE_PENDING | 409 | Plan change blocked by the subscription's state. |
INVITE_EMAIL_MISMATCH | 403 | Accepting an invitation with an account whose email is not the invited one. |
ACCOUNT_EXISTS | 409 | Registering from an invitation with an address that already has an account. |
Validation messages
Validation failures do not carry a code; the message is specific enough to show to a user. Examples: name is required, TCP target must be host:port (IPv6 as [address]:port), Target resolves to a private address (10.0.0.4), which monitors may not probe, url must be a valid https URL.
A 404 on a resource you are sure exists almost always means the key belongs to a different organisation, or an organisation-wide key was used without
X-Workspace-Id.