Error codes
Every API failure returns an RFC 9457
application/problem+json body with two stable extensions: a numeric code and
a dotted codeName.
{ "status": 403, "title": "Forbidden by policy", "detail": "Activation is blocked by the entitlement's activation policy.", "code": 2011, "codeName": "license.forbidden_by_policy"}Branch on code or codeName, never on detail or title — those are
human-facing prose and may change; the codes are contract. New codes may be added
over time (an additive, backward-compatible change), so treat unknown codes as a
generic failure of the given HTTP status.
Codes are globally unique and grouped in ranges: general platform errors are 1000–1999, licensing 2000–2999, account/directory 3000–3999, webhooks 4000–4999.
General (1000–1999)
Section titled “General (1000–1999)”Cross-cutting errors any endpoint can return.
| Code | Code name | HTTP | Meaning |
|---|---|---|---|
| 1001 | validation.empty | 400 | A required value was missing or empty. |
| 1002 | validation.duplicate | 409 | The value collides with an existing record. |
| 1003 | validation.failed | 400 | The request failed validation. |
| 1010 | resource.not_found | 404 | The resource doesn’t exist. |
| 1011 | resource.expired | 410 | The resource existed but has expired. |
| 1012 | resource.limit-exceeded | 429 | A plan or capacity limit was reached. |
| 1020 | operation.invalid | 400 | The operation isn’t valid in the current state. |
| 1021 | operation.pending | 409 | A conflicting operation is already in flight. |
| 1030 | auth.forbidden | 403 | The caller lacks the required scope or role. |
| 1040 | service.unavailable | 503 | Temporarily unavailable — retry with backoff. |
| 1041 | service.failure | 500 | Unexpected failure. |
| 1042 | service.too-many-requests | 429 | Rate limit exceeded — honor Retry-After. |
Licensing (2000–2999)
Section titled “Licensing (2000–2999)”Returned by activation, session and usage endpoints.
| Code | Code name | HTTP | Meaning |
|---|---|---|---|
| 2001 | license.no_active_license | 403 | No active license backs this request. |
| 2002 | license.no_such_entitlement | 404 | The entitlement doesn’t exist. |
| 2003 | license.no_active_session | 409 | No active session for this operation. |
| 2004 | license.not_found | 404 | The activation code doesn’t map to anything, or has expired. |
| 2005 | license.invalid_operation | 400 | The operation isn’t valid for this license’s state. |
| 2006 | license.no_permission | 403 | The caller doesn’t own this session or entitlement. |
| 2007 | license.no_such_product | 404 | The product doesn’t exist. |
| 2008 | license.no_such_provider | 404 | The provider doesn’t exist. |
| 2009 | license.validation_error | 400 | The request body or activation code is invalid. |
| 2010 | license.no_credit | 400 | The credit balance can’t cover the requested consumption. |
| 2011 | license.forbidden_by_policy | 403 | Blocked by the entitlement’s activation policy (e.g. identity verification required). |
| 2012 | license.operation_pending | 409 | A pending step (e.g. email verification) must complete first. |
| 2013 | license.expired | 409 | The license or credit balance has expired. |
Account & directory (3000–3999)
Section titled “Account & directory (3000–3999)”Returned by user and organization endpoints.
| Code | Code name | HTTP | Meaning |
|---|---|---|---|
| 3001 | organization.not_found | 404 | The user or organization doesn’t exist. |
| 3002 | organization.duplicate | 409 | Already exists (e.g. email in use). |
| 3003 | organization.invalid_operation | 400 | Not valid in the current state. |
| 3004 | organization.no_permission | 403 | The caller lacks directory permission. |
| 3005 | organization.validation_error | 400 | The request failed validation. |
| 3006 | organization.no_credit | 400 | A seat or capacity limit was reached. |
Webhooks (4000–4999)
Section titled “Webhooks (4000–4999)”Returned by the webhook subscription and delivery-management endpoints.
| Code | Code name | HTTP | Meaning |
|---|---|---|---|
| 4001 | subscription.tenant_required | 400 | The request lacks an active environment context. |
| 4002 | subscription.client_id_required | 400 | An OAuth client identity is required. |
| 4003 | subscription.tenant_mismatch | 403 | The subscription belongs to a different environment. |
| 4010 | subscription.not_found | 404 | The subscription doesn’t exist. |
| 4020 | subscription.invalid_state | 409 | Not allowed in the subscription’s current state (e.g. test-fire on an inactive subscription). |
| 4021 | subscription.invalid_transition | 409 | The requested state change isn’t allowed. |
| 4030 | subscription.invalid_secret | 400 | The signing secret doesn’t meet requirements (min. 32 bytes). |
| 4031 | subscription.invalid_overlap | 400 | The rotation overlap window is invalid. |
| 4032 | subscription.invalid_callback_scope | 400 | A requested callback scope isn’t allowed. |
| 4033 | subscription.invalid_url | 400 | The receiver URL is not allowed. |
| 4040 | subscription.challenge_failed | 422 | The endpoint failed the registration challenge. |
| 4050 | subscription.not_licensed | 403 | Webhooks aren’t included in your plan. |
Validation errors
Section titled “Validation errors”Model-binding failures (malformed JSON, wrong types, missing required fields)
return the standard ASP.NET validation problem — a 400 with an errors
dictionary keyed by field name:
{ "status": 400, "title": "One or more validation errors occurred.", "errors": { "activationCode": ["The activationCode field is required."] }}