Skip

00/Business

E-invoicing with Hacienda for restaurants in Costa Rica — technical guide

How to integrate your POS or restaurant system with Costa Rica Hacienda: ATV, certificates, XML, digital signature, realistic pricing $2,500–4,500, and the mistakes we see in production.

Fecha
May 20th, 2026
Tiempo de lectura
10 min read
Autor
By Jafeth Jiménez

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

  1. 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.

  2. Generate OAuth token and validate connectivity. Generate the access_token (5-min validity) and run a manual curl against staging to confirm 200 before writing any code.

  3. 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.

  4. Sign with XAdES-BES. Use the .p12 to sign the XML as an embedded <ds:Signature> node. Always test against staging first.

  5. Queue submission. Do not send inline in the POS transaction. Queue it in pending_invoices or a job queue. Dedicated worker with exponential backoff (5s, 30s, 2min, 10min, 1h).

  6. 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.

  7. 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

Jafeth Jiménez

By

Jafeth Jiménez

Founder · SEO & developer

Co-founder and owner of Sirius. Leads SEO strategy and ships code on every project the agency delivers. Works with clients in Costa Rica and the region.

03/Step by step

How to integrate e-invoicing with Hacienda step by step

Seven steps to connect your restaurant POS or system with Costa Rica Hacienda without getting receipts rejected in production.

  1. Step 01

    Register issuer in ATV

    Log into atv.hacienda.go.cr with your tax ID and dynamic key. Register the issuer (individual with activity or legal entity), define economic activities, and download the .p12 cryptographic certificate. Write down the .p12 password — without it the system cannot sign anything.

  2. Step 02

    Generate OAuth token and validate connectivity

    With your Hacienda username and password generate the access token (valid for 5 minutes) against the authentication endpoint. Before writing any code, run a manual curl against the staging reception endpoint and confirm you get a 200. If it fails here, there is nothing else to code afterward.

  3. Step 03

    Build the v4.4 receipt XML

    Hacienda publishes the XSD schema for the Electronic Receipt v4.4. Each invoice is an XML with a header (key, sequence, date, issuer, receiver), detail lines (code, description, quantity, price, VAT), totals, and tax summary. The 50-digit key follows a strict pattern: country + date + tax ID + branch + type + sequence + situation + security code. One wrong digit means immediate rejection.

  4. Step 04

    Sign the XML with XAdES-BES

    The XML is signed with XAdES-BES using the issuer .p12 certificate. The signature wraps the full XML and adds a <ds:Signature> block with hash, certificate, policy, and timestamp. The official Java library works, but there are also implementations in Node.js (xml-crypto + node-forge) and .NET. The signature must pass Hacienda validation before submission.

  5. Step 05

    Queue submission with controlled retries

    Do not send the XML inline within the POS transaction. Queue it in a `pending_invoices` table or a job queue (BullMQ, SQS). A dedicated worker picks up the receipt, sends it to Hacienda, waits for the response, and updates state. If Hacienda returns 503 or times out, retry with exponential backoff (5s, 30s, 2min, 10min). If it returns 4xx with a business error, mark as rejected and notify.

  6. Step 06

    Handle acceptance or rejection

    Hacienda does not return acceptance in the same submission request. It returns 202 (received) and then within 5–60 seconds you can query state via GET /recepcion/{key}. Your system must poll or wait for callback. Final state is "accepted," "accepted with observations," or "rejected." Only when "accepted" arrives can you generate the customer PDF.

  7. Step 07

    Generate the PDF and send to receiver

    Once the receipt is accepted, generate the PDF with XML data, the QR (for public validation on Hacienda), and the Ministry response. If the receiver has a registered email, send the PDF and XML by email. If it is a ticket for an end consumer, it normally prints on 80mm thermal paper from the POS.

04/Frequently asked

What people ask us about this.

How much does it cost to integrate e-invoicing with Hacienda for a restaurant?

Between $2,500 and $4,500. Basic integration (emit invoice, sign XML, send to Hacienda, receive response, and store PDF) is $2,500 and takes 2 weeks. If you need credit notes, debit notes, exemptions, automatic retries, and a robust async queue, it reaches $4,500 over 3 weeks. The cryptography setup plus the .p12 certificate adds a week if we manage it.

Is e-invoicing mandatory for restaurants in Costa Rica?

Yes. Under the Hacienda electronic receipts regime, every taxpayer in the traditional or simplified regime who issues a receipt must do so electronically. For restaurants with end-consumer clients without a tax ID, the electronic ticket is the minimum required receipt. If you issue a full invoice to another business with a tax ID, you must generate the signed XML and send it to Hacienda in real or near-real time.

What is the ATV and why does it matter?

The ATV (Virtual Tax Administration) is the Hacienda web portal where issuers register, generate cryptographic keys, and check receipts. To integrate your POS or system you need to: register as an issuer, obtain your .p12 certificate (digital signature with password), generate the OAuth token to call the API, and keep the economic activity catalog updated. Without ATV, there is no integration.

What is the difference between a full invoice and an electronic ticket?

The full electronic invoice carries receiver data (name, tax ID, email) and is used when the customer asks for it to deduct taxes. The electronic ticket is the simplified version for end-consumer sales without identification, equivalent to a cash register receipt. Both require XML signing and submission to Hacienda, but the ticket has fewer mandatory fields. Most restaurant transactions are tickets; invoices are the minority.

Should you use your own certificate or a BSP provider?

It depends on volume. With an in-house certificate (.p12) you have full control and zero marginal cost per receipt, but you handle certificate rotation and XML cryptographic signing. With a BSP (Business Service Provider) you pay $0.05–0.15 per receipt and they sign and forward, but you depend on their uptime. For a restaurant with under 500 receipts/day, in-house is cheaper over 12 months. Above 2,000/day, BSP simplifies operations.

What happens if Hacienda rejects the XML?

Hacienda responds with an error code (4xx) explaining the problem: duplicate key, invalid sequence, non-existent receiver tax ID, miscalculated VAT, etc. The system should queue the rejection rather than blindly retry. A good pipeline marks the receipt as "rejected," notifies the admin, and lets you correct or void the receipt. Blind automatic retries generate duplicates and fines.

Can you integrate e-invoicing with a third-party POS (Square, Toast)?

Square and Toast do not have native integration with Costa Rica Hacienda. Options are: (1) use middleware that listens to their webhooks and emits the XML to Hacienda; (2) replace the POS with one that has local integration; or (3) use our own web POS with invoicing included. The middleware adds $1,500–3,000 and creates a failure point; a local POS with native integration ends up costing the same and is more reliable.

How do I contact Sirius to integrate e-invoicing?

Message us on WhatsApp at +506 8433 7752 or email admin@siriusx.net. You can also try the [pricing wizard](/cotizador) — 30 seconds to a ballpark range. We work Monday to Friday 8 AM – 5 PM and Saturdays 8 AM – 12 PM, Costa Rica time. The initial quote is free and in writing.

05/Direct contact

Talk to Sirius about this.

We're a software agency in Costa Rica. If what you read applies and you want to move forward, reach us through any of these:

Hours
Mon–Fri 8am – 5pm · Sat 8am – 12pm
Location
Pozos de Santa Ana, Santa Ana, San José, CR

02/Tell us

Does any of this apply to you? .

If the note rang a bell and you have a project in mind, let's talk on WhatsApp. No forms.