VeriFactu records
The billing record behind each invoice under VeriFactu: how it is generated, chained and sent to AEAT, and what to do with AEAT's answer.
Under VeriFactu every issued invoice produces a billing record that goes to AEAT. BeeL. generates, chains and submits it; these rules cover what that asks of your integration and of the issuing business.
13 rules: 8 from the law, 4 AEAT criteria, 1 BeeL. rule. How to read a rule.
Each issued invoice gets a billing record built from its data
When an invoice is issued, its billing record (registro de alta) is generated at that moment from the invoice's own data: issuer, recipient, number, dates, type, description, totals, regime and the tax breakdown of each line. BeeL. generates it; you classify each line correctly.
- Why
- The record is what AEAT registers. A line classified wrongly on the invoice is registered wrongly too, and only a later document can change it.
- Responsibility
- Checked by the API: BeeL. applies it.
- Applies to
- Operations
issueCompanyInvoiceInvoices of a company under VeriFactu.
Legal basisRD 1007/2023 (RRSIF), art. 9 · RD 1007/2023 (RRSIF), art. 10.1
«deberán generar automáticamente un registro de facturación de alta de forma simultánea o inmediatamente anterior a la expedición de cada factura.»«El registro informático de facturación de alta incluirá la siguiente información:»Classifying an exempt line as a 0 % taxed line: AEAT registers a taxed operation.
Sending the exemption reason on the line, so the record carries the exempt base and its cause.
The record goes to AEAT as soon as the invoice is issued
Every billing record is sent to AEAT continuously and automatically, as the invoice is issued. BeeL. submits it without a call from you; issue each invoice when the operation happens rather than holding drafts to issue in batches.
- Why
- Under VERI*FACTU the immediacy of the submission is part of the record's security. There is no per-invoice switch and no later submit step.
- Responsibility
- Checked by the API: BeeL. applies it.
- Applies to
- Operations
issueCompanyInvoiceInvoices of a company under VeriFactu.
Legal basisRD 1007/2023 (RRSIF), art. 16.1 · AEAT, Preguntas frecuentes SIF y VERI*FACTU, Sistemas VERI*FACTU
«de forma continuada, segura, correcta, íntegra, automática, consecutiva, instantánea y fehaciente todos los registros de facturación generados»«La inmediatez del envío a VERI*FACTU es parte del sistema de seguridad de los registros de facturación, por lo que se aplica en todos los casos.»Keeping a day's sales as drafts and issuing them all at midnight.
Issuing each invoice when the sale happens, so its record goes out with it.
Explained inAuto-submit policy
VERI*FACTU is kept until the end of the year
Once a NIF has sent its first record under VERI*FACTU, it keeps that modality at least until 31 December of that year. Leaving it is declared in a submission before the year ends.
- Why
- The option is annual: switching a NIF off in the middle of the year breaks the obligation it took on with its first submission.
- Responsibility
- Responsibility: the issuing business.
- Applies to
- A NIF that has started sending records under VERI*FACTU.
Legal basisRD 1007/2023 (RRSIF), art. 16.5 · Orden HAC/1177/2024, art. 17.2
«La opción en el uso de los «Sistemas de emisión de facturas verificables» se prolongará, al menos, hasta la finalización del año natural en el que se haya producido, de forma efectiva, el primer envío de los registros de facturación.»«El funcionamiento como «VERI*FACTU» deberá mantenerse siempre al menos hasta el final del último año en que haya funcionado como tal, es decir, hasta el 31 de diciembre de dicho año.»Planning to leave VERI*FACTU in the same year the NIF sent its first record.
Deciding before year end whether the NIF continues next year.
BeeL. generates the hash and the chain
Do not compute a hash or chain records yourself. Each record carries a hash and refers to the previous record of the same issuer; BeeL. generates both when the invoice is issued.
- Why
- The chain is what makes the records traceable from the first to the last. A second chain kept by your system would not be the one AEAT receives.
- Responsibility
- Checked by the API: BeeL. applies it.
- Applies to
- Invoices of a company under VeriFactu.
Legal basisRD 1007/2023 (RRSIF), art. 8.2.b) · RD 1007/2023 (RRSIF), art. 12 · Orden HAC/1177/2024, art. 7.a)
«La trazabilidad de los registros de facturación, que deberán estar encadenados de manera que pueda verificarse su rastro siguiendo su secuencia de creación desde el primero al último.»«deberán añadir una huella o «hash» a los registros de facturación de alta y de anulación»«4.º Los primeros 64 caracteres de la huella o «hash» del registro de facturación inmediatamente anterior.»Computing a SHA-256 over your own invoice fields and sending it with the invoice.
Issuing through BeeL. and reading verifactu.invoice_hash from the invoice if you need it.
One chain per NIF, one company per NIF
Records of each taxpayer are kept apart, in a chain of their own. Create one company per NIF and issue each invoice from the company of the NIF that issues it; show your users which one they are operating.
- Why
- A system used by several taxpayers must keep their records separate and meet the requirements for each one; an invoice issued from the wrong company lands in another taxpayer's chain.
- Responsibility
- Responsibility: your integration.
- Applies to
- Accounts that invoice for several NIFs.
Legal basisRD 1007/2023 (RRSIF), art. 7.a) · Orden HAC/1177/2024, art. 7.c)
«siempre que los registros de facturación de cada obligado tributario se encuentren diferenciados y se cumplan los requisitos exigidos en este Reglamento por separado para cada uno de los obligados tributarios»«Para un determinado obligado tributario, cada sistema informático producirá una única cadena de registros de facturación»Issuing the invoices of two businesses from one company, told apart by a series prefix.
Creating a company per NIF and targeting each call at the right one.
Explained inOverview › The model
No certificate is needed to sign records
Records sent under VERI*FACTU need no electronic signature: their hash is enough. Neither the issuer nor the integrator hands BeeL. a digital certificate for the submissions.
- Why
- Integrations that plan a signing step, or ask their customers for a certificate, add work the regulation does not require.
- Responsibility
- Checked by the API: BeeL. applies it.
- Applies to
- Invoices of a company under VeriFactu.
Legal basisRD 1007/2023 (RRSIF), art. 16.3
«no tendrán la obligación de realizar la firma electrónica de los registros de facturación a la que se refiere el artículo 12 de este Reglamento, siendo suficiente con que calculen la huella o «hash» de dichos registros.»Asking each customer to upload a certificate so that their invoices can be signed.
Asking the NIF holder to sign the AEAT representation once, and nothing else.
Keep invoicing when AEAT is unreachable
Do not stop invoicing because AEAT is unavailable. The invoice is issued and numbered as usual, the submission is retried, and a record that goes out on a later day than the issue date is flagged as a late submission.
- Why
- An incident in the submission never justifies stopping invoicing, and records have to be sent as soon as it is possible, in order and flagged as late.
- Responsibility
- Checked by the API: BeeL. applies it.
- Applies to
- Invoices of a company under VeriFactu.
Legal basisOrden HAC/1177/2024, art. 16.4 · AEAT, Preguntas frecuentes SIF y VERI*FACTU, Sistemas VERI*FACTU
«se deberá proceder a la remisión de los registros de facturación en cuanto sea posible, respetando el orden temporal de generación de los registros de facturación.»«Incidencias como las mencionada, que afectan a la remisión a la AEAT , NO suponen en ningún caso que deba interrumpirse la facturación de la empresa.»Queueing sales in your system until AEAT is back, then issuing them with the day's date.
Issuing through BeeL. as usual and following each invoice with the verifactu.status.updated webhook.
Follow submission_status and fix what AEAT rejects
Track each issued invoice's verifactu.submission_status (NOT_SUBMITTED, PENDING, ACCEPTED, REJECTED, VOIDED) through the verifactu.status.updated webhook and a periodic reconciliation. A transient AEAT error keeps the invoice PENDING while BeeL. retries it. A REJECTED invoice is not registered: read its error_message, and its error_code when AEAT gave one, and fix it. GET /v1/companies/{company_id}/invoices/{invoice_id}/verifactu-records lists each record of the invoice, its cancellation included, with its own status.
- Why
- A
200on issue means BeeL. accepted the invoice, not that AEAT registered it. A rejection nobody reads leaves an invoice outside AEAT's records. - Responsibility
- Responsibility: your integration.
- Applies to
- Operations
getCompanyInvoiceInvoices of a company under VeriFactu.
Treating the 200 of the issue call as proof that AEAT registered the invoice.
Subscribing to verifactu.status.updated and, on a schedule, listing invoices REJECTED or still NOT_SUBMITTED to reconcile them.
Check the data AEAT accepted with errors
When AEAT accepts a record but reports an error (ACCEPTED with an error_code), check the data it flagged, usually the recipient's tax ID and name. If it was right, nothing else is needed. If it was wrong, fix it in the customer's data and correct the invoice already recorded with an R4 corrective that carries the corrected recipient (COR-017); the following invoices take the fixed data.
- Why
- A record accepted with errors stays in AEAT with those errors until a later document fixes them, and for a recipient's data that document is a corrective.
- Responsibility
- Responsibility: your integration.
- Applies to
- Invoices
ACCEPTEDwith anerror_code.
Legal basisAEAT, Validaciones y errores VERI*FACTU (v1.2.2), 4.3.1
«Los registros de facturación con errores admisibles serán “aceptados” y registrados por los sistemas de la AEAT, pero deberán ser subsanados para poder llevar a cabo el tratamiento y validación de los mismos.»Reading ACCEPTED and ignoring the error_code next to it.
Reading error_message, confirming the customer's tax ID was mistyped, fixing it in the customer's data and issuing the R4 corrective of the recipient's data for the invoice already recorded.
Explained inHandling AEAT rejections › Accepted with errors
Subsanación is only for errors that need no corrective
A subsanación replaces a registration record with a corrected one, and applies only when the error needs no corrective invoice. When AEAT refused the record for a cause outside the invoice's data, such as an issuer not yet in the census, fix the cause and contact BeeL. with the invoice. Any error in what the invoice says is fixed with a corrective.
- Why
- AEAT allows a subsanación only when the cause does not require a corrective invoice; a wrong amount, customer or description does.
- Responsibility
- Responsibility: your integration.
- Applies to
- Records rejected or accepted with errors.
Legal basisAEAT, Validaciones y errores VERI*FACTU (v1.2.2), 4.3.1 · AEAT, Preguntas frecuentes SIF y VERI*FACTU, Registros de facturación: alta
«Solo podrá llevarse a cabo una subsanación cuando no se trate de una causa que exija la emisión de una factura rectificativa (u otro mecanismo contemplado en el Reglamento de Facturación).»«podrá ser una anulación completa del registro inicial o una subsanación / sustitución (es decir sustitución del “registro de alta” por otro registro subsanado)»Asking for a subsanación of an invoice whose recipient NIF was wrong.
Getting the issuing NIF registered in the AEAT census, then contacting BeeL. with the invoice ID.
The NIF holder signs the AEAT representation first
Before a NIF issues real invoices under VeriFactu, its holder signs the AEAT representation that lets BeeL. submit the records on the taxpayer's behalf. Enabling VeriFactu without it is rejected with VERIFACTU_REPRESENTATION_REQUIRED; issuing is rejected with EMISSION_NOT_READY, with NIF_REPRESENTATION_REQUIRED among the blockers in details.
- Why
- Records are sent by the taxpayer or by someone acting as its representative. Without the signed representation there is nobody entitled to send them.
- Responsibility
- Checked by the API: a request that breaks it is rejected with the error codes listed.
- Applies to
- Operations
generateCompanyRepresentationsubmitCompanyRepresentationupdateCompanyVeriFactuConfigurationissueCompanyInvoiceProduction (Live) NIFs; sandbox needs no representation. - Error codes
VERIFACTU_REPRESENTATION_REQUIRED422,EMISSION_NOT_READY422,NIF_REPRESENTATION_REQUIRED
Legal basisOrden HAC/1177/2024, art. 5
«La remisión podrá ser efectuada por el propio obligado tributario o por un tercero que actúe en su representación»Enabling VeriFactu in Live for a new NIF straight after creating it: the API answers VERIFACTU_REPRESENTATION_REQUIRED.
Generating the representation document, having the holder sign it, uploading it, and then enabling VeriFactu.
Tax amounts are base times rate
The tax amount of each breakdown equals its base times its rate, with the same sign as the base. BeeL. computes it from the rate of each line: the API takes rates, never tax amounts.
- Why
- AEAT checks the tax amount against base × rate, allowing 10 € of difference, and rejects the record beyond it.
- Responsibility
- Checked by the API: BeeL. applies it.
- Applies to
- Every taxed line.
Legal basisAEAT, Validaciones y errores VERI*FACTU (v1.2.2), 3.1.3.15.7 CuotaRepercutida
«CuotaRepercutida y BaseImponibleOimporteNoSujeto deben tener el mismo signo.»Keeping a tax amount computed by your system and expecting BeeL. to register it.
Sending the rate on each line (main_tax) and reading the computed amounts from the response.
An invoice AEAT would reject is not numbered
Before an invoice recorded with VeriFactu takes its number, BeeL. builds the billing record it will send and checks it against AEAT's validations: the invoice type, the recipient, the correction, the tax breakdown (at most 12 groups, rates with two decimals, the rate and surcharge accepted on the operation date, what each regime key admits) and the operation date. If AEAT would reject the record, the invoice is not issued and the number is not used: the API answers 422 with the specific code, or VERIFACTU_RECORD_NOT_DECLARABLE with the AEAT section in its message when there is no specific one. The record that is checked is exactly the one that is sent.
- Why
- AEAT rejects a record after the invoice already has its number, and a gap in the numbering cannot be repaired.
- Responsibility
- Checked by the API: a request that breaks it is rejected with the error codes listed.
- Applies to
- Operations
issueCompanyInvoicecreateCompanyCorrectiveInvoiceInvoices recorded with VeriFactu. - Error codes
VERIFACTU_RECORD_NOT_DECLARABLE,INVOICE_TAX_BREAKDOWN_TOO_LONG,INVOICE_TAX_RATE_TOO_MANY_DECIMALS422,EXEMPTION_INCOMPATIBLE_WITH_REGIME400,VAT_RATE_NOT_ACCEPTED_ON_DATE422,SURCHARGE_RATE_NOT_ACCEPTED_ON_DATE422,OPERATION_DATE_TOO_OLD,INVOICE_REQUIRES_AT_LEAST_ONE_NORMAL_LINE422
Legal basisAEAT, Validaciones y errores VERI*FACTU (v1.2.2), 3.1.3.13 Agrupación Destinatarios · AEAT, Validaciones y errores VERI*FACTU (v1.2.2), 3.1.3.15.4 CalificacionOperacion · AEAT, Validaciones y errores VERI*FACTU (v1.2.2), 3.1.3.15.5 OperacionExenta
«Si TipoFactura es “F2” o “R5”, la agrupación Destinatarios no puede estar cumplimentada.»«Si CalificacionOperacion es “S2”, TipoFactura solo puede ser “F1”, “F3”, “R1”, “R2”, “R3” y “R4”.»«Si Impuesto = “01” (IVA), “03” (IGIC) o no se cumplimenta (considerándose “01” - IVA), y ClaveRegimen es igual a “01”, no pueden marcarse los valores de OperacionExenta “E2” y “E3”.»Issuing a draft saved before a rule existed, with an exemption under article 21 and regime key 01: the API answers EXEMPTION_INCOMPATIBLE_WITH_REGIME and the draft keeps no number.
Fixing the draft (regime key 02 for an export) and issuing it again.