Retries and rate limits
Retry writes safely with an Idempotency-Key, and stay within the request limits.
Idempotency-Key
Every write that a tenant API key can call (POST, PUT, PATCH, and DELETE on counterparties, payment methods, transactions, invoices, matches, import jobs, and ingest) accepts an Idempotency-Key header. Generate one key per logical operation, for example a UUID, and send the same key when you retry that operation after a timeout or network error.
curl --request POST \
--url https://api.invunion.com/api/v1/invoices \
--header 'authorization: Bearer uk_live_YOUR_API_KEY' \
--header 'content-type: application/json' \
--header 'Idempotency-Key: 5f0c2b8e-invoice-INV-2026-0042' \
--data '{ "invoiceNumber": "INV-2026-0042", "...": "..." }'- Same key and same body after the first request succeeded: the stored response is returned with the header
Idempotent-Replayed: true, and nothing is written again. - Same key while the first request is still running: 409 with
codeidempotency_in_progress. Wait and retry. A request stuck for more than 5 minutes is treated as abandoned and can be taken over. - Same key with a different body: 422 with
codeidempotency_key_reuse. Use a new key for a new request. - Only successful (2xx) responses are stored. After an error, the key is released and you can retry with it.
- A key is 8 to 255 characters: letters, digits,
.,_,:, or-. It is scoped to your tenant and to the method and path, and kept for 24 hours.
Without the header, a retried write can run twice. Most creates are protected by a unique code anyway (invoiceNumber, account_code, sourceId), but matches and import jobs are not.
Rate limits
- All endpoints: 100 requests per minute per API key, and 100 per minute per IP address.
- Create import job: 20 requests per minute per key, on top of the general limit.
- Ingest transactions (deprecated): 10 requests per minute per key, on top of the general limit.
Over a limit, the API answers 429 with Retry-After in seconds and the RateLimit-* headers. Wait that long before retrying. To move many records, send them in one Create import job (up to 10,000 items) or one bulk import call instead of one request each.
Retrying errors
- 429 and 503: wait for
Retry-After, then retry. - 500: retry with exponential backoff and the same
Idempotency-Key. The body includescorrelationId; quote it when you contact support. - 400, 403, 404, 409, and 422: fix the request first. Retrying it unchanged returns the same error.