Costa Rica's electronic invoicing moved to version 4.4 with Resolución MH-DGT-RES-0027-2024 — 146 changes, mandatory for all taxpayers since 1 September 2025, a brand-new document type (the Recibo Electrónico de Pago), and a new mandatory node (ProveedorSistemas, identifying the software that produced the document). If you maintain an ERP or billing integration for Costa Rica, you migrated recently, and you probably still get rejections you don't immediately understand.
Most of them trace back to one field: the clave numérica.
The 50-digit clave, decomposed
The clave isn't a random ID. It's a structured composite:
positions 1–3: country code (506)
positions 4–9: emission date as DDMMAA
positions 10–21: the issuer's cédula
positions 22–41: the consecutivo — which must equal the document's , and whose own digits encode the branch, terminal and document type (which must match the XML root element!)
position 42: situación (normal / contingencia / sin internet)
positions 43–50: security code
So the clave cross-references the emission date, the issuer, the consecutivo and the document type. Generate any of those inconsistently — a consecutivo counter that drifted, a clave built before a date rollover, a credit note wrapped in an invoice root — and the document is internally contradictory even though it validates against the XSD.
A real rejection, explained
Here's actual validator output for a signed v4.4 invoice where the consecutivo, a CABYS code and the total were altered (excerpt):
{
"valid": false,
"documentType": "FacturaElectronica",
"version": "4.4",
"signatureValid": false,
"errorCount": 5,
"findings": [
{ "level": "error", "ruleId": "CR-CLAVE-CONSECUTIVO",
"text": "Clave consecutivo segment (positions 22-41) '00100001010000000001' does not match the document's '00100001010000000009'.",
"location": "Clave / NumeroConsecutivo" },
{ "level": "error", "ruleId": "CR-CODE-CABYS",
"text": "CodigoCABYS '85110' must be exactly 13 digits (Anexos y Estructuras v4.4; national CABYS product/service catalogue code).",
"location": "CodigoCABYS" },
{ "level": "error", "ruleId": "CR-MATH-COMPROBANTE",
"text": "TotalComprobante (99999.00000) != TotalVentaNeta + TotalImpuesto + TotalOtrosCargos - TotalIVADevuelto (11300.00000).",
"location": "ResumenFactura/TotalComprobante" }
]
}
Plus a CR-SIG-DOC-DIGEST mismatch — the XAdES-EPES signature caught the tampering too, because the recomputed document digest no longer matches what was signed.
Note what the official clave lookup can't tell you: VerificaTuFactura and the ATV consultation only answer "has Hacienda received this clave?" — nothing about a document you haven't sent yet, and nothing about why it's malformed.
Pre-flight in one call
The output comes from the Costa Rica e-Invoice Validator v4.4 (Hacienda) — keyless REST API, free tier available:
curl --request POST \
--url https://costa-rica-e-invoice-validator-v4-4-hacienda.p.rapidapi.com/validate \
--header 'Content-Type: application/xml' \
--header 'x-rapidapi-host: costa-rica-e-invoice-validator-v4-4-hacienda.p.rapidapi.com' \
--header 'x-rapidapi-key: YOUR_RAPIDAPI_KEY' \
--data-binary @comprobante.xml
It auto-detects all 8 v4.4 document types (including the new REP), validates the official Hacienda XSDs, decomposes and cross-checks the clave, enforces the v4.4 ProveedorSistemas requirement, checks CABYS and the other code lists, reconciles totals/IVA, and verifies the XAdES-EPES signature end to end (document digest, SignedProperties digest, RSA-SHA256, EPES policy presence). Keyless and stateless — no ATV login, no certificate, in-memory validation only.
The TRIBU-CR angle
Costa Rica is migrating its platform to TRIBU-CR, so the schema/annex set will keep moving — v4.4 was itself a 146-change step. If you hand-rolled your validation, every sub-version is a rebuild. A validator whose XSDs and code lists are swappable data turns that churn into someone else's problem.
Scope note: trust-chain verification to the SINPE/MICITT roots, live CABYS catalogue existence and the clave's acceptance require Hacienda's online services — valid: true means "structurally ready", not "accepted".
I maintain validators like this for five mandated e-invoicing regimes (Malaysia, Dominican Republic, Nigeria, Bolivia, Costa Rica) — overview with links: github.com/SamirChatwiti/e-invoice-validators.
Top comments (0)