Idempotency
POST /v1/invoices requires Idempotency-Key. Use it to make invoice submission retries safe without creating duplicate submissions.
Idempotency-Key
Send an Idempotency-Key header with every POST /v1/invoices request.
Idempotency-Key: inv-submit-sandbox-fv-0001Reuse the same key only when retrying the same invoice submission request.
Request fingerprint
The API compares a canonical request fingerprint built from:
- normalized
external_id - decoded raw
invoice_xml - sorted string-only metadata
- for test mode only, the normalized sandbox scenario
Missing Ksef-Sandbox-Scenario and explicit accepted are the same semantic sandbox request.
Replay
Replaying the same Idempotency-Key with the same canonical request returns the exact stored HTTP status and response body.
If the original successful submission returned 201 Created, the replay also returns 201 Created.
{ "id": "inv_2kCYq4m4G7YbUjvH0kC1dg", "object": "invoice", "mode": "test", "status": "processing", "organization_id": "org_2kCYq4m4G7YbUjvH0kC1dg", "external_id": "fv-2026-0001", "created_at": "2026-05-31T10:15:30Z", "updated_at": "2026-05-31T10:15:30Z", "ksef_number": null, "upo_available": false, "retrying": false, "next_retry_at": null, "last_error": null, "metadata": { "order_id": "ord_123" }}Conflict
Reusing the same Idempotency-Key with a different canonical request returns idempotency_conflict.
{ "error": { "type": "conflict_error", "code": "idempotency_conflict", "message": "The same idempotency key was used with a different request.", "param": "Idempotency-Key", "request_id": "req_0Y9a6cW9xQz9xwWzYxA0fY", "retryable": false }}In-progress request
If the same key is still being processed, the API can return idempotency_request_in_progress.
{ "error": { "type": "conflict_error", "code": "idempotency_request_in_progress", "message": "The same idempotency key is already being processed.", "param": "Idempotency-Key", "request_id": "req_0Y9a6cW9xQz9xwWzYxA0fY", "retryable": true }}Previous live attempt failed
If a previous live attempt failed before KSeF submission, the original key is terminal. Submit the same request again with a new Idempotency-Key.
{ "error": { "type": "conflict_error", "code": "idempotency_previous_attempt_failed", "message": "The previous live submission attempt failed before KSeF submission. Submit the same request again with a new Idempotency-Key.", "param": "Idempotency-Key", "request_id": "req_0Y9a6cW9xQz9xwWzYxA0fY", "retryable": false }}Reconciliation required
If a previous live submit outcome is ambiguous, the API returns idempotency_reconciliation_required. Do not automatically retry the same key.
{ "error": { "type": "conflict_error", "code": "idempotency_reconciliation_required", "message": "The previous live submission outcome is not safe to retry automatically. Operator reconciliation is required before using this idempotency key again.", "param": "Idempotency-Key", "request_id": "req_0Y9a6cW9xQz9xwWzYxA0fY", "retryable": false }}Read requests
Read operations do not require Idempotency-Key:
GET /v1/invoices/{id}GET /v1/invoices/{id}/upo