Errors
Response shape
Section titled “Response shape”Error bodies are JSON. Three shapes are in use; read the machine-readable code from whichever of errorCode / error is present, and treat the human text as display-only.
- Route-level errors — a short object whose code is in
errororerrorCode, with extra fields named in the tables below (detail,required,missing,feature, …). Example:{ "errorCode": "PERMISSION_DENIED", "required": "org.device_identity.update" }. - Result envelope —
{ "isSuccess": false, "message": "…", "errorCode": "…" }, optionally withvalidationErrors(field → messages) andmetadata. - OAuth / OIDC endpoints follow the RFC shape —
{ "error", "error_description" }.
A request that fails outside a route’s own checks is answered with the envelope in PascalCase — { "IsSuccess": false, "Message": "…", "ErrorCode": "…", "Metadata": { "TraceId": "…" } } — with one of these codes:
ErrorCode | Status | Meaning |
|---|---|---|
VALIDATION_ERROR | 400 | Input validation failed; Metadata.ValidationErrors lists { Field, Error } per field. |
DOMAIN_RULE_VIOLATION | 400 | A business rule rejected the request; Message says which. |
OAUTH_SESSION_EXPIRED | 401 | The social sign-in session expired — start the sign-in again. |
ACCESS_DENIED | 403 | The caller may not perform this action. |
NOT_FOUND | 404 | The record does not exist. |
SOD_CONFLICT | 409 | The change would break a separation-of-duties rule. |
INTERNAL_ERROR | 500 | Unexpected error. Quote Metadata.TraceId to support. |
General status meanings:
| Status | Meaning |
|---|---|
| 400 | Validation / malformed request |
| 401 | Unauthenticated (missing/invalid token) |
| 403 | Authenticated but not permitted (e.g. not a member; ORG_SEAL_REQUIRED; tenant conflict) |
| 404 | Not found (or feature disabled) |
| 409 | Conflict (duplicate name/key, cycle) |
| 500 | Unhandled server error |
Role & permission error codes
Section titled “Role & permission error codes”Field: error or errorCode. See Roles & permissions.
| Code | Status | Meaning |
|---|---|---|
ROLE_NOT_FOUND | 404 | The role is not in this organization. (400 on a project invitation whose role key has no active role.) |
ROLE_DUPLICATE_KEY | 409 | The roleKey is already used. |
ROLE_SYSTEM_PROTECTED | 403 | The Owner role (ORG_OWNER) cannot be deleted. |
ROLE_FIXED | 403 | The fixed Roost roles cannot be renamed, changed or deleted. |
OWNER_REQUIRED | 403 | Only the Owner, or someone who holds the Owner-only scope, can assign this role. |
VARIABLE_REQUIRED | 400 | The role needs a variable at assignment (variable names it). |
PERMISSION_DENIED | 403 | The caller lacks the required scope (required), or is adding a permission they do not hold themselves. Also returned when an invitation or an approval-line change is refused for lack of permission. |
SCOPE_NOT_IN_LIBRARY | 400 | A scope in the org, view, platform or user namespace that Axowl does not define. |
LIFECYCLE_NOT_SUPPORTED | 400 | uses, ttl or exp on a role permission. |
USES_NOT_SUPPORTED | 400 | An approval request asks for a finite uses on a scope other than a Roost management operation. Carried at the start of error. |
UPGRADE_REQUIRED | 403 | A plan limit was reached (feature is roles or permissions_per_role). |
Request and configuration codes
Section titled “Request and configuration codes”| Code | Status | Meaning |
|---|---|---|
INVALID_SCOPE | 400 | POST /api/m2m/token: the requested scope includes a scope the key does not hold (scopes lists them). Field: error. |
RANGE_TOO_LARGE · INVALID_RANGE | 400 | Audit query: the range is longer than 90 days (maxDays), or startDate is after endDate. Field: code. |
invalid_ttl_seconds | 400 | POST /permits/issue: ttlSeconds is outside 1–300. Field: error. |
ADDON_REQUIRED | 402 | The action needs an add-on the organization does not own (addon names it) — for example assigning a company device without Advanced Device Trust. Field: error. |
SERVER_NOT_CONFIGURED | 503 | Checkout or account linking is temporarily unavailable. Nothing was charged or sent; try again later. Field: error. |
Sign-in, account and app group codes
Section titled “Sign-in, account and app group codes”Field: failureReason (sign-in), errorCode or error (others).
| Code | Status | Meaning |
|---|---|---|
ACCOUNT_SUSPENDED · ACCOUNT_LOCKED · ACCOUNT_INACTIVE · ACCOUNT_DELETED | 400/401 | The account can’t sign in. |
ACCOUNT_PENDING_DELETION | 400/401 | Deletion was requested; restore with the account-recovery endpoints. |
DELETION_BLOCKED | 409 | Delete or leave the listed organizations first (blockers). |
VERIFICATION_REQUIRED · CODE_INVALID · CODE_THROTTLED | 401/429 | Account deletion or recovery confirmation. |
SOCIAL_PROVIDER_DISABLED | 400 | That provider is off for this app group. |
TESTER_LIMIT_REACHED | 409 | A development app group already has 100 testers. |
LIVE_PAYMENTS_REQUIRE_PRODUCTION | 409 | Development app groups take test payments only. |
PROMOTION_BLOCKED | 409 | A blocking promotion check failed (checks). |
INVALID_SOCIAL_CREDENTIAL | 400 | A required OAuth key field is missing (detail). |
Payment gateway codes
Section titled “Payment gateway codes”Field: error (or confirmError in a test-payment answer).
| Code | Status | Meaning |
|---|---|---|
CUSTOMER_INFO_REQUIRED | 409 | KG Inicis needs the buyer’s name, email and phone (missing). Send name / phoneNumber with the test payment. |
TEST_CHANNEL_CANNOT_CONFIRM | — | Returned as confirmError: on the live platform a test key can be tested, but it is confirmed for sales only on an app group in development. |
PRODUCTS_EXIST | 409 | The app group has products priced for its current collection method. Delete them, switch (or disconnect), then register them again. |
LIVE_SUBSCRIPTIONS | 409 | Live subscribers on the service being left. Switch after they have ended. |
SUBSCRIPTIONS_UNKNOWN | 409 | Subscribers could not be counted; nothing was changed. Try again shortly. |
STRIPE_NOT_READY | 409 | Turning collection on with Application payment integration: the payout account can’t take card payments and payouts yet. |
PAYMENT_SERVICE_REQUIRED | 409 | Turning collection on for an app group with no collection method: choose one first (app_payment or your own gateway). |
PAYMENT_SERVICE_NOT_CONFIRMED | 409 | Turning collection on while your own gateway hasn’t passed its test payment. |
PRODUCTS_REQUIRED | 409 | Turning collection on needs at least one product. |
NOT_OFFERED | 409 | That collection method is not offered (collect_on_behalf, or Application payment integration outside the supported countries). |
INVALID_COLLECTION_RAIL | 400 | collectionRail must be none, app_payment, own or collect_on_behalf. |
FREE_REQUIRED | 400 | Publishing to the marketplace for the first time: say whether the app is free (free: true or false). |
MARKETPLACE_PAID_NOT_READY | 409 | A paid listing needs a confirmed collection method, collection on and at least one product (missing). |
MONEY_LINE_VIOLATION | 409 | The request mixed the two money lines (what your app collects and what you pay Axowl) and was stopped. Body: { "error": "MONEY_LINE_VIOLATION", "detail": "…" }. Nothing was charged; report it to support. |
APP_IS_FREE | 409 | Marketplace checkout or plan change for an app its publisher listed as free — install it directly, no payment needed. |
CURRENCY_FIXED | 409 | Prices must be in the app group’s collection currency (currency): own gateway → its currency, otherwise USD. |
NOT_A_TEST_PAYMENT | 400 | The payment id was not issued as this connection’s test payment. |
Hosted sign-in returns to the portal with error= in the URL: not_public (sign-up closed or app group in development), provider_disabled, bad_provider, credential_changed (the app group’s OAuth key changed during sign-in — start again).