Customer story · Our own product · verifactu.biz
From 2026, every invoice a Spanish freelancer issues needs a chained record and a QR code the tax agency can check. Under VERI*FACTU, a copy must also be sent to the AEAT. We built an invoicing app where you type or dictate one sentence, review the draft and confirm. The system does the rest.
· 4 min read

- Industry
- Invoicing software for freelancers and small businesses · VERI*FACTU
- Location
- Spain
- Period
- September – October 2026
- Scope
- Chat and voice assistantVERI*FACTU issuingSubmission to the AEATClients and paymentsTax forms 303 and 130Plans and billing with StripeMobile app (PWA)
- Benefits
- A sentence like "window repair 180 € VAT included" becomes a draft with the base, VAT and income tax withholding calculated
- Every invoice gets its chained SHA-256 hash and QR code, and is sent to the AEAT automatically
- Each invoice and the invoice list show its status with the tax agency, with an alert when something fails
- What you type or dictate never leaves your browser: the assistant uses no external AI
From the first commit to a private beta in production
Simultaneous invoices issued in the integration tests without breaking the hash chain
Calls to an external AI: the assistant and dictation run in the browser
Real time from sentence to issued invoice (the target is under 30 seconds)
Context
Under Spain's invoicing systems regulation (VERI*FACTU), a freelancer's invoicing software has to create a record for every invoice. It has to chain each record to the previous one with a hash and print a QR code the tax agency can check. In VERI*FACTU mode, it also has to send the record to the AEAT.
For a plumber, a designer or a small workshop, that usually means learning accounting software. We wanted the opposite: issuing a legal invoice should take as much effort as sending a message.

How it works, step by step
We followed a freelancer from opening the site to their invoice reaching the tax agency:
- Describe
- Type or dictate what you sold: "Invoice Talleres Martínez SL for two hours of design at 30 € an hour plus VAT". No account needed to start.
- Review
- The assistant completes the description, quantity, price, VAT and withholding, and finds the client by tax ID. Changes can be asked for in the chat too: "VAT at 10", "add materials 20 €".
- Sign up
- The first time, it asks for an email and a 6-digit code. The issuer's tax ID and name are checked against the AEAT register. If they can't be identified, nothing is issued.
- Confirm
- The invoice is shown as a document. It is only issued once the user ticks that they have reviewed it: an issued invoice can't be edited or deleted.
- Issue
- A single transaction assigns the number, computes the chained hash, stores the record and queues it for submission.
- Submit and track
- A background process sends the record to the AEAT and stores the reply. The invoice shows whether it is queued, accepted or rejected, with the PDF and QR code to send to the client.



The hard parts
The hash chain can't break. If two invoices from the same issuer are issued at the same moment, they can't both point to the same previous record. Issuing happens in one transaction that locks the issuer, and a unique index in the database stops the chain from forking. We test it with 50 simultaneous invoices against a real Postgres.
The tax agency uses Madrid time. The record's timestamp, the yearly numbering and the daily limits are always computed in Europe/Madrid, wherever the server runs.
The AEAT doesn't always answer the first time. Submission starts right after issuing and runs in batches that respect the wait time the AEAT itself asks for. It retries, and it classifies every error (missing authorisation, duplicate…) so the user is told what to do.
The assistant can't invent an amount. That's why it isn't a language model. It is a set of rules that understand numbers written as words, "plus VAT" or "VAT included". Whatever the rules don't understand, they leave blank. Dictation runs Whisper inside the browser, so the audio never leaves the device.
And what's issued is immutable: records, invoices and the audit log can't be changed or deleted, not even from the server.
Everything else an invoicing app needs
Beyond issuing, the app covers the rest of a freelancer's month. The home screen shows what's been billed and what's still unpaid. The invoice list has filters and exports to CSV, Excel or a ZIP of PDFs. There is a page for each client, plus due-date alerts and payment reminders.
Under Taxes it calculates what belongs on the quarter's form 303 (VAT) and form 130 (income tax) from the invoices issued, with the days left to file. If an accountant handles it, they can be invited in.
The free plan has a daily and monthly invoice limit. Paid plans (a monthly fee or a fee per invoice issued) are billed with Stripe. Each billable invoice is recorded in the same transaction that issues it, so none is lost or counted twice.




How we test it
With money and the tax agency involved, every change passes a continuous integration workflow before reaching production:
- Types and style
- Strict TypeScript and ESLint on every push to main and every pull request.
- Unit tests
- Whole cents and rounding, Madrid-time dates, the chat interpreter with real sentences, the hash checked against an independent library, the PDF and the QR code.
- Against the AEAT
- Submission batches are validated against the AEAT's official XSD schemas, without sending anything.
- Integration
- A real embedded Postgres: 50 simultaneous invoices, drafts, clients, payments, billing, several tax IDs per account and the submission process against a simulated AEAT.
- End to end
- Playwright walks through the public site on every change. Another test is ready to issue a complete first invoice against the preview deployment, with Supabase and the AEAT test environment.
- Deployment
- Every pull request gets a Vercel preview deployment. Production runs in Frankfurt, next to the database.
Result
In eleven days we went from an empty repository to a private beta in production. It has full VERI*FACTU issuing, submission to the AEAT, payments, taxes, paid plans and an app you can install on your phone.
Before it opens to everyone, three things remain that don't depend on the code. We have to validate submission with real certificates, get a legal review of the terms, and measure the real time from sentence to accepted invoice. That's why that figure shows as pending above.
Next step
Do you have a process with strict rules that's still done by hand? Let's talk about turning it into a product.