internal_error
HTTP 500 type: internal_error param: null{ "error": { "type": "internal_error", "code": "internal_error", "message": "An unexpected error occurred. Retry with the same Idempotency-Key; quote request id req-7f3c9a21 if it persists.", "param": null, "upstream": null, "doc_url": "https://docs.fiskhub.com/errors/internal_error" }}What happened
An unexpected failure inside FiskHub. Nothing in your request caused it, and the message is deliberately vague — internal detail is not exposed through the API.
It is already recorded on our side, with your X-Request-Id attached.
Should you retry?
Yes — with the same Idempotency-Key. This is precisely what the key is for.
The failure may have happened before or after the sale was fiscalized, and from the outside you cannot tell which. Resending with the same key resolves that: if the sale went through, you get the original response replayed; if it did not, it is fiscalized now. Either way there is exactly one fiscal record.
Resending with a new key removes that protection and risks a second fiscalization of one sale.
async function fiscalizeWithRetry(sale, attempts = 3) { // Serialise ONCE — re-serialising can change key order and therefore the body hash. const body = JSON.stringify(sale.payload);
for (let attempt = 1; attempt <= attempts; attempt++) { const res = await fetch(`${API}/invoices`, { method: "POST", headers: { Authorization: `Bearer ${API_KEY}`, "Idempotency-Key": sale.idempotencyKey, // NEVER regenerated "Content-Type": "application/json", }, body, });
if (res.status < 400) return res.json(); if (res.status < 500 && res.status !== 429) throw new FiscalRequestError(await res.json());
await sleep(500 * 2 ** (attempt - 1)); // 500 ms, 1 s, 2 s } throw new Error("fiscalization failed after 3 attempts");}Exponential backoff with a small amount of jitter. Three attempts is plenty — beyond that, store the sale and submit it later.
If it does not clear
Complete the sale anyway, and store it for later submission.
A 500 means the sale was not necessarily recorded, so unlike the
no-JIR response there may be no ZKI for this transaction. That still does not
justify refusing the customer: the specification requires the device to dispense regardless of
what fiscalization does. Store the sale with its real occurred_at and submit it — with the
same idempotency key — once the service recovers. FiskHub marks it as late delivery
automatically.
Reporting it
Quote your X-Request-Id — the value you sent, or the one returned in the X-Request-Id
response header. It is attached to every log line for that request and turns an investigation
into a lookup.
Send the correlation id, the device_id, and roughly when it happened. Do not send the
Authorization header or the certificate passphrase; neither helps and both are secrets.
Distinguishing it from an outage
500 internal_error— FiskHub itself failed. Retry.200withfiscal_error.code = "upstream_unavailable"— FiskHub is fine and the Tax Administration is unreachable. The sale is recorded, a ZKI exists, and the retry is already scheduled. Do nothing except complete the sale. Seeupstream_unavailable.
Check which you are looking at before doing anything:
curl -sS https://api.fiskhub.com/v1/health