Idempotency
A network timeout tells you nothing: your request may have been processed, or it may not. Retry blindly and you risk charging a customer twice. Idempotency keys remove the ambiguity.
Send an Idempotency-Key header on every write:
curl -X POST $TMBILLING_URL/v1/businesses/$BIZ/customers \
-H "Authorization: Bearer $TMBILLING_API_KEY" \
-H "Idempotency-Key: 8f14e45f-ea6c-4a1f-b0ba-9a1d1c4b2f30" \
-H "Content-Type: application/json" \
-d '{ "email": "[email protected]" }'
Use any unique string — most people use a UUID per logical operation. Generate it before your first attempt and reuse the same value for every retry.
Retry safely
tmbilling runs the first request with a given key normally and stores its response. A later request with the same key does not run the handler again. You get the stored response, with:
Idempotent-Replayed: true
So when your client times out and retries, it gets the original answer: the same customer id, the same invoice, the same charge.
Retry within 24 hours
tmbilling keeps a finished request's key and response for at least 24 hours. Retry within that time and you get the stored response. After it, the key can be removed, and a request that uses it again runs as a new request. A retry loop that gives up within minutes is well inside the window; never reuse a key for a different operation days later.
Understand how tmbilling scopes a key
tmbilling scopes each key to the organization that used it, so two organizations can use the same string without colliding.
Within that scope, it binds the key to a fingerprint of the request — the method, the path and the
body. Reuse a key with a different payload and you get 409 with an idempotency_error, because
your client believes it is retrying while actually asking for something else.
create-customer, is identical for every caller and
collides. Derive it from the thing you are creating, or generate a fresh UUID per attempt.Handle two replies that surprise people
A replay of a secret-minting request returns 409, not 200. Some endpoints return a value
that exists only once: an API key secret, a checkout link carrying a bearer token, a rotated
webhook signing secret. tmbilling deliberately does not store those responses, so a replay cannot
hand the secret out again. The 409 tells you the original request succeeded — look the resource
up rather than retrying.
A crashed first attempt returns 409 with instructions. If the first request using your key
died after making a durable change but before recording its response, tmbilling can neither replay
it nor safely re-run it. It returns 409 explaining the situation and asks for a fresh key,
because the durable change already happened.
Know which requests need one
Every write: POST, PATCH, PUT and DELETE. Reads are already idempotent and ignore the
header.
tmbilling deduplicates inbound provider webhooks separately, by the provider's own event id, so a gateway that delivers the same notification twice never settles an invoice twice.
Related
Authentication
Authenticate with a bearer API key per organization, scoped to test mode or live mode, and learn what the mode check refuses and why that protects your data.
Errors
Read one error format across the whole API, branch on a small set of error types, and know from the status code whether anything was processed before it failed.