Romanian fiscal compliance
Romanian fiscal compliance
Section titled “Romanian fiscal compliance”Every Romanian customer has the same compliance baseline (ANAF e-Factura, GDPR, EAA accessibility, Romanian VAT 21%) plus niche-specific obligations on top. This page is the operator’s single source of truth — start with the Common section, then drop into the matching niche.
Common — applies to every RO niche
Section titled “Common — applies to every RO niche”ANAF e-Factura
Section titled “ANAF e-Factura”Mandatory for every B2C and B2B sale by a Romanian company since 2025-07-01. The framework’s efactura-ro plugin handles XML generation, ANAF SPV upload, status polling, and PDF rendering.
Setup checklist:
- Register at ANAF SPV —
https://www.anaf.ro/anaf/internet/SPV/. Get the digital certificate or DigiSign token. This is a multi-week process; plan ahead. - Generate OAuth credentials — at
anaf.ro/oauth-developer-register, register your firm’s CIF + redirect URL. Receiveclient_id+client_secret. - Configure env:
Terminal window ANAF_CIF=12345678 # no RO prefixANAF_OAUTH_TOKEN=<bearer from SPV>ANAF_CLIENT_ID=<oauth client>ANAF_CLIENT_SECRET=<oauth secret>ANAF_MODE=test # flip to `prod` after live KYC - Run a test submission — admin → Settings → Fiscal → “Test ANAF connection”. Submits a fake invoice to the test SPV. Must return
approved. - Enable on a real order — flip
ANAF_MODE=prod. The next paid order automatically generates an XML, uploads to SPV, polls for status, and stores theindex_id(ANAF’s unique invoice id) on the order row.
Operator monitoring: super-admin → /installs shows e-Factura submission failures per tenant. Common causes: expired OAuth token (refresh via client_id/client_secret), invalid customer CIF, mismatched VAT.
Retention: ANAF requires 10-year retention for all submitted invoices. The efactura-ro plugin stores a copy of every XML + the ANAF response in the efactura_invoices table. Don’t delete those rows. Backup includes them by default (Backup & Restore).
Romanian VAT
Section titled “Romanian VAT”- Standard rate: 21% (changed from 19% on 2025-08-01).
- Reduced rate 11% for some categories (food, books, medicines — see ANAF VAT-rate-changes 2025-08).
- 0% (intra-EU B2B with VIES) — automated via the
efactura-roplugin’s VIES-validation hook. - Exempt — services to non-EU clients (per Article 268, Cod Fiscal), some medical/educational services.
The framework’s packages/core/src/tax.ts implements the rate matrix per niche + per category. Tenants can override per-product if they have categories with mixed rates.
Important — Romanian invoices must show the VAT base + the VAT amount + the total in separate lines, in RON. The framework auto-converts from the storefront currency at the order’s exchange rate (BNR rate of the day, fetched daily by the bnr-rates worker).
- Consent log — every consent action (newsletter, cookies, marketing emails, profile-data processing) is recorded with timestamp + IP + actor-id in the
gdpr_consent_logtable. Required by Art. 7(1) GDPR. The framework auto-records this on every consent UI interaction. - Right to be forgotten — admin → Customers → ⋯ → “Anonymise”. Replaces PII with deterministic hashes; preserves order history rows for ANAF retention but disconnects them from the customer identity. Audit-logged.
- Data export — Customer self-service via storefront → Account → “Export my data”. Returns a JSON of every row that mentions their
customer_id. Async job (generates a tarball + emails the link). - Retention — default 30 days after archive (configurable in
/settings). Hard-cleanup cron drops the rows after the window. - DPO contact — every page footer links to a Privacy Policy that names the data protection officer. Verify yours is current; failure is a real ANSPDCP fine vector.
EAA accessibility
Section titled “EAA accessibility”European Accessibility Act mandates WCAG 2.1 AA from 2025-06-28 for any commerce site selling to EU consumers. The framework’s theme-* packages all ship with AA-conformant defaults:
- Colour contrast ≥ 4.5:1 (text) / 3:1 (UI elements)
- Keyboard navigation across the full storefront
- Focus indicators on every interactive element
- Skip-link to main content
- ARIA labels on icon-only buttons
langattribute set toroor per-tenant locale
Customer obligation: every customer publishes an Accessibility Statement on their site (template at /legal/accessibility-statement), updated annually. The framework provides the page; the customer fills in their compliance level + contact for issues. Failure is a real ANSPDCP fine vector under EAA implementation Law 232/2022.
Cookie consent
Section titled “Cookie consent”The framework’s storefront ships with a cookie consent banner (per Decision 200/2018 ANSPDCP + GDPR). Categories: strictly-necessary (always on), performance, advertising. The banner blocks third-party scripts (META_PIXEL_ID, GA4_MEASUREMENT_ID, TIKTOK_PIXEL_ID, TAWKTO_WIDGET_ID) until the matching category is granted.
Don’t bypass the banner via the admin UI for “convenience” — that’s a clear GDPR breach.
Per-niche details
Section titled “Per-niche details”ecommerce niche
Section titled “ecommerce niche”Payment options + ANAF integration
Section titled “Payment options + ANAF integration”Two recommended payment paths for Romanian ecommerce:
| Driver | Card schemes | Notes |
|---|---|---|
| Netopia | All RO banks | Local processor. Lower per-transaction fees. Plugin: payment-netopia. |
| EuPlatesc | All RO banks | Local processor. Strong fraud detection. Plugin: payment-euplatesc. |
| Stripe | International | Use for cross-border tenants. Plugin: payment-stripe. Higher fees. |
Paid orders → XML → ANAF SPV → invoice number issued → emailed to customer with PDF + XML attached.
Shipping + AWB
Section titled “Shipping + AWB”The shipping plugins (shipping-sameday, shipping-fan, shipping-dpd) automate AWB generation. The AWB number lands on the order record and triggers the e-Factura submission once the customer’s “delivered” hook fires (or on a configurable threshold — invoice on shipment is the default for cash-on-delivery; invoice on order for prepaid).
Returns (Legea 449)
Section titled “Returns (Legea 449)”Customers have 14 days to return for any reason for B2C distance contracts. The framework’s Returns flow (admin → Orders → Returns) generates a return AWB via the same shipping plugin and emits a credit note (factură de stornare) via efactura-ro automatically.
Don’t disable the return flow. Refusing 14-day returns on a B2C distance sale is a real fine vector.
services niche
Section titled “services niche”Services niches (clinics, salons, fitness) sell bookings, not goods. Compliance differs:
- Bonul fiscal — Romanian law requires a fiscal receipt (
bonul fiscal) at the moment of payment for services rendered. Theniche-services-posplugin (Pro tier and above) wraps a fiscal printer driver. Invoice (factură) replaces bonul if the customer is a B2B with a VAT number. - Cabinete medicale — additional ASP/CAS reporting requirements apply if the clinic accepts state-insurance patients. Out-of-scope for the default plugin; customer must integrate via their CMS-vendor’s API.
- Fitness + sport — no extra fiscal layer beyond standard VAT 21%. Sport facilities can opt into the microîntreprindere 1% regime if turnover is under €500k — this is a per-customer fiscal advisor decision, not a framework setting.
real-estate niche
Section titled “real-estate niche”Real-estate listings + lead capture have minimal direct fiscal impact at the platform level — the actual transactions happen offline (notary). The framework’s compliance role is:
- Lead-capture forms log GDPR consent before storing PII
- Listing photos + descriptions are not fiscal records — no ANAF invoice unless the agency itself sells a service via the platform (e.g. “premium listing fee”)
- If the agency monetises premium listings on the storefront, those transactions follow the standard ecommerce VAT + e-Factura path
travel niche
Section titled “travel niche”Travel niches (hotels, packages, deposits) have special VAT rules:
- Tour-operator margin scheme (Cod Fiscal Art. 311) applies when the tenant resells third-party services (hotel + flight + transfer). The VAT base is the margin (price - cost), not the full price. The
niche-hotelplugin’s pricing engine auto-detects this scenario and emits the correct invoice. - Single-vendor hotels (selling their own rooms only) follow standard VAT 21%.
- Deposits — the 30% deposit at booking is not fully VAT’d at booking time; only the margin portion is. The remaining 70% is VAT’d at check-in. The plugin handles the split automatically.
This is one of the trickiest niches fiscally. Recommend customers consult their own fiscal advisor before going live.
Operator checklist (issue when onboarding any RO customer)
Section titled “Operator checklist (issue when onboarding any RO customer)”- ANAF SPV registration confirmed (
anaf.ro/anaf/internet/SPV/) - OAuth
client_id+client_secretcaptured + tested - Test invoice submitted in
ANAF_MODE=test— statusapproved - Customer’s CIF validated against ANAF taxpayer registry
- VAT rate (21% standard) confirmed in admin → Settings → Fiscal
- BNR rates worker is running (admin → Activity → recent
bnr-rates.fetchevents) - Privacy Policy + Terms + Cookie Policy + Accessibility Statement pages populated for the tenant’s domain
- DPO contact set in the Privacy Policy template
- Cookie consent banner verified blocks third-party scripts before consent
- Returns flow tested end-to-end (B2C ecommerce only)
- If services niche: fiscal printer connected + tested at the POS
- If travel niche: tour-operator margin scheme confirmed with the customer’s advisor
- Backup includes
efactura_invoicestable + GDPR consent log (verify with Backup & Restore)
See also
Section titled “See also”- Customer Onboarding — full provisioning playbook
- Environment Variables —
ANAF_*,STRIPE_*,NETOPIA_*env keys - Architecture — how the e-Factura plugin integrates
plugins/efactura-ro— plugin source- ANAF e-Factura technical specs:
https://mfinante.gov.ro/web/efactura/specificatii-tehnice - ANSPDCP (data protection authority):
https://www.dataprotection.ro/ - EAA national implementation: Law 232/2022