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… | Response | What it tells you |
|---|---|---|
| …within 15 seconds, after it already created a ticket | 400 {"error":"cannot reuse quote token"} | The first request did create a ticket. |
| …after 15 seconds | 400 {"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:
- Wait until your own request has fully timed out, so it is no longer in flight.
- Look the ticket up by its reference:
The filter is an exact match and returns zero, one or several tickets. Add
curl -X GET "https://api.sandbox.avenia.io:10952/v2/account/tickets/?externalId=your-reference-id" \
-H "Authorization: Bearer eyJhdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"subAccountIdif the ticket belongs to a sub-account. - A ticket came back: don't create it again. Follow it with
GET /v2/account/tickets/{ticketId}or through webhooks. - 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 anUNPAIDticket; repeating it returns400and changes nothing. - Webhook events keep the same
event.idwhen they are delivered again or resent. Use it to process each event once — see Webhooks in Practice.