Direct fiscal POS/ERP
The direct @timbro/fiscal lane is for a POS or ERP that already owns the sale and needs to fiscalize it. That operation creates a fiscal operation against Timbro; it does not create a Payment, hand off to Checkout, or expose payment-provider concepts. Keep sale ownership, internal numbering, and lines in the POS/ERP.
The approved flow has two separate lanes:
- For collection, the server uses
@timbro/paymentsandpayments.create; authorization and itsPaymenthave their own states. - To fiscalize a sale already paid by another method, the server uses
@timbro/fiscalwith its fiscal credential and the sale’s immutable revision. Do not mix a Checkout reference or tender write-back into that operation.
The direct adapter receives issuer identity, buyer, lines, and an idempotency key. Store sourceRecordId and sourceRevision; on timeout retrieve the same operation instead of creating another. Fiscal operation states are accepted, processing, issued, rejected, unavailable, and operator_required; they never translate into Payment states.
The fiscal client’s intended shape makes those recovery keys explicit:
import { createTimbroFiscal, type SourceDocument } from "@timbro/fiscal";
const baseUrl = process.env.TIMBRO_FISCAL_ORIGIN;const credential = process.env.TIMBRO_FISCAL_CREDENTIAL;if (!baseUrl || !credential) throw new Error("Missing fiscal origin or credential");const fiscal = createTimbroFiscal({ baseUrl, credential,});const sourceDocument: SourceDocument = { kind: "consumer", buyer: { identityKind: "anonymous" }, sale: { currency: { kind: "dop" }, declaredTotals: { net: "1050.85", tax: "199.15", total: "1250.00", nonBillable: "0.00" }, lines: [{ sourceLineId: "sku-1", description: "Service", quantity: "1", measurementUnit: "unit", unitPrice: "1250.00", itemKind: "service", taxTreatment: "itbis_18" }], paymentTerms: { terms: "cash" }, },};const idempotencyKey = "pos-sale-123-r4"; // derive this from the immutable sale revisionconst operation = await fiscal.fiscalOperations.create({ source: { recordId: "pos-sale-123", revision: 4, contentSha256: "...sha256-of-canonical-sale..." }, idempotencyKey, action: { kind: "issue", document: sourceDocument }, printedRepresentation: { profile: "receipt_80mm" },});The published fiscal package must preserve the semantics of sourceRecordId, sourceRevision, digest, and idempotency; do not add a paymentId or checkoutUrl to this lane.
Before writing a tender back, reconcile POS response, acquiring authority, and fiscal result separately. If a boundary is uncertain, leave the sale under review and assign operational recovery.