Idempotent requests
Fiscalapi supports idempotency so you can retry a request without the risk of running the same operation twice. If a network error or a timeout makes you lose the response, send the request again with the same idempotency key: Fiscalapi returns the original response without stamping (the certification by a SAT-authorized provider that makes a CFDI valid) or charging again.
How it works
To make a request idempotent, send the Idempotency-Key header with a unique idempotency key that you generate. We recommend a UUID v4 or any random text with enough entropy to avoid collisions. The idempotency key accepts 1 to 64 visible ASCII characters, with no spaces, and must not contain personal data such as email addresses or RFC (Mexico's taxpayer ID, Registro Federal de Contribuyentes).
Fiscalapi stores the status code and the body of the first request with that idempotency key as soon as the endpoint starts running, including 500 errors. Each retry with the same idempotency key gets that same response, with the Idempotent-Replayed header set to true, and the operation doesn't run again. The traceIdentifier of a replayed response is the one from the original execution.
Each idempotency key belongs to the authenticated person who sends the request (person: any individual or legal entity registered in your tenant; tenant: the space in Fiscalapi that holds your issuers, recipients, credits, and data). The same idempotency key sent by another person is a different operation. A request with an idempotency key finishes running even if your client closes the connection, so a retry always gets the actual result.
What is compared on a retry
Fiscalapi compares each retry with the original request: the method, the path, the query parameters, the X-TIME-ZONE header, and the exact body. If anything changes, the request is rejected, so the same idempotency key can't be used by mistake for another operation. Send the retry with the same bytes as the original request.
When the result is not stored
If the request fails validation before it runs, for example because a required field is empty or the JSON is malformed, Fiscalapi responds with 400 and its validation failures, and it doesn't store the result: fix the request and retry with the same idempotency key. Nothing is stored either while another request with the same idempotency key is still in progress.
Any other response is stored, including a 403 for insufficient balance or a 500. To try the operation again after you fix the cause, use a new idempotency key. If the stored response is a 500, check the resource first to confirm whether the operation happened.
Expiration
Idempotency keys expire 24 hours after the first request. From that moment on, the same idempotency key is accepted as new, and the operation runs again.
Endpoints that support it
| Endpoint | Operation |
|---|---|
POST /api/v4/invoices | Create an invoice of any type, by value or by reference |
POST /api/v4/stamps | Transfer stamps or withdraw stamps (stamp: one credit, used each time you stamp a CFDI) |
POST /api/v4/tickets | Create a ticket |
Other endpoints ignore the header.
Errors
| Status | When it happens | Message |
|---|---|---|
| 400 | The idempotency key is empty, is longer than 64 characters, or has spaces or characters outside ASCII. | El encabezado Idempotency-Key debe tener de 1 a 64 caracteres ASCII visibles, sin espacios. |
| 409 | Another request with the same idempotency key is still in progress. Retry after the number of seconds that the Retry-After header indicates. | Otra petición con esta Idempotency-Key sigue en proceso. Reintenta en unos segundos; si continúa, consulta el recurso y usa una Idempotency-Key nueva. |
| 413 | The request body is larger than the maximum size. | El cuerpo de la petición excede el tamaño máximo permitido. |
| 422 | The idempotency key was already used with another request. | Esta Idempotency-Key ya se usó con otra petición. Usa una Idempotency-Key nueva para cada operación distinta. |
Example
Generate the idempotency key once per operation, and store it with the invoice you are issuing. If the request fails because of a network error or a timeout, send it again with the same idempotency key and the same body. In the SDKs, you build the invoice the same way as in Create an invoice, and the key is an optional argument.
Request
curl --location 'https://test.fiscalapi.com/api/v4/invoices' \
--header 'X-TENANT-KEY: <tenant_key>' \
--header 'X-API-KEY: <api_key>' \
--header 'X-TIME-ZONE: America/Mexico_City' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000' \
--data-raw '{ ... }'
To transfer stamps with an idempotency key, pass it as the second argument to the transfer method of each SDK:
| SDK | Method |
|---|---|
| .NET | Stamps.TransferStamps(request, idempotencyKey) |
| Python | stamps.transfer_stamps(request, idempotency_key=...) |
| Node.js | stamps.transferStamps(request, idempotencyKey) |
| Java | getStampService().transferStamps(request, idempotencyKey) |
| PHP | getStampService()->transferStamps($data, $idempotencyKey) |