None of this is made up: these are real calls between FIRE and a working fiscal provider,
with the identifiers changed. They are useful for checking an implementation against
something that already works, instead of against a description.
Numbering a sale
The request is the same for both countries —same fields, same order—; what changes is
what each provider uses and what it returns in document. The bodies below are trimmed to
what you need to read the example; the full request, field by field, is in the
contract.
Ecuador (EC) — SRI
Colombia (CO) — DIAN
What we send
storeFiscalConfig.metadata travels empty: in Ecuador the establishment and the point of
emission are resolved on your side against your catalog, from store.code and device.uid.What the provider returned
document speaks Ecuadorian. claveAcceso, secuencial, ambiente — the SRI’s
names, not a translation. And there are no fields from other countries: the Colombian
cufe simply does not exist here.
- The visible number arrives already assembled in
numeroComprobante
(005-004-000000052). You compose it, because you know the rule —art. 18 of the
Regulation— and FIRE prints it as is, without reformatting. The three pieces still
travel separately, as the SRI defines them, but they are for reconciliation: nobody joins
them back together.
graphic.qr matches document.claveAcceso. In Ecuador that is how it works, and the
redundancy is deliberate: the alternative is for the point of sale to know what gets
encoded in each country.
ambiente: "2" means testing — at the SRI. At the DIAN the 2 is the other way
around; see the Colombia tab.
What we send
Here storeFiscalConfig.metadata does carry data —the technical key and the range the
DIAN issues with the resolution— and the amounts in totals are not informational: they
go into the CUFE hash.What the provider returned
document speaks Colombian, and it looks nothing like Ecuador’s: there is no
claveAcceso and no secuencial, there is cufe, prefijo and numeroDian.
graphic comes back null. In Colombia the QR is the DIAN catalog URL and it travels
inside document.qrCode, so it is not duplicated outside.
numeroComprobante and numeroDian are not the same thing: the first is the visible
number already assembled (prefix + consecutive), the second is the consecutive alone.
Both are returned resolved; FIRE concatenates nothing.
ambiente: "2" means testing at the DIAN — the code is the authority’s own, without
normalizing, and that is why it means the opposite of Ecuador’s.
Notice what does not travel in either of them: no accountId, no vendorId —the tenant
comes from the API key—, no tax authority codes, no reference to the provider’s catalog.
And two things common to both countries:
authorizationMode and issuedAt sit at the root, outside document: they are common
to every country, so they do not belong in the country block.
status: "INVOICED", not "PENDING". Right after numbering, a document is always
pending authorization — that is the normal condition, not a state to report.
When it fails
The same request, with the store outside the provider’s catalog
Why this error is well constructed:
retryable is what decides what happens next. With false we stop and the sale ends up
without a fiscal receipt, with the reason recorded. With true the request stays open and
can be resumed.Without that field you have to guess from the HTTP code — and guessing wrong means retrying
while the customer waits, or abandoning a sale that could have been numbered.
What we do with each response
The state FIRE exposes to its channels is derived from what the provider returns. The
provider does not know these states and does not have to emit them:
PENDING cannot come from the provider by definition: stating it would imply having
answered. It is the “there was no response” state, and it is the most delicate one — the
provider may have numbered and consumed a sequential without us finding out.That is why your deduplication has to be by orderCode: the retry arrives with the same
orderCode and must return the same document with reused: true, instead of numbering another one.Do not base it on an idempotency header: we do not send you one. The call to the
provider carries only x-api-key and Content-Type. The natural key
—country + orderCode + operation— is the only thing that links a retry with the original
attempt, at both ends.