API reference
Retries
These are the rules for resending each kind of call, what to do after each failure, and the timeout and backoff Snapcaster recommends.
Each kind of call
Section titled “Each kind of call”When a call times out or its connection drops, you cannot tell whether Snapcaster applied it. Each kind of call has one thing that makes resending it safe.
| Call | Resend it with | What the resend returns |
|---|---|---|
Any GET | Nothing extra, because a read changes nothing | The current state, so a GET is always safe to retry |
| A listing write | The same body and the same asOf on every item | noop for an item Snapcaster already applied and applied for one it did not. See Retry a write whose response was lost |
| A store update | The same body | The same result, because the update sets values rather than adding to them |
| An order command | The same Idempotency-Key, order, operation and body | The original HTTP status and the same JSON value, under the rules in Calls with an Idempotency-Key |
| A sandbox buyer operation | The same Idempotency-Key and body | The original HTTP status and the same JSON value |
| The webhook test | The same Idempotency-Key | The same event_id, and Snapcaster sends nothing more |
| The sandbox test purchase | The same Idempotency-Key and body | The same test_purchase_ref, and the sandbox buyer never pays twice |
The listing writes are POST /listings, POST /listings/bulk, DELETE /listings and POST /listings/purge.
They take no Idempotency-Key, because the asOf on each item does that job.
The store update is PATCH /me, which takes no Idempotency-Key either.
The order commands include PATCH /orders/{orderId}/fulfillment, POST /orders/{orderId}/cancel and POST /orders/{orderId}/refunds, and every other order operation that is not a GET.
The webhook test is POST /webhooks/test, and the test purchase is POST /sandbox/test-purchases.
Calls with an Idempotency-Key
Section titled “Calls with an Idempotency-Key”Every order command, every sandbox buyer operation, POST /webhooks/test and POST /sandbox/test-purchases require a UUID Idempotency-Key.
A call without one returns HTTP 400 IDEMPOTENCY_KEY_REQUIRED.
- Choose a new UUID for each new operation, and keep it for every retry of that operation.
- Before the first send, save the key with the operation in durable storage, such as the database row that records the command. A retry after a crash or restart then reads it back and sends the same key.
- A replay returns the original HTTP status and the same JSON value, even if the order has changed since.
A replayed command that already went through returns its first success, so it never returns HTTP 422
INVALID_TRANSITION. - The replayed JSON can list object keys in a different order, so compare parsed values, not raw bytes.
- Read the current state with
GET /orders/{orderId}, not from a replay. - Keys remain valid for the lifetime of the order.
- The same key with changed contents returns HTTP 409
IDEMPOTENCY_CONFLICT. A key the seller already used for a command in the Snapcaster dashboard also returns HTTP 409IDEMPOTENCY_CONFLICT. - A concurrent request with the same key returns HTTP 409
REQUEST_IN_PROGRESSwithRetry-After.
What to do after each failure
Section titled “What to do after each failure”| Failure | What to do |
|---|---|
| No response, a timeout, or a dropped connection | After a backoff, resend the same call the way Each kind of call gives for its kind |
HTTP 429 RATE_LIMITED | Wait Retry-After seconds, then resend the same call |
HTTP 409 REQUEST_IN_PROGRESS | Wait Retry-After seconds, then resend with the same key |
HTTP 429 ADDRESS_VERIFICATION_RETRY_TOO_SOON | Wait until a minute has passed since the failed check, then retry it |
HTTP 500 INTERNAL_ERROR or another 5xx | Resend the same call after a backoff. If it keeps failing, email info@snapcaster.gg with the X-Correlation-ID response header |
HTTP 503 TEST_PURCHASE_NOT_AVAILABLE | Do not retry. Email info@snapcaster.gg to place the test purchase |
| Any other 4xx | Do not resend it unchanged. Fix the request using the error’s code and the operation’s reference |
A per-item rejected result on a listing write | Do not resend the item unchanged. Act on its code from the per-item failures in Error codes |
Snapcaster sends Retry-After, a whole number of seconds, with every HTTP 429 RATE_LIMITED and HTTP 409 REQUEST_IN_PROGRESS.
On a metered listing write, Retry-After is the time left in the current one-minute window of the listing rate limit.
If a RATE_LIMITED or REQUEST_IN_PROGRESS response reaches you without Retry-After, for example because a proxy dropped the header, fall back to the backoff below.
HTTP 429 ADDRESS_VERIFICATION_RETRY_TOO_SOON carries no Retry-After, and its message says how many seconds remain.
Every response carries an X-Correlation-ID header, which identifies the request when you contact support.
Recommended timeout and backoff
Section titled “Recommended timeout and backoff”Neither the contract nor Snapcaster sets a client timeout, an attempt count, or a backoff. These values are recommendations, not server rules, and the catalog sync sample uses them.
- A 30-second timeout on each request.
- At most 5 attempts per request, the first included.
- After a timeout, a dropped connection, or a 5xx, a random wait of up to 2, 4, 8, and then 16 seconds before attempts 2 to 5. If you allow more attempts, cap the wait at 30 seconds.
- After HTTP 429
RATE_LIMITEDor HTTP 409REQUEST_IN_PROGRESS,Retry-Afterplus up to 1 random second. - After HTTP 429
RATE_LIMITEDthat reached you withoutRetry-After, the same wait as after a 5xx.
When the attempts run out, stop and report the error.
A later resend with the same key, or the same body and asOf, is still safe.
Need help?
The email includes this page and selects sandbox as the environment. Update it if you need help with production.
Never include an API key or signing secret in the message.