The journey from a partner application to the local document management
system passes through several stages. Any one of them can temporarily lose a
message, which is why at-least-once delivery is used throughout. To prevent
this from resulting in duplicate imports, there is the
Idempotency-Key.
The guarantee is simple: A request with the same key will be executed at most once – no matter how many times it is sent.
The Key
POST /v1/dms/documents
Authorization: Bearer eyJ...
Idempotency-Key: import-schriftsatz-2026-0042-001
Content-Type: application/json
| Property | Rule |
|---|---|
| Header | Idempotency-Key |
| Allowed characters | Letters, digits, and ., _, and
-
|
| Length | 1 to 128 characters |
| Required? | No. Without a key, the call behaves like a regular request. |
| Recommended for | All mutating calls: import, new version, reassignment |
A violation of the character set or length rules is rejected with
400 – intentionally, so that an application relying on
idempotency immediately knows its key was not accepted.
A suitable value is a random identifier (such as a GUID) or a string derived from the business operation. The only requirement is: one key per business operation, and the same key on every retry.
What Happens on a Retry
Unlike some other APIs, the original result is not cached and not returned again. Instead, the API reports the duplicate attempt as such:
| State of the original request | Response to the retry |
|---|---|
| Still in progress |
504 IDEMPOTENCY_KEY_INFLIGHT_TIMEOUT – it did not
complete in time. Try again later. |
| Completed or permanently failed |
409 IDEMPOTENCY_KEY_REUSED – the request will
not be executed again. |
| Temporarily failed | The retry is executed normally. |
Rejected unprocessed by the connector
(502 CONNECTOR_DEADLINE_EXCEEDED) |
The retry is executed normally – the first attempt had no effect. |
Important for implementation. A
409 IDEMPOTENCY_KEY_REUSEDis not an error with the request. It simply means: "This request has already been processed." It does not indicate whether it succeeded. The application must determine the actual outcome on its own – for operations that return202 Accepted, via the operation queryGET /v1/platform/operations/{operationId}; otherwise, through a business-level check (does the document already exist in the target case file?).
Two Pitfalls to Be Aware Of
The Key Is Unaware of the Request Body
Only the key is evaluated – not the request body. If the same key is used with a different body, it is treated as a retry and rejected. The second body will not be silently executed, but the contradiction will not be reported as such either.
Rule: Every new request always gets a new key. Even if only a single field was corrected.
A Key Cannot Be Reused After a Correction
If an import fails due to an incorrect field and the field is corrected, that is a new request. Using the old key would cause the corrected request to be rejected as a duplicate.
Retry Strategy
Recommendations by HTTP status:
| Response | Retry? | Approach |
|---|---|---|
2xx |
No | – |
4xx except 408, 425,
429
|
No | Fix the request first |
408 Timeout |
Yes | Exponential backoff: 1 s, 2 s, 4 s, 8 s, then give up |
425 Too Early |
Yes | Same as above |
429 Too Many Requests |
Yes | Follow Retry-After exactly |
502, 503, 504
|
Yes | Exponential backoff with jitter: start at 1 s, cap at 60 s, give up after approximately 10 minutes |
| No response (network) | Yes | Same as 5xx
|
Retry-Afteralways takes precedence. If the response specifies a wait time – as it does for429and503– that value applies instead of the cap in the table above. ForTENANT_OVERLOADED, for example, that is 120 seconds.
This page is the authoritative source for retry behavior. The per-error-code recommendations in Error Codes refer back to it; where the two appear to conflict, the recommendation for the specific error code takes precedence.
The jitter is not a minor detail – it matters: without it, all waiting applications would hammer the service at the same moment once an outage ends.
The Idempotency-Key remains the same across all
attempts for a given request.
The Special Case: No Response Received
This is the exact scenario idempotency exists for: the request may have arrived and been processed, but the response was lost. The application has no way to tell the difference.
With a key, retrying is safe:
- The request did not arrive → it will be executed now.
- The request arrived and is still running →
504 IDEMPOTENCY_KEY_INFLIGHT_TIMEOUT. - The request arrived and completed →
409 IDEMPOTENCY_KEY_REUSED, and the application determines the outcome via the operation query.
In none of these three cases will a duplicate document be created.
What Idempotency Does Not Do
- No ordering guarantee. Two requests with different keys may be processed in any order. If ordering matters, you must serialize on your end or use the result of the first request as input to the second.
- No unlimited validity. See the section below – after roughly five minutes, a key expires.
- No protection against a logically incorrect request. Idempotency guards against duplicate execution, not against a business operation that was wrong to begin with.
How Long a Key Remains Valid
A key is retained for approximately five minutes. After that, it is no longer known to the API.
This is the most important number on this page, because the consequences are significant: A retry after this deadline has passed will be executed as a normal request – it is no longer treated as a retry. For an import, this means a second document will be created.
Two rules follow from this:
- Complete all retries for a given request within a few minutes. The recommended cap of approximately ten minutes from the table above is already too long to rely on idempotency at the end of that window.
- Do not blindly retry after a long interruption. If a request is picked up again hours later – for example, after an application restart – you must first perform a business-level check to determine whether it has already been executed. For an import, that means listing the documents in the target case file and checking.
Including a Correlation ID
Independently of the idempotency key, every request should include its own correlation ID:
X-Correlation-Id: 9f3a2b7c4d1e5081
Allowed characters are letters, digits, and ., _,
and -, up to 64 characters. If no ID is provided, or an invalid
one is sent, the API generates one automatically.
Where the ID appears in the response depends on the outcome:
| Outcome | Where the ID appears |
|---|---|
| Success | In the X-Correlation-Id response header |
| Error |
Only in the error response body, in the
correlationId field – the header is absent in this case |
The reason is technical: error handling rebuilds the response from scratch, discarding any headers that were already set. For integrations, this means: in the event of an error, read the ID from the response body, not the header. Relying on the header will leave you without an ID precisely when you need one most.
This ID is the thread connecting all logs all the way through to the firm. It should be recorded in the partner application's logs so it is readily available if a question arises.
Further Reading
This article has been automatically translated by an AI and may therefore contain errors.
Related to