Skip to main content

Idempotency and Retries

A payout must happen once, even when a request times out. This page explains which values protect you from duplicates and how to retry safely.

The quote token is the once-only key​

Every ticket is created from a quoteToken, and one token creates at most one ticket. The token is valid for 15 seconds after the quote.

You re-send a quoteToken…ResponseWhat it tells you
…within 15 seconds, after it already created a ticket400 {"error":"cannot reuse quote token"}The first request did create a ticket.
…after 15 seconds400 {"error":"InvalidFieldError: quoteToken is invalid"}Nothing. The token expired; a ticket may or may not exist.

The same quoteToken is invalid error is returned when the quote and the ticket name different accounts (subAccountId on one and not the other, or two different values).

Creating a ticket from a quote never returns 409, and there is no idempotency header for it. The optional X-API-IdempotencyKey header only takes part in the request signature; it doesn't deduplicate anything. The quote token is the only key the API enforces.

externalId is your reference, not a key​

externalId is free text (up to 68 characters) that Avenia stores on the ticket so you can find it later. Avenia doesn't enforce uniqueness: two tickets created with the same externalId (each from its own quote) are two tickets.

Make it unique on your side — one per operation you intend to run — and you can always look the ticket up by it.

Retrying after a timeout​

If the response to POST /v2/account/tickets/ is lost (timeout, dropped connection) or is a 500, the ticket may already exist. Don't decide from a re-sent token, and don't quote again right away:

  1. Wait until your own request has fully timed out, so it is no longer in flight.
  2. Look the ticket up by its reference:
    curl -X GET "https://api.sandbox.avenia.io:10952/v2/account/tickets/?externalId=your-reference-id" \
    -H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    The filter is an exact match and returns zero, one or several tickets. Add subAccountId if the ticket belongs to a sub-account.
  3. A ticket came back: don't create it again. Follow it with GET /v2/account/tickets/{ticketId} or through webhooks.
  4. The list is empty: request a new quote and create the ticket again with the same externalId.

Other requests​

  • Quotes have no side effect. Request a new one whenever you need it.
  • Cancel (PATCH /v2/account/tickets/{id}/cancel) only acts on an UNPAID ticket; repeating it returns 400 and changes nothing.
  • Webhook events keep the same event.id when they are delivered again or resent. Use it to process each event once — see Webhooks in Practice.