Errors

Every error returned by an Extole API follows a consistent JSON structure with a stable code field for programmatic handling. This page documents the error shape, the HTTP status codes Extole returns, the most common error codes by category, and guidance for retries, async events, and support escalation.

Quickstart

{
  "unique_id": "6941049359794271324",
  "http_status_code": 403,
  "code": "missing_access_token",
  "message": "No access_token was provided with this request.",
  "parameters": {}
}

When handling errors:

  • Branch on code. It is a stable string enum suitable for switch or pattern-match logic.
  • Display message to humans where appropriate.
  • Log unique_id and include it in any support ticket.
  • Inspect parameters for sub-error details when present.

Error Response Structure

FieldDescription
unique_idA unique identifier Extole logs against this error. Include it when contacting support.
http_status_codeThe HTTP status code returned. Mirrors the response status.
codeA stable string enum identifying the error class. Use this for programmatic handling.
messageA human-readable description of the error. Intended for display or logs.
parametersObject containing sub-error detail. Keys vary by error class.
parameters.reasonWhen present, a string enum naming a more specific sub-error.
parameters.descriptionWhen present, a human-readable description of the sub-error.

For example, a validation error often carries parameters.description with the specific field and condition that failed:

{
  "unique_id": "6941047907334948670",
  "http_status_code": 400,
  "code": "validation_error",
  "message": "Validation failed",
  "parameters": {
    "description": "must not be null"
  }
}

Asynchronous Error Handling

Consumer event endpoints (POST /events, GET /events/{event_name}) always return HTTP 200 to avoid blocking the participant's session, regardless of whether the event was processed successfully.

To detect processing errors on these endpoints, inspect the response headers:

HeaderMeaning
X-Extole-Error-MessageHuman-readable error message, set when processing failed.
X-Extole-TokenThe current access token value (which may have rotated during the call).
X-Extole-Cookie-ConsentCookie consent status.
curl -i https://acme.extole.io/events \
  -H "Content-Type: application/json" \
  -d '{"event_name":"purchase","data":{"email":"[email protected]"}}'

HTTP/1.1 200 OK
X-Extole-Token: DI3ZCZ97V3V1F9SUA9T
X-Extole-Error-Message: invalid_email

For all other endpoints, errors return non-200 status codes with the standard error body.

Rate Limiting

A 429 response with code too_many_requests indicates that the caller has sent too many requests in a window. Extole applies two limits:

  • 100 requests per minute per IP address or token.
  • 10 requests per second per identified person.

The /v6/async-events endpoint is not rate-limited and is the recommended path for high-volume event ingestion.

Typical causes of rate limiting:

  • A misconfigured tag or integration sending duplicate or dummy events.
  • A customer data platform (CDP) misconfigured to forward more data than expected.
  • Load testing or security scans (expected and unavoidable in those scenarios).

When implementing retry logic:

  • Use exponential backoff with jitter. A reasonable starting pattern: 1s, 2s, 4s, 8s, capped at 30s.
  • Avoid retrying immediately. Even a 100 ms retry can keep the limit tripped.
  • Distinguish retryable from non-retryable errors. 429 and 500 are retryable; 400, 401, 403, 415 are not (the request is the problem, not the platform).

If your integration encounters rate limiting that does not match these patterns, contact [email protected].

Retry Guidance

StatusRetryableNotes
400NoThe request itself is invalid. Fix and resubmit.
401After refreshAcquire or refresh a token, then retry.
402NoFeature is not enabled. Contact your Extole guide.
403NoToken lacks scope or resource is forbidden. Retrying will not help.
415NoSet Content-Type: application/json and retry once.
429YesExponential backoff. Prefer /v6/async-events for high-volume event flow.
500YesTransient. Exponential backoff. Escalate if persistent.

For state-changing operations (POST, PATCH, PUT, DELETE), be cautious about retrying after a 5xx. The operation may have succeeded server-side even if the response did not return. Where the API supports idempotency, use it.

Debugging

Set the X-Extole-Debug header to a value between 1 and 3 on any request to receive expanded diagnostic information in the response. Higher levels return more detail.

curl https://api.extole.io/v6/async-events \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Extole-Debug: 2" \
  -d '{...}'

Debug responses can be verbose; use level 1 in routine logging and reserve 2 or 3 for active troubleshooting.

Support and Escalation

When contacting [email protected] about an error:

  • Include the unique_id from the error response. Extole correlates this with internal logs.
  • Include the HTTP method, full request path, and a UTC timestamp.
  • Include the response body verbatim.
  • Do not include the access token in unredacted form.

For endpoint-specific behavior or errors not documented here, consult the API reference for the endpoint in question. Each endpoint enumerates the errors it can return.

HTTP Status Codes

StatusMeaningTypical action
200Success. For consumer event endpoints, see Asynchronous error handling.Continue.
400Bad Request. The request body, parameters, or headers are invalid.Fix the request and retry.
401Unauthorized. Missing or invalid access token.Acquire or refresh a token.
402Payment Required. The feature is not enabled for this client.Check provisioning with your Extole guide.
403Forbidden. The token does not carry the required scope, or the resource is not accessible.Use a token with the correct scope.
415Unsupported Media Type. The Content-Type header is missing or wrong.Set Content-Type: application/json.
429Too Many Requests. Rate limit exceeded.Back off exponentially and retry.
500Server Error. Extole encountered an unexpected condition.Retry with backoff. If persistent, log unique_id and contact support.

Common Errors by Category

Each endpoint's API reference lists the full set of errors that endpoint can return. The codes below are the most common ones an integrator will encounter, grouped by area.

Authentication and authorization

CodeStatusCause
missing_access_token403No access token in the request.
invalid_access_token401Token does not match a known credential.
expired_access_token401Token is past its expiration.
method_unauthorized401Caller is not authorized to use this method.
access_denied403Caller is not authorized for this resource.
scopes_denied403Token does not carry the required scope.
invalid_credentials401Wrong email or password during token creation.
missing_credentials403Token creation called without sufficient credentials.
jwt_authentication_error401JWT signature did not verify.
jwt_error400JWT is malformed or has invalid claims.
invalid_client_id400The client_id is not a known client.
invalid_access_token_duration400Token duration outside the allowed range.
payment_required402Feature not enabled for this client.
sandbox_not_found400The referenced sandbox does not exist.

Validation

CodeStatusCause
validation_error400Generic validation failure. Inspect parameters for the field and condition.
invalid_parameter400A request parameter has an invalid value.
invalid_json400The request body is not valid JSON.
missing_request_body400A required request body is missing.
binding_error400Request parameters could not be bound to the expected schema.
invalid_null400A non-nullable field is null.
unsupported_media_type415Content-Type is missing or unsupported.
invalid_limit400The limit parameter is invalid.
invalid_offset400The offset parameter is invalid.
max_fetch_size_1000400The requested page size exceeds the maximum of 1000.

Persons

CodeStatusCause
person_not_found404The specified person does not exist.
invalid_person_id400The person ID is malformed.
invalid_key_value400A person identity key has an invalid value.
identity_key_value_already_taken400An identity key value is already assigned to another person.
forwarding_profile_is_device400Cannot forward from a device-only profile.
forward_to_profile_is_device400Cannot forward to a device-only profile.
invalid_block_reason400The block reason is not recognized.
data_not_found404The specified person data parameter does not exist.
data_already_exists400A person data parameter with this name already exists.
read_only_name400The data parameter name is read-only.
value_does_not_follow_pattern400Value does not match the expected pattern.
data_values_invalid400One or more data values are invalid.
partner_ids_invalid400One or more partner IDs are invalid.
person_not_identified400The person is not identified; an operation requiring identity was attempted.
person_not_rewardable400The person is not eligible to receive a reward.

Events

CodeStatusCause
missing_event_name400The event name is missing.
event_blocked400The event was blocked by quality, fraud, or time rules.
invalid_event_time_format400The event time format is invalid.
invalid_time_format400A time field is in an invalid format.

Zones

CodeStatusCause
missing_zone_name400The zone name is missing.
invalid_zone_name400The zone name is invalid.
no_creative400No creative was returned for the zone.
invalid_creative_result400The creative result is invalid.
invalid_redirect400The redirect URL is invalid.

Rewards

CodeStatusCause
reward_not_found404The specified reward does not exist.
reward_state_invalid400The reward is in an invalid state for this operation.
reward_type_not_supported400The reward type is not supported here.
reward_supplier_not_found404The specified reward supplier does not exist.
reward_in_not_retryable_state400The reward cannot be retried in its current state.
reward_retry_not_supported400This reward does not support retry.
retry_claimed_reward_not_allowed400A claimed reward cannot be retried.
reward_illegal_state_transition400The requested state transition is not allowed.
period_not_supported400The requested time period is not supported.
period_count_invalid400The period count is invalid.
time_interval_invalid400The time interval is invalid.

Audiences and memberships

CodeStatusCause
audience_not_found404The specified audience does not exist.
missing_audience_id400Required audience ID is missing.
membership_not_found404The audience membership does not exist.

Shareables and shares

CodeStatusCause
share_not_found404The share does not exist.
shareable_not_found404The shareable does not exist.
code_taken400The shareable code is already in use.
code_taken_by_promotion400The code is reserved by a promotion.
code_out_of_range400The code is outside the valid range.
code_illegal_character400The code contains an illegal character.
code_contains_reserved_word400The code contains a reserved word.
shareable_key_taken400The shareable key is already in use.

Batch jobs and files

CodeStatusCause
batch_job_invalid_state_transition400Batch state transition not allowed.
batch_job_delete_not_allowed400Batch cannot be deleted in its current state.
batch_job_locked400Batch is locked.
batch_job_event_name_invalid400The event name for the batch is invalid.
batch_job_name_invalid400The batch name is invalid.
batch_job_tag_invalid400A batch tag is invalid.
batch_job_data_source_empty400The batch data source is empty.
batch_job_unauthorized_scopes403The batch job lacks required scopes.
file_asset_file_processing_error400An error occurred while processing the file asset.
file_asset_input_file_missing400The file asset's input file is missing.
file_asset_invalid_name400The file asset name is invalid.
file_asset_duplicated_name400A file asset with this name already exists.
file_asset_invalid_tags400The file asset tags are invalid.
file_asset_download_error400An error occurred downloading the file asset.
file_asset_not_found404The file asset does not exist.
file_asset_expired400The file asset has expired.
missing_extole_public_key400The Extole public key for encryption is missing.
decryption_error400The file asset could not be decrypted.