Idempotency
Send an Idempotency-Key with every POST that creates something, and a retry can never create it twice.
Networks fail in the worst place: after Volume has created your invoice, but before you
heard back. Retrying blindly would create a second one. An Idempotency-Key makes the
retry safe.
curl https://api.paywithvolume.com/v1/invoices \
-H "Authorization: Bearer $VOLUME_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: fund_9f2c:invoice" \
-d '{ "amount": "25.00" }'Send the same request with the same key again and Volume does not create anything. It
answers with the first response, status and body, and adds an
Idempotent-Replayed: true header.
Which requests need one
POST /v1/invoices, POST /v1/checkout_sessions and
POST /v1/test_helpers/checkout_sessions/{id}/pay require one. Without it they are
refused with 400 idempotency_key_required. A key is up to 255 characters.
Choosing keys
Make the key from your own record of what you are doing, not from the attempt. If your
database has a top-up with id fund_9f2c, use fund_9f2c:invoice for its invoice and
fund_9f2c:checkout for its checkout. Then any retry, from a timeout, a crashed worker
or a double-clicked button, lands on the same invoice. A random key per attempt protects
nothing.
Reusing a key
A key belongs to one request. Sending it again with a different body or to a different
path is 409 idempotency_key_reuse_mismatch, not a replay, because Volume cannot know
which of the two you meant. Keys are kept per account and mode: your test and live keys
never collide.
Receiving, not sending
Webhooks are the other direction, and the same idea applies there: Volume may deliver an event more than once. See webhooks.