Skip to main content
Most integration trouble is not transport or auth — it is holding a partial model of what happens between “a buyer appoints an agent” and “a ticket is issued”. This page is that model, with the literal values you will see.

The two objects

A payment is a purchase attempt that reached the money path. A watch is a standing instruction to buy later — when a drop opens, or when a sold-out tier is restocked. A buy-now purchase creates only a payment; a queued purchase creates a watch that later creates a payment.

Watch lifecycle

status is exactly one of: queued · firing · fired · failed · cancelled · expired. What fires a watch: the tier becoming buyable. That happens when you PATCH onSaleStart/onSaleEnd/availableCount/sellable (the change fires it within about a second), or when a scheduled sweep notices a clock-crossing drop (within five minutes). You do not need to tell us to fire it. failed is terminal. A refusal produced by the buyer’s own mandate — spend cap, quantity guardrail, scope — will never succeed on retry, so we do not retry it, and the watch leaves the queue. Only genuinely transient errors return a watch to queued. This is why a failed watch “disappears”: it is finished. You receive watch.failed with the reason so you can tell the buyer.

Payment lifecycle

status is exactly one of: pending · authorized · declined · error.
  • Fulfil on authorized, and only on authorized. For ticketing it is terminal: the seat is sold, the buyer’s authority is consumed, and the funds are captured to your PSP moments later.
  • error is not a decline. It means the outcome is genuinely unknown (a timeout mid-charge). The money may or may not have moved, so the seat stays held and the buyer’s allowance stays consumed until a human reconciles it against the PSP. Never treat it as a failure, and never retry it as a fresh purchase.
  • A row can read pending for a second or two before its result lands — which is why a poller must not advance its cursor past a non-terminal row. Webhooks have no such race: they fire only once the payment is authorized.

Telling the five common cases apart

When you are stuck

GET /v1/integration/payments/{intentId} returns the intent, the result, and the full durable event trail — every routing attempt, refusal and capture, in order. That trail is the authoritative account of what happened, and it is readable with the same merchant token you already hold: you should not need to ask us to query a database.