Skip to content

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.
  • 200 with fiscal_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. See upstream_unavailable.

Check which you are looking at before doing anything:

Terminal window
curl -sS https://api.fiskhub.com/v1/health