In Costa Rica, every restaurant or business that issues an invoice must use electronic invoicing with Hacienda. The question is not whether to integrate but how to do it without getting receipts rejected and without discovering six months in that your submission queue creates duplicates.
This guide is the technical and pricing-grounded version of how we quote Hacienda integration at Sirius for restaurants, diners, and any point of sale that issues receipts. If you need the exact range now, head to the pricing wizard — 4 questions, 30 seconds.
💡 TL;DR: $2,500 (basic: emit + sign + send) to $4,500 (with credit notes, exemptions, async queue, retries). 2–3 weeks. Four decisions that matter: receipt type, in-house certificate vs BSP, sync vs async queue, 4xx rejection handling.
Why it matters and when it is mandatory
Since Hacienda completed the migration to the electronic receipts regime, any taxpayer issuing a receipt must do so electronically: restaurants, retail, professional services, and ecommerce.
Fines for not issuing or issuing incorrectly are significant: from one base salary per faulty receipt to temporary business closures for repeat offenses. Beyond the fine, a corporate customer will not pay you without an electronic invoice — hotels, hospitals, and large companies require full receipts with their tax ID.
Integration is not optional, but how you integrate is: you can pay a provider $100/month, use a commercial POS that includes it for $30–80/month, or integrate into your custom system. Each option has tradeoffs.
How the Hacienda system works
Four components you need to understand before writing any code.
1. ATV (Virtual Tax Administration)
The Hacienda web portal at atv.hacienda.go.cr. There you register the issuer, generate cryptographic keys (.p12 + password), look up receipts, and file monthly VAT returns. Each issuer has a .p12 certificate that signs every XML, rotates every 4 years. Without that .p12 and password, your system cannot emit anything.
2. XML structure
The v4.4 electronic receipt follows an XSD schema published by Hacienda. Each receipt has:
- 50-digit numeric key: country (506) + date (DDMMYY) + issuer tax ID (12 digits) + branch + terminal + receipt type + sequence + situation + security code.
- Header: issuer, receiver (if applicable), date and time.
- Line detail: code, description, quantity, unit price, VAT (1%, 2%, 4%, 8%, or 13%), total.
- Summary: taxable, exempt, exonerated, taxes, receipt total.
- Reference information (required for credit/debit notes).
- XAdES-BES signature block.
One wrong digit = rejection.
3. XAdES-BES digital signature
The XML is signed in enveloped mode — the signature stays inside as a <ds:Signature> node with SHA-256 hash, X.509 certificate, RSA-SHA256, signature policy, and timestamp.
Production-tested implementations: the official Java library from Hacienda, xml-crypto + node-forge in Node.js, native .NET libraries. Signing fails silently if the certificate chain is poorly built — always test against staging first.
4. REST API for submission and lookup
Three relevant endpoints:
POST /recepcion— submit the signed XML in base64. Returns 202 or error.GET /recepcion/{key}— check state: "accepted," "rejected," or "processing."GET /recepcion/{key}/recibo— download the confirmation.
OAuth 2.0 authentication: with username + password you generate an access_token valid for 5 minutes.
Realistic pricing: $2,500 – $4,500
The price depends on how complete the module needs to be. Here is the breakdown by concrete feature:
| Feature | Cost USD | Time |
|---|---|---|
| Base setup (ATV, .p12, OAuth, staging/prod connectivity) | 400 – 600 | 3 days |
| v4.4 XML generation (header, lines, totals) | 600 – 900 | 4 days |
| XAdES-BES signing with node-forge / Java / .NET | 400 – 700 | 3 days |
Async queue + worker (BullMQ, SQS, or pending table) |
400 – 600 | 3 days |
| Retries with backoff + timeout handling | 200 – 400 | 2 days |
| Credit notes and debit notes (references) | 300 – 500 | 2 days |
| Exemptions (tax ID and validity) | 300 – 500 | 2 days |
| 4xx error code handling with notifications | 200 – 400 | 2 days |
| PDF + QR generation + email delivery | 300 – 500 | 2 days |
| Automated tests + queue monitoring | 200 – 400 | 2 days |
| Total basic integration | 2,500 | 2 weeks |
| Total full integration | 4,500 | 3 weeks |
What $2,500 includes (basic)
Electronic ticket and invoice emission, working XAdES-BES against production, sync queue with simple retry (3 attempts), PDF generation with QR, automatic email delivery, and 30 days of support.
What gets you to $4,500
- Credit and debit notes with references to the original receipt.
- Exemptions — exonerated registry lookup, regulatory authority, validity.
- Robust async queue — BullMQ or SQS, dashboard, manual reprocessing.
- Granular 4xx error handling — complete error code dictionary + action (correct, void, escalate).
- Mass reprocessing after Hacienda downtime.
- Tax reporting — monthly export for the accountant.
- Multi-branch — independent sequence counters per terminal.
If your restaurant has a single location, < 50 tickets/day, and no exemptions, basic is enough. If you are a chain, serve businesses with exempt invoices, or handle frequent returns, you need the full integration.
To see how this fits into the total cost, the pricing pillar has the breakdown: $2,500–4,500 base POS + $2,500–4,500 e-invoicing = $5,000–9,000 for a complete restaurant. Cases and stack at /services/restaurants.
The 4 technical decisions that matter
Decision 1: full invoice vs electronic ticket
The full invoice carries receiver data (name, tax ID, email) and is used when the customer requests it to deduct taxes or it is B2B. The ticket is the simplified version for end consumers.
Your system must support both. The typical flow is 90% ticket, 10% invoice. Design the UI so the server switches from ticket to invoice with a single tap and captures tax ID/email on the spot. Forcing every transaction to be a full invoice with end-customer tax ID creates massive typing errors.
Decision 2: in-house certificate (.p12) vs BSP provider
With in-house you manage the .p12 directly; marginal cost per receipt = zero. With a BSP (Business Service Provider) you pay $0.05–0.15 per receipt or a $30–80/month subscription.
- < 500 receipts/day + technical team: in-house is cheaper over 12 months.
- 2,000+ receipts/day or no technical team: BSP simplifies.
- Small restaurant (< 100/day) wanting maximum simplicity: BSP at $30/month is reasonable.
At Sirius we default to in-house quotes because the customer keeps control and avoids monthly dependency.
Decision 3: sync vs async queue
Synchronous: at payment time, the system signs and sends to Hacienda. Simpler, but if Hacienda takes 8 seconds the customer waits 8 seconds, and if Hacienda is down you cannot collect.
Asynchronous (recommended): the system prints the ticket immediately with "pending" state. A background worker signs, sends, and updates. Customer does not wait, survives Hacienda outages. Requires a queue (BullMQ, SQS, or pending_invoices table) and dashboard.
For a restaurant POS in production, always async.
Decision 4: 4xx error handling
Hacienda returns specific codes:
- Duplicate key → do not retry; generate a new key.
- Non-existent receiver tax ID → notify user; allow correction.
- Miscalculated VAT → bug in your system; critical alert to admin.
- Receipt already voided → ignore silently.
- Timeout / 503 → retry with exponential backoff.
Blind retries without diagnosis generate duplicates and fines. Your system must have a code → action dictionary, and any unknown code escalates as an admin alert, never automatic retry.
HowTo step by step
Register issuer in ATV. Log into
atv.hacienda.go.cr, register the issuer, define economic activities (5610 for restaurants), and download the .p12. Note the password.Generate OAuth token and validate connectivity. Generate the access_token (5-min validity) and run a manual
curlagainst staging to confirm 200 before writing any code.Build the v4.4 XML. Download the official XSD. Generate the 50-digit key, complete header, lines with correctly calculated VAT, totals that match bit-for-bit, and reference information for credit/debit notes.
Sign with XAdES-BES. Use the .p12 to sign the XML as an embedded
<ds:Signature>node. Always test against staging first.Queue submission. Do not send inline in the POS transaction. Queue it in
pending_invoicesor a job queue. Dedicated worker with exponential backoff (5s, 30s, 2min, 10min, 1h).Handle acceptance or rejection. Hacienda returns 202 on the POST; within 5–60 seconds you query state via GET. Only with "accepted" do you generate the customer PDF.
Generate PDF and send. Generate the PDF with XML data, the public-validation QR, and the Ministry response. Send by email or print to 80mm thermal paper.
Common mistakes we see in production
Malformed numeric key. The sequence must be unique per receipt type and terminal. Teams that share sequences across terminals generate duplicates. Fix: sequential counter per terminal with transactional locking.
Infinite retries on 4xx errors. Timeout is 503 (retry); validation errors are 4xx (diagnose and fix). Systems that retry 4xx send the same rejected XML 50 times. Fix: error code → action dictionary; unknown code = admin alert.
VAT rounding. VAT is calculated per line, not on the total. If you round at the end, it does not match per-line sums. Fix: VAT per line with 5 decimals, round to 2 per line, sum the rounded values.
Expired certificate. The .p12 expires every 4 years; if hardcoded on disk, it expires without warning. Fix: monitor expiration in observability, alert 30 days before, load from a secret manager.
Not handling offline mode. If your POS cannot issue when internet drops, the business stops. Fix: the POS prints the ticket with "pending" state; the worker syncs when connection returns.
Badly generated PDF. Hacienda does not generate the PDF — your system does, with XML data. Fix: generate the PDF on acceptance; inspect one per branch in the first week.
Not handling foreign-taxpayer receipts. A foreign customer uses a passport, not a national ID. Fix: support the three identification types (national tax ID, corporate tax ID, foreign passport) from day 1.
How this fits into your total system cost
If you are pricing a complete restaurant system, e-invoicing is one module of the project. To understand the total breakdown:
- Basic web POS (menu, orders, daily reports): $2,500–4,500. Detail in the pricing pillar.
- Online reservations + WhatsApp: + $800–1,500.
- E-invoicing with Hacienda (this module): + $2,500–4,500.
- Kitchen inventory: + $2,000–4,000.
For a mid-sized restaurant that needs POS + e-invoicing + reservations, the total range is $5,800–10,500. See real cases and stack at /services/restaurants.
💡 If you need the exact range for your case, head to the pricing wizard. 4 questions, 30 seconds, gives you the USD range with a pre-loaded WhatsApp message.
In summary
| Component | Cost USD | Time |
|---|---|---|
| ATV setup + .p12 + OAuth | 400 – 600 | 3 days |
| v4.4 XML generation | 600 – 900 | 4 days |
| XAdES-BES signing | 400 – 700 | 3 days |
| Queue + worker + retries | 600 – 1,000 | 5 days |
| Credit/debit notes + exemptions | 600 – 1,000 | 4 days |
| PDF + QR + email delivery | 300 – 500 | 2 days |
| Total e-invoicing module | 2,500 – 4,500 | 2 – 3 weeks |
If your project falls outside these ranges, let's talk. The initial quote is free, in writing, and non-binding.
💡 For an approximate quote in 30 seconds, use the interactive pricing wizard. 4 questions → USD range + WhatsApp message with your scope pre-loaded.
📞 To talk directly: WhatsApp +506 8433 7752 or admin@siriusx.net. Monday to Friday 8 AM – 5 PM, Saturdays 8 AM – 12 PM, Costa Rica time.
Related posts
- How much software costs in Costa Rica in 2026 — full pricing pillar by project type and vertical.
- MVP timeline in 6 weeks — how a project with e-invoicing gets planned from week 1.
- Restaurant services — real cases, stack, and how we build it.
