Skip to main content
A network timeout leaves you not knowing whether your request landed. For most APIs that is an inconvenience; for an invoicing API it is a legal problem, because a duplicated invoice can only be undone with a corrective invoice. Idempotency keys remove the dilemma: retrying is always safe.

How it works

Send an Idempotency-Key header on POST /v1/invoices (and any future write that documents the header):
  • The key is any string of 1–255 printable ASCII characters, scoped to your environment. Derive it from something unique on your side (your order id, your job id), or use a UUID.
  • The first request with a key executes normally and its response is stored for 24 hours.
  • A retry with the same key and the same body returns the stored response without executing again, marked with an Idempotent-Replayed: true header. The invoice is issued exactly once no matter how many times you retry.
  • The same key with a different body is rejected with 409 idempotency_conflict: a key names one logical request, not a slot to reuse.
  • While the original request is still running, a concurrent retry answers 409 idempotency_conflict. Wait and retry: once the original completes you get its stored response.

Failures

  • Deterministic rejections (4xx, for example invalid_tax_id) are stored and replayed like successes: retrying the same wrong request repeats the same answer without re-executing.
  • A 503 tax_id_validation_unavailable (census down) releases the key: nothing was persisted, so retrying with the same key re-executes once the census recovers. This is the retry the Retry-After header schedules.
  • If a request ends in a truly unknown state (a crash mid-flight), the key stays blocked with 409 for up to 24 hours rather than risking a duplicate. If you never received a response and the 409 persists, issue with a fresh key after checking GET /v1/invoices for whether the original landed.

What not to do

  • Do not reuse a key across different invoices, even after the previous one succeeded.
  • Do not retry a 409 in a tight loop; use backoff and let in-flight requests finish.
  • Do not skip the header on invoice creation. It is optional in the schema, mandatory in spirit.