Skip to content
EntitlerDocs

Errors

Read a refusal's status, code and reason, and decide whether to fix the request, retry or tell the customer.

A request Entitler refuses answers an HTTP status from 400 up and a body that says why:

{
  "error": {
    "code": "NotFound",
    "reason": "CUSTOMER_NOT_FOUND",
    "parameters": {}
  }
}
  • code is the kind of refusal, one of the names below. It sets the HTTP status.
  • reason is the exact refusal, in capitals, such as CUSTOMER_NOT_FOUND. Branch on the reason; it is stable.
  • parameters add detail, such as field for the field that was wrong or capability for the capability a plan lacks.

Every answer, refusals included, carries an x-request-id header. Quote it when you contact support.

Refused usage is not an error: a gated report that doesn't fit answers 200 with the outcome USAGE_OUTCOME_REFUSED. See Usage and meters.

Codes and statuses

StatusCodeMeaningRetry?
400InvalidArgument, FailedPrecondition, OutOfRangeThe request is malformed, or the customer or your plan isn't in a state that allows itNo: fix the request
401UnauthenticatedThe credential is missing or invalidNo
403PermissionDeniedThe credential may not do thisNo
404NotFoundThe customer, feature or other resource doesn't existNo
409AlreadyExists, AbortedIt exists already, or a concurrent change wonRead again, then retry
429ResourceExhaustedA rate limit or allowance was reachedAfter Retry-After
499CancelledThe request was cancelledYes
500Internal, Unknown, DataLossSomething failed on Entitler's sideYes, if safe to repeat
501UnimplementedNo such route or methodNo
503UnavailableA service is briefly unavailableYes
504DeadlineExceededThe request took too longYes, if safe to repeat

Limits and retries says which requests are safe to repeat.

Reasons you will meet

ReasonWhat to do
CREDENTIAL_REQUIREDSend a key or token in Authorization: Bearer.
KEY_INACTIVEThe key was revoked, has expired or doesn't exist. Use another.
CUSTOMER_TOKEN_INVALIDThe customer token has expired or is malformed. Mint a new one.
IDENTITY_TOKEN_INVALIDThe identity token failed verification, or was sent beside a credential that can't take one.
ORIGIN_NOT_ALLOWEDA browser sent a secret key, or a publishable key from an origin not listed on it.
PERMISSION_DENIEDThe credential lacks the permission, or a customer token named another customer.
CUSTOMER_REF_INVALIDme was sent with a credential that has no customer of its own, such as a secret key.
CUSTOMER_NOT_FOUNDRegister the customer, or send "register": true where the route takes it.
FEATURE_NOT_FOUNDNo feature has that key in the catalogue the customer is served.
EXTERNAL_ID_KEYWORD_RESERVEDme can't be an external ID.
CUSTOMER_LIMIT_REACHEDYour Entitler plan's customer limit is reached.
CAPABILITY_REQUIREDYour Entitler plan lacks the capability in parameters.capability.
USAGE_FEATURE_NOT_METEREDUsage can only be reported for metered features.
USAGE_KEY_MISMATCHThe idempotency key was used for a different report. Use a new key.
IDEMPOTENCY_KEY_REUSEDThe idempotency key was used for a different request. Use a new key.
USAGE_NOT_FOUND, HOLD_NOT_FOUNDNo report or hold with that ID for this customer.
HOLD_SETTLED, HOLD_RELEASED, HOLD_EXPIREDThe hold is already closed. Report the usage instead if the work finished.
GRANT_LIMIT_REACHEDThe customer holds the most grants allowed. Revoke one first.
AS_OF_NOT_ALLOWEDas_of works only in test environments.
CUSTOMER_TOKEN_SCOPE_INVALIDName scopes from the list.
API_RATE_LIMITED, USAGE_RATE_LIMITEDToo many requests. Wait the Retry-After seconds.
API_ALLOWANCE_REACHEDYour environment's request rate is used up for now. Wait the Retry-After seconds.

In the SDKs

The SDKs throw an EntitlerError. A refusal carries the same fields, with requestId from x-request-id and retryAfter from Retry-After: in TypeScript it is an ApiError, and in Swift EntitlerError.api(APIError). A request that never received an answer is a connection or timeout error instead, with none of those fields.

Edit this page on GitHub