What a request key actually promises
Both systems let a caller attach a key to a create request so that a repeat of the same request returns the first answer instead of doing the work twice. In Xero this is the Idempotency-Key header, which applies to POST, PUT and PATCH requests; Xero says a key is kept for six minutes from its first use, can be at most 128 characters, and is checked per app. Re-using a key with a different request body or address returns a 400 error. In QuickBooks Online the equivalent is a request id passed as a query parameter, up to 50 characters for ordinary calls and unique across the requests made for a company.
These are useful retry helpers. They are not a duplicate-prevention design, because each has limits that a real integration will eventually cross.
Where each key stops protecting you
Xero's six minutes are short compared with a queue that retries after an hour, or a person who re-runs a failed job the next morning: a repeat after the key has expired is simply a new request. Xero also says an error that was cached against a key is returned again on a re-run even after the underlying problem is fixed, and that repeated calls still count toward rate limits because idempotency is checked afterwards. For QuickBooks Online, Intuit support has said the retention period of a request id is not published, so no design should assume a particular window.
- A different key for the same business operation is a different operation to the vendor.
- A key generated per attempt, rather than per source order, protects nothing across attempts.
- Neither vendor documents protection against two different callers creating the same invoice with different keys.
- A lost response after a successful create looks identical to a failed create unless you can look the invoice up.
The lasting control is a stored identity and a lookup
Give every source order an identifier that never changes and carry it into a field on the invoice that can be searched. Xero treats the invoice number of a sales invoice as a unique code and generates one if you leave it out, while the reference field is a free text field; QuickBooks Online's document number is limited to 21 characters. Which field you use is a design choice to settle with the person who owns invoice numbering, because changing numbering has its own consequences.
Before any create, search for that identity and handle zero, one and many matches as set out in the guide "Invoice creation timed out: reconcile the unknown result before retrying". A request key then becomes a second layer that smooths short-lived retries. Two runs that start together can both find nothing and both create, so also record a durable per-order claim, with a unique key or a lock, before the create call.
A safe first investigation
Use a Xero demo company or a QuickBooks sandbox company, never live invoices. Create one invented invoice with a key, repeat the identical call within a minute, and count the invoices. Repeat after the documented key lifetime has passed, and count again. Then run the automation twice at the same moment for the same invented order. The three counts show which layer of protection your automation really has.
- Record the invoice count after each step, not just the call responses.
- Do not delete or void anything to make a test pass.
- Keep keys and credentials out of any note you share.
What fits, what does not, and how it is accepted
If your automation lacks the identity or the lookup, the fixed-price job "Stop a retried automation from creating a second invoice in Xero or QuickBooks Online" is from £395. It is an untested published price; scope and price are confirmed after your enquiry, and payment follows the agreed checks and your sign-off. It is accepted when replaying the same three invented orders three times, once after a simulated lost response, leaves exactly three invoices, and a concurrent double run leaves one invoice per order.
It does not remove duplicates you already have: choosing which invoice stands, voiding or deleting is a decision for your finance owner. It also does not cover other failures such as dropped orders or wrong amounts. Your own developer can implement everything described here without us; this guide is written from vendor documentation read on 11 October 2026 and nothing in it was run against a live account. Send invented examples and counts first, never credentials, bank details, invoices or customer records; real records are handled only after written agreement through a secure handoff.
Sources and limits
- Xero: idempotent requests Checked 2026-10-11.
- Xero accepts an Idempotency-Key header on POST, PUT and PATCH requests and ignores it on other methods.
- A key is kept for six minutes from its first use, may be at most 128 characters, is checked per app, and re-using it with a different request returns a 400.
- An error cached against a key is returned again on re-run, and idempotency is checked after rate limits so repeated calls still count toward them.
- Xero advises checking with a GET whether a resource was already created before retrying with a new key.
- Intuit: what is RequestId Checked 2026-10-11.
- A request id passed as a query parameter makes a repeat of the same request return the original response instead of repeating the operation.
- The id may be up to 50 characters for non-batch operations and must be unique across requests for a company.
- Intuit support thread: how long a request id is remembered Checked 2026-10-11.
- An Intuit support answer says the retention period for a request id is not published, so retry logic should not depend on a specific window.
- Xero Accounting API: invoices Checked 2026-10-11.
- For sales invoices (ACCREC) the InvoiceNumber is a unique code that Xero generates from the organisation's invoice settings when it is missing; for bills (ACCPAY) it is not unique and shows as the reference.
- Intuit: Invoice API reference Checked 2026-10-11.
- DocNumber has a maximum of 21 characters.