The journey
orderCode and attaches it to the order. From there it travels in data.fiscalRepresentation of
order.opened, order.completed,
order.invoiced, order.cancelled
and order.reversed.
Field by field
Ecuador, which is thedocument block of /fiscal/ec/prekeys:
A complete example, with real data:
The block above always has the same keys, with
null for those that do not
apply — that is what you program against. What changes per country lives inside
countryData, and there only the keys of the country that numbered travel: an
Ecuadorian receipt does not carry cufe, nor a Colombian one claveAcceso.The four cases, in full
These are all the states the block can have, and which response of yours produces them. The block above always brings the same 12 keys: what changes are the values and the contents ofcountryData.
GENERATED — you numbered, there is a receipt
GENERATED — you numbered, there is a receipt
You returned The integrator prints and reconciles.
2xx with document.countryData brings the SRI’s vocabulary and nothing from other countries.FAILED_FINAL — you rejected and retrying will not help
FAILED_FINAL — you rejected and retrying will not help
You returned non-It is a charged sale with no fiscal receipt. The integrator compensates on its side and
returns the receipt via the callback. Retrying does not fix it: the data has to be corrected.
2xx with retryable: false.FAILED_RETRYABLE — you rejected, but it can be retried
FAILED_RETRYABLE — you rejected, but it can be retried
You returned non-Same block as the previous one; what changes is the
2xx with retryable: true.numberingStatus and the scope. There
is no receipt, but there may be one: the channel retries with the same orderCode.PENDING — you did not respond
PENDING — you did not respond
There was a timeout or the connection dropped. You never produce this state: stating it
would imply having answered.
And the case with no numbering
When the sale did not go through any provider —the merchant does not invoice, or the country has no fiscal gateway— the whole block travels asnull:
documentType today is always SALE_INVOICE in the order’s events. CREDIT_NOTE
exists in the contract —it is produced by operation: "CANCEL"— but the numbering of the
cancellation is not attached to the order yet. When it is enabled, it is the same block with
documentType: "CREDIT_NOTE".Three fields worth understanding well
provider and metadata — two blocks, two destinations
They look alike and are not the same thing, so they travel separately:
Neither of the two carries
providerCode: that is our adapter identifier and it already
travels separately, above the block.
provider.reference is the only reason this block has shape. When something goes wrong, it
is what the integrator quotes to you so you can find the operation in your records. Buried in an
opaque bag —which by contract nobody should program against— it did not fulfil that function.metadata reaches the integrator untouched, in providerMetadata. We do not
interpret it, we do not validate it, we do not rename it.
That has two sides:
And on the other side: nobody should program against its keys. It is declared opaque precisely
so you can change it without breaking anyone. If a piece of data is important enough for the
integrator to branch on it, it does not belong in metadata — it belongs in the contract.
graphic — it is the only thing that cannot be derived
Everything else in the response can be reconstructed or composed. graphic cannot: the
Brazilian NFC-e QR is a URL signed with a hash that only the issuer can build. If it does not
arrive, the receipt prints without a QR.
It travels as is, untransformed: FIRE passes it on to the point of sale, which renders it with its
own library. We do not generate images on this side — size and resolution depend on the printer,
and only whoever prints knows that.
failure — it enables compensation at the other end
When numbering fails, the error does not stay in a log: it travels in the event. The sale was
charged anyway and the integrator needs to know it ended up without a fiscal receipt.
With that it can compensate on its side and return the receipt via the callback. Without it, a
charged sale with no receipt is indistinguishable from an account that does not invoice.
That is why failure.code has to be stable and failure.message actionable: they are not read
only by our support team, they are read by the end customer’s system.
What does NOT travel to the events
And the authority’s verdict, separately
fiscalRepresentation is the numbers that were printed, and they never change. Their
existence does not mean the authority authorized the receipt.
The verdict arrives later via your callback and travels elsewhere in the event:

