Skip to content

Errors

Errors use application/problem+json:

{
"type": "https://docs.luxorr.io/errors#invalid_request",
"title": "Invalid request",
"status": 400,
"code": "invalid_request",
"detail": "recipient.phone is required",
"errors": [
{ "field": "recipient.phone", "code": "required", "message": "recipient.phone is required" }
]
}
Field Meaning
code Stable, snake_case. Use it in your logic. New codes can be added; existing codes do not change.
status HTTP status.
title Short label for the code.
detail Description of this occurrence. Log it; do not parse it.
type Link to the code on this page.
errors Validation errors: one entry per field, each with a code.

Some errors add fields: currentStatus on not_editable and not_cancellable, orderId on external_order_id_conflict.

Validation errors are never 5xx. On a 5xx, retry; for a POST, reuse the Idempotency-Key.

400. The request is malformed: missing required field, invalid JSON, wrong value type, unreadable ID in the query or body, limit outside 1–100, unknown cursor, or a timestamp with an unencoded +. errors[] lists each field. Fix the request and send it with a new Idempotency-Key.

A delivery correction is validated after merging, so errors[] can name a recipient.* field you did not send, such as a missing stored recipient.address.postalCode. Send that field.

A malformed ID in the path answers 404 not_found, for example GET /orders/not-a-uuid.

413. The request body is larger than 10 MB. Nothing runs. A personal-link batch of 1,000 recipients fits well under it; split anything larger.

400. A POST without an Idempotency-Key header, or with a blank one. See idempotency.

400. The Idempotency-Key header is longer than 255 characters. Nothing runs. Send a shorter key, such as a UUID. See idempotency.

415. The request body is not sent as application/json, for example as text/plain or a form. Nothing runs. Send JSON with Content-Type: application/json.

406. The Accept header rules out application/json. Nothing runs. Send Accept: application/json, or no Accept header. Catalog images are exempt.

401. The key is missing, malformed, unknown or revoked, API access is switched off, or the key is for the other environment. Do not retry.

403. The key lacks the scope this endpoint needs: CATALOG, ORDERS or PERSONAL_LINKS. detail names it. See keys.

404. No record visible to this key. Records of another tenant or outside the key’s brands, and path IDs that are not UUIDs, answer the same way.

405. The path exists, but not with this HTTP method.

429. More than 300 requests in a minute from this key, or 600 image requests from one IP. Wait for the Retry-After header’s seconds. See rate limits.

422. The Idempotency-Key was used before with a different request. Use a new key for a new request.

409. A request with this Idempotency-Key is still running. Nothing runs a second time. Retry with the same key and body after a few seconds: you get the first request’s answer once it is stored. See idempotency.

422. An order with no campaignId must name a brandId.

422. The brand does not exist, belongs to another tenant, or is outside the key’s brands.

422. An order names both campaignId and a brandId that is not that campaign’s brand. Leave brandId out, or send the campaign’s brand. errors[] names brandId.

422. The campaign does not exist, belongs to another tenant, or is outside the key’s brands.

422. The campaign is not active: it is still being prepared, or it has completed.

422. The campaign does not offer this gift.

422. The gift cannot be ordered or offered: it is not published, or it is internal.

422. A personal-link batch names a product that is not in the catalog.

422. The gift cannot be delivered to the recipient’s country. Check available in the catalog for that country.

422. The variations are not one valid value for every dimension of the gift.

422. A required custom field of your tenant has no answer, or an answer does not fit its field, such as a dropdown value that is not one of its options. detail and errors[] say which. An answer whose fieldId names no field of your tenant is ignored, not refused. GET /me lists your fields in tenant.customFields, with each one’s type, options and whether it is required.

422. managerEmail on an order names no active member of your team. In a personal-link batch the same code rejects only that recipient, as a field code on managerEmail.

422. A delivery correction changes address.country. The country cannot change; cancel and place a new order, or message Luxorr.

422. A personal-link batch sent brandId with an empty productIds.

422. A personal-link batch has no recipients.

422. A personal-link batch has more than 1,000 recipients. Split it.

409. The campaign has no stock left for these variations. Offer the player another gift.

409. Your tenant already has an order with this externalOrderId. orderId names it when the key can see it. If you meant to retry, use the original Idempotency-Key.

409. Delivery details can change only while the order is PROCESSING. currentStatus says where it is now. Message Luxorr instead.

409. The order or link can no longer be cancelled. currentStatus says where it is now. For an order already SENT, message Luxorr. Cancelling something already CANCELLED is not an error: it answers 200 with the record as it is.

409. The record changed since you read it. Read it again and retry with the new version.

500. Server error. Retry; for a POST, reuse the Idempotency-Key. If it continues, contact Luxorr with the time and request.

Inside errors[], each entry has its own code:

Code Meaning
required The field is missing or blank, such as recipient.address.postalCode for a country that uses postal codes.
invalid The value is malformed or not allowed.
too_long The value is longer than the field allows.
duplicate The same email appears earlier in the same personal-link batch.
not_enabled The locale is not enabled for your tenant.
manager_not_found A personal-link recipient’s managerEmail names no active member of your team.
not_allowed_with_catalog_selection A personal-link batch sent campaignId together with brandId or productIds.