Skip to content
Log in

Verifactu

The Anti-Fraud Law (Law 11/2021) mandates that businesses must ensure their invoicing and accounting systems meet strict technical standards to prevent data manipulation. Royal Decree 1007/2023 further defines the technical requirements for digital billing systems, emphasizing the need for standardized invoice formats that can be easily accessed by tax authorities.

These regulations require businesses to adopt systems capable of securely generate, store, and transmit invoices and tax reports. B2Brouter’s REST API is a technical solution that allows your business to easily be 100% compliant offloading the complexities to B2Brouter and focusing on the business logic of your system.

Verifactu is a compliance system designed to simplify the process of meeting the invoicing requirements outlined in the Anti-Fraud Law. It ensures that all invoices generated by businesses are securely transmitted to the Tax Authority to be verified for integrity and authenticity by both the Tax Authority and the Customer. The Spanish Tax Authority is the AEAT (“Agencia Estatal de Administración Tributaria”).

Verifactu involves the immediate, real-time submission of invoice data to the AEAT as soon as the invoice is issued. This ensures that no modifications can be made after the invoice is issued, guaranteeing its security. Additionally, the invoice contains a QR code, allowing the recipient to verify its tax compliance through the AEAT’s platform.

In practice, Verifactu requires:

  • Creating a tax report XML file.
  • Computing a digital fingerprint for each tax report. This includes a hash chain to create a tamper-proof trail.
  • Assembling a “Libro de Registro” or Ledger that may include one or several tax reports.
  • Authenticated submission of the “Libro de Registro” to the AEAT using a qualified electronic certificate.
  • Obeying the rate-limited requests established by the AEAT (max. 1 call per minute, unless submitting >1,000 invoices).
  • Generating a QR code for invoice verification, to be included in the issued invoice.
  • Processing the responses from the AEAT for each tax report.

With B2Brouter you can abstract much of the complexities of this process, and comply with the Anti-Fraud Law by issuing just a few REST calls to the API. You will not need your own qualified electronic certificate because B2Brouter is a Social Collaborator in Tax Management. You just need a valid B2Brouter API Key.

Testing environments: Use sandbox for initial API testing and payload validation — sandbox simulates Verifactu submissions so you can exercise the invoice lifecycle without hitting the AEAT. For full end-to-end testing with the AEAT test endpoint, use the staging environment (api-staging.b2brouter.net).

The first step is to set up the configuration for Verifactu for each one of the Companies for which you want to submit tax reports. You can refer to the Tax Report Settings Guide for a full description of the process. The call for configuring an account is as follows:

Example request

Terminal window
curl --request GET \
--url https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/tax_report_settings \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{
"tax_report_setting": {
"code": "Verifactu",
"start_date": "2025-04-06",
"auto_generate": true,
"auto_send": true,
"reason_vat_exempt": "E1",
"special_regime_key": "01",
"reason_no_subject": "N1",
"credit_note_code": "R1"
}
}'

If you are using B2Brouter for both issuing invoices and reporting them to the Tax Authority, once you have correctly configured your account, you can operate as you’d normally do for issuing invoices.

The issued invoices will contain the mandatory QR code, and the Verifactu tax report will be sent automatically to the AEAT. This is an example of a call to create and issue an Invoice:

Example request:

Terminal window
curl --request POST \
--url https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/invoices \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'content-type: application/json' \
--data '{
"send_after_import": true,
"invoice": {
"date": "2025-04-15",
"due_date": "2025-05-15",
"number": 48,
"payment_method": 1,
"contact": {
"name": "contact.name",
"address": "contact.address",
"city": "contact.city",
"province": "contact.province",
"postalcode": "28938",
"country": "es",
"email": "john.doe@example.com",
"language": "es",
"currency": "EUR",
"terms": "15",
"payment_method": 1,
"tin_scheme": 9920,
"tin_value": "ESA28388510"
},
"invoice_lines_attributes": [
{
"quantity": 10.0,
"description": "line.description",
"price": 11.0,
"unit": 9,
"taxes_attributes": [
{
"name": "IVA",
"percent": 21.0,
"category": "S"
}
]
}
]
}
}'

In the response of the POST REST call for creating an invoice, if send_after_import is set to true, you will find a section tax_report_ids in which you’ll find the ID of the tax report associated with the invoice.

You can access the complete tax report, including the QR code, its identifier, its state, and all other fields, by calling the get tax report endpoint with the tax report ID provided in the response of the create invoice call.

The state of the tax report will always be processing in the response of the POST call. You must check the life cycle of the tax report. You have two options:

  • The recommended way is using the tax report web hook. Final states: registered, error, and registered_with_errors

  • Polling the state of the tax report with get tax report endpoint until the state field is registered, error or registered_with_errors.

If you are not using B2Brouter for issuing invoices, need more control over the process of generating and processing tax reports, or expect a high volume of tax reports, you can use the new Tax Report API.

This API is designed for maximum control by the user and high availability. You can either submit tax reports as a JSON payload or as a valid Verifactu XML.

The structure of the JSON format for B2Brouter tax reports is based on PEPPOL Continuous Transaction Control (CTC). B2Brouter Tax Report API is an universal API not only geared towards Verifactu but designed to handle tax reporting around the World.

It’s important to notice that tax reports have tax breakdowns (“desglose” in Spanish) which are the sum of the lines of the original invoice with the same tax. Is the responsibility of your system to aggregate the invoice lines by tax type and category and provide the necessary tax breakdowns. The TaxReport model does not perform any calculations.

To create a tax report you have to call the create tax report endpoint. A minimal and valid tax report:

Example request:

Terminal window
curl --request POST \
--url https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/tax_reports \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{
"tax_report": {
"type": "Verifactu",
"invoice_date": "2025-04-03",
"invoice_number": "11",
"description": "Lorem ipsum...",
"customer_party_tax_id": "B12345678",
"customer_party_country": "es",
"customer_party_name": "Ejemplo S.L.",
"tax_inclusive_amount": 121.0,
"tax_amount": 21.0,
"invoice_type_code": "F1",
"currency": "EUR",
"tax_breakdowns": [
{
"name": "IVA",
"category": "S",
"non_exemption_code": "S1",
"percent": 21.0,
"taxable_base": 100.0,
"tax_amount": 21.0,
"special_regime_key": "01"
}
]
}
}'

The response of this POST call will already contain the field qr with the QR code (codified in base64) that you must include in the invoice for your customer. The content of this QR code is a URL that will allow your customer to check that AEAT has received and processed the tax report derived from their invoice.

Import a Tax Report from an XML Verifactu file

Section titled “Import a Tax Report from an XML Verifactu file”

If your system is capable of generating Verifactu XML files (a RegistroAlta or a RegistroAnulacion from the SuministroInformacion namespace), you can import them directly using the API via the import endpoint.

If the creation of the Tax Report is successful, the response will already contain the QR code and the identifier for the Tax Report. Note that B2Brouter will perform the chaining process regardless of any chaining information in the imported XML.

The state field of the tax report will always be processing after a successful creation. Check the life cycle via:

  • The tax report web hook. Final states: registered, error, annulled, and registered_with_errors

  • Polling the get tax report endpoint until the state field is any of: registered, error, annulled, and registered_with_errors.

Get the XML representation of the tax report

Section titled “Get the XML representation of the tax report”

Use the download tax report endpoint. B2Brouter also includes a field named xml_base64 in the GET response. Note that the XML can only be generated after the tax report has been chained.

B2Brouter has implemented an exhaustive set of validations of Verifactu tax reports based on the specifications published by the AEAT. If there is a validation error the tax report will not be created. You’ll receive a 422: Unprocessable Entity response with all errors in JSON format.

To cancel a tax report (“anulación” in Spanish) use the DELETE verb calling the annullation endpoint.

To correct a tax report (“subsanación” in Spanish) use the PATCH or PUT verbs calling the correction endpoint.

Verifactu tax reports are not send individually to the AEAT, they are bundled in a “Libro de Registro” (Ledger in B2Brouter terms), that contains up to 1000 tax reports. Each tax report has a ledger_id field that identifies the internal ID for the ledger. With that ID you can:

Equivalence between B2Brouter internal tax report fields and Verifactu XML nodes

Section titled “Equivalence between B2Brouter internal tax report fields and Verifactu XML nodes”
B2Brouter Field (based on PEPPOL CTC)Verifactu XML Node
invoice_dateIDFactura > FechaExpedicionFactura
invoice_numberIDFactura > NumSerieFactura
invoice_series_codeIDFactura > NumSerieFactura
supplier_party_nameNombreRazonEmisor
external_referenceRefExterna
correctionSubsanacion
annullationAnulación
previously_refusedRechazoPrevio
invoice_type_codeTipoFactura
amend_typeTipoFactura
amended_numberFacturasRectificadas > IDFacturaRectificada > NumSerieFactura
amended_series_codeFacturasRectificadas > IDFacturaRectificada > NumSerieFactura
amended_dateFacturasRectificadas > IDFacturaRectificada > FechaExpedicionFactura
amended_tax_exclusiveImporteRectificacion > BaseRectificada
amended_tax_amountImporteRectificacion > CuotaRectificada
tax_point_dateFechaOperacion
descriptionDescripcionOperacion
simplified_art7273FacturaSimplificadaArt7273
ticketFacturaSinIdentifDestinatarioArt61d
macrodataMacrodato
issued_by_third_party_or_receiverEmitidaPorTerceroODestinatario
third_party_nameTercero > NombreRazon
third_party_tax_idTercero > NIF
customer_party_nameDestinatarios > IDDestinatario > NombreRazon
customer_party_tax_idDestinatarios > IDDestinatario > NIF or IDOtro > IDType
customer_party_countryDestinatarios > IDDestinatario > IDOtro > CodigoPais
customer_party_tax_schemeDestinatarios > IDDestinatario > IDOtro > IDType
tax_breakdowns[].nameDesglose > DetalleDesglose > Impuesto
tax_breakdowns[].special_regime_keyDesglose > DetalleDesglose > ClaveRegimen
tax_breakdowns[].non_exemption_codeDesglose > DetalleDesglose > CalificacionOperacion
tax_breakdowns[].exemption_codeDesglose > DetalleDesglose > OperacionExenta
tax_breakdowns[].percentDesglose > DetalleDesglose > TipoImpositivo
tax_breakdowns[].taxable_baseDesglose > DetalleDesglose > BaseImponibleOimporteNoSujeto
tax_breakdowns[].taxable_base_at_costDesglose > DetalleDesglose > BaseImponibleACoste
tax_breakdowns[].tax_amountDesglose > DetalleDesglose > CuotaRepercutida
tax_amountCuotaTotal
tax_inclusive_amountImporteTotal
previous_idEncadenamiento > RegistroAnterior > NumSerieFactura
XSD fileDescription
SuministroLR.xsdOperaciones de alta y anulación de los sistemas Verifactu y no Verifactu
RespuestaSuministro.xsdRespuesta de las operaciones de los sistemas Verifactu y no Verifactu
ConsultaLR.xsdOperación de consulta de registros de facturación Verifactu
RespuestaConsultaLR.xsdRespuesta de la operación de consulta de registros de facturación Verifactu
SuministroInformacion.xsdDefinición de tipos comunes

Param: invoice_type_code

CodeDescription
F1Factura (art. 6, 7.2 y 7.3 del RD 1619/2012)
F2Factura Simplificada y Facturas sin identificación del destinatario (art. 6.1.d) RD 1619/2012
F3Factura emitida en sustitución de facturas simplificadas facturadas y declaradas
R1Factura Rectificativa (Error fundado en derecho y Art. 80 Uno Dos y Seis LIVA)
R2Factura Rectificativa (Art. 80.3)
R3Factura Rectificativa (Art. 80.4)
R4Factura Rectificativa (Resto)
R5Factura Rectificativa en facturas simplificadas

Param: special_regime_key

CodeDescription
01Operación de régimen general.
02Exportación.
03Operaciones a las que se aplique el régimen especial de bienes usados, objetos de arte, antigüedades y objetos de colección.
04Régimen especial del oro de inversión.
05Régimen especial de las agencias de viajes.
06Régimen especial grupo de entidades en IVA (Nivel Avanzado)
07Régimen especial del criterio de caja.
08Operaciones sujetas al IPSI / IGIC.
17Operación acogida a alguno de los regímenes previstos en el Capítulo XI del Título IX (OSS e IOSS)
18Recargo de equivalencia.
19Operaciones de actividades incluidas en el Régimen Especial de Agricultura, Ganadería y Pesca (REAGYP)
20Régimen simplificado

Param: non_exemption_code

CodeDescription
S1Operación Sujeta y No exenta - Sin inversión del sujeto pasivo.
S2Operación Sujeta y No exenta - Con Inversión del sujeto pasivo.

Param: no_subject_code

CodeDescription
N1Operación No Sujeta artículo 7, 14, otros.
N2Operación No Sujeta por Reglas de localización.

Param: exemption_code

CodeDescription
E1Exenta por el artículo 20
E2Exenta por el artículo 21
E3Exenta por el artículo 22
E4Exenta por los artículos 23 y 24
E5Exenta por el artículo 25
E6Exenta por otros

Param: customer_party_tax_scheme

CodeDescription
02EU VAT ID (NIF-IVA)
03Passport
04Official ID issued by country of residence
05Certificate of residence
06Other supporting document
07Not registered