Volumedocs

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.

On this page