Error codes

Errors follow problem+json (RFC 9457). Errors raised by the API gateway also carry the header X-Error-Source: gateway.

Error body

401
HTTP/1.1 401 Unauthorized
Content-Type: application/problem+json
X-Error-Source: gateway

{
  "type": "https://nextx.vn/errors/unauthorized",
  "title": "Please sign in to continue.",
  "status": 401,
  "traceId": "0HN7…",
  "errorCode": "gateway.unauthorized",
  "retryable": false
}

errorCode is stable for machines; title is for people; retryable tells you whether a retry can succeed; include traceId when you contact support.

HTTP status codes

HTTPMeaningHow to fix
400 oauth2.missing_client_idclient_id missing when requesting a token (likewise oauth2.missing_client_secret, oauth2.missing_workspace_id)Send client_id, client_secret and workspace_id as form fields
400 oauth2.unsupported_grant_typeUnsupported grant_typeUse grant_type=client_credentials
401 oauth2.invalid_clientWrong client_id / client_secret, or the client is not confidentialCheck the key pair; contact NextX if the secret must be reissued
401 oauth2.client_suspendedThe app was suspended by NextXContact NextX support
403 oauth2.app_not_installedThe workspace has not installed the app (no consent) — NOT a 404The workspace installs the app and grants the scopes under Connected apps
403 oauth2.module_not_subscribedNo scope left after filtering by the modules the workspace pays forRequest scopes from modules the workspace has, or add the module
401 gateway.unauthorizedBearer token / API key missing, expired or invalid (problem+json, errorCode gateway.unauthorized)Get a new token (TTL 3600s; the response has a refresh_token field, but it is empty)
403 insufficient_scopeOnly on ~25 routes in the gateway scope map: body { error: insufficient_scope, required: <scope> }Request the scope in required + workspace consent
403 Permission required: <scope>Other routes are checked by the service: a missing scope returns 403 with detail "Permission required: <scope>"Request the scope named in detail
404Resource does not existCheck the id / path
429Rate limit exceeded (600 req/min per app by default)Slow down and read the Retry-After header

Missing permission (403)

Routes checked at the gateway return error: insufficient_scope with required (the scope needed). Routes checked by the module return detail like Permission required: <scope>.

403
{ "error": "insufficient_scope", "required": "crm.contacts.view" }

When to retry

Retry only when retryable: true (429, 502, 503, 504), with increasing back-off. Send an Idempotency-Key on writes so a retry never creates a duplicate.