Skip to main content

Authentication and Errors

The API key

Retail sends one header on every request:
X-API-Key, not Authorization: Bearer. It is a plain shared secret, not an OAuth token. An integration that reads Authorization answers 401 to every call, and both sides’ unit tests still pass. Header names are case-insensitive, so x-api-key is the same header.
Gomry generates the key. It is 32 random bytes, delivered to you once over a secure channel. You never choose it, which lets us guarantee its strength and rotate it without asking you to redeploy code. Your integration must:
  1. Fail closed. If no key is configured on your side, reject every request. An unset key must never mean “allow everyone”: POST /orders spends real money.
  2. Compare in constant time, so a key cannot be guessed one character at a time.
  3. Accept more than one key. During a rotation both the old and the new key are live for a while. A second key also lets you give a tester access without sharing Retail’s own.
  4. Answer 401 for a missing or wrong key, with the error body below.
Node.js

Error format

Answer every failure with a JSON body in this shape:
message is for humans and goes into Retail’s logs. Never put a buyer’s email, address or a barcode in it.

404 has a meaning

Retail treats 404 as an answer, not a failure:
  • Listings: a listing that was bought disappears. It does not report quantity 0.
  • Fulfilment, credentials: you do not know this order yet.
  • Venue map: treated as “no map”.
Every other non-2xx status is a failure, and Retail never treats a failure as “nothing there”.

429 pauses Retail’s calls to you

When you answer 429, Retail pauses its page-render and background calls to you, from every instance, until the time you give. Checkout calls still go through, so a buyer who is paying is not stranded by a catalog sync. Give the time in either of these forms. Retail reads them in this order:
  1. A Retry-After header, in seconds or as an HTTP date.
  2. error.retryAfter in the body, as an ISO 8601 timestamp.
Without either, Retail assumes you will take calls again after the current minute.
429
If your supplier limits calls per application, across all endpoints, say so when you go live. Retail keeps a shared per-minute budget per supplier and gives checkout and buyer-facing calls priority over background sync.

Do not retry inside a call

Your integration must not retry internally on any endpoint. Retries belong to Retail, because only Retail knows whether an operation is safe to repeat:
  • On listings, a slow success is worse than a fast failure. The buyer’s page has already given up and rendered the event as unavailable.
  • On place order, a retry can buy the ticket twice. See Place order.

Time budgets

Retail aborts a call after these limits. A reply after the limit is discarded. A timed-out POST /orders is not a failure to Retail. It is an unknown outcome, resolved by searching for the reference.