Core concepts

Idempotency

Networks fail. Idempotency lets you retry a create without creating it twice: an Idempotency-Key for any create, and externalRef for invoices, which never double-bills.

Idempotency-Key#

Send Idempotency-Key: <unique string> on these requests:

  • POST /customers
  • POST /invoices
  • POST /webhook-endpoints

Keys are at most 255 characters (longer gets 400 invalid_idempotency_key). Flux keeps each key for 24 hours, separately for each API key.

curl -X POST "$FLUX_BASE_URL/api/v1/customers" \
  -H "Authorization: ApiKey $FLUX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: create-customer-ws_42" \
  -d '{
  "customerType": "company",
  "companyName": "Leadway Group",
  "email": "finance@leadway.example",
  "externalRef": "ws_42"
}'

How Flux treats a repeated key#

When you send a key that was used beforeFlux
With the same request (method, path and body)Replays the first response, status and body, with the header Idempotent-Replayed: true. Nothing runs again.
With a different requestRefuses it: 422 idempotency_key_reused.
While the first request is still runningRefuses it: 409 idempotency_in_progress. Wait a moment and retry.
After the first request failed with a 5xx or an exceptionRuns it: the key wasn't kept. Retrying with the same key is safe.
After the first request failed with a 4xxReplays that 4xx. Fix the request and send it with a new key.

Choosing keys#

  • Derive the key from your own ids, such as create-customer-ws_42, or generate a UUID and save it before sending, so a retry after a crash uses the same key.
  • Use a new key for each distinct operation. Reusing a key for a different body is refused.
  • Other POSTs (links, checkout, test, redeliver, rotate-secret) don't take a key. Links and checkout are safe to repeat. Rotating twice gives two new secrets, and only the last one works.

externalRef: never double-bill#

POST /invoices is also idempotent on externalRef, permanently, not just for 24 hours:

  • If no invoice in the organization has that externalRef, Flux raises one and returns 201.
  • If one exists, Flux returns it with 200, in its current state, and raises nothing. This holds even for two requests that arrive at the same moment.

Use a stable id for what you're billing: your customer id and the billing period, such as ws_42-2026-11. This is the recommended way to avoid double billing. See Bill without double billing.

Customers work differently

A customer's externalRef is unique too, but a repeat isn't replayed: POST /customers with a used externalRef gets 409 conflict. Look the customer up with GET /customers?externalRef= first, or send an Idempotency-Key.