Errors & responses
A consistent envelope for every response, success or failure.
Success
{
"success": true,
"data": { "...": "endpoint-specific payload" },
"message": "Events retrieved successfully."
}
success, alwaystrueon success.data, the payload. Search results wrap aheader(echo of your input), acountand aresultsarray; single-item endpoints returnresult.message, a human-readable summary.
Failure
When a business rule fails, success is false and message explains why:
{
"success": false,
"message": "The selected quantity is not available for this ticket."
}
Validation errors (422)
Missing or malformed parameters are rejected with 422 before the request
reaches business logic, so they do not use the envelope. Instead you get a
top-level message and an errors map keyed by field. Nested fields use dot
notation (for example delivery.phone):
{
"message": "The eventId field is required. (and 1 more error)",
"errors": {
"eventId": ["The eventId field is required."],
"delivery.phone": ["The delivery.phone must be a string."]
}
}
Read errors to map each message back to the input that caused it. A field
can carry more than one message, so treat each value as an array.
Authentication
Authentication failures also come back without the envelope:
{ "message": "Unauthenticated." }
Status codes
| Code | Meaning |
|---|---|
200 |
Request succeeded. Check success in the body for business-level errors. |
401 |
Missing or invalid bearer token. |
403 |
The token is valid but your account is not allowed on this endpoint. |
404 |
The resource does not exist, or does not belong to your account. |
409 |
Conflict with the current state of the resource. Read message to tell the cases apart. |
422 |
Validation failed. Read the errors map for the offending fields. |
429 |
Too many requests, slow down and retry with backoff. |
5xx |
Temporary server error, retry with exponential backoff. |
A 200 status does not always mean success. Always inspect the success field, availability, pricing and split-quantity errors are reported there.
Conflicts (409)
409 means the request was well-formed but clashes with the current state. On the
Seller API it covers three cases, told apart by message:
- Duplicate
external_id: a ticket with that id already exists. The response carries the existingticket, so treat a repeatedPOST /broker/ticketsas a safe retry. - Event pending approval: the event you submitted is not approved yet. Wait for the
event.approvedwebhook before posting tickets to it. - Locked ticket: a buyer checkout is holding the listing, so writes are refused until the
sale completes or expires. The body carries
"locked": true. See Locked tickets.
On the Buyer API, POST /orders/create answers 409 when the Idempotency-Key (or the lock
requestId) clashes with an earlier request. The body uses the envelope and data.code tells
the cases apart:
data.code |
Meaning | What to do |
|---|---|---|
IDEMPOTENCY_IN_PROGRESS |
The first request with this key is still running | Wait a few seconds and retry with the same key |
IDEMPOTENCY_KEY_REUSED |
The key was already used for a different ticket, event or quantity | Use a new key for a new order |
IDEMPOTENCY_OUTCOME_UNKNOWN |
The earlier outcome could not be confirmed | Do not retry. Contact support with the key |
See Retry safely with an idempotency key.
Handling errors well
- Always branch on
success, not just the HTTP status. - On
422, read theerrorsmap to highlight the invalid fields, and fix the input before retrying, the same request will fail again. - Surface
messageto your logs; show a friendly message to end users. - Retry
429and5xxwith exponential backoff and a cap. - Do not loop on a
409. Fix the conflict, or queue the change for your next sync cycle. The one exception isIDEMPOTENCY_IN_PROGRESSonorders/create: wait a few seconds and retry with the same key. - Send an
Idempotency-Keyonorders/createand reuse it on every retry of the same order, so a timeout never leads to a second purchase. See the Ticket purchase flow.

API