Build a TicketBAI Invoice XML (País Vasco)
Skill: Convert an issued invoice into a TicketBAI XML
Region: Spain (España) — País Vasco
Category: E-invoicing / Anti-fraud — TicketBAI
Does: Takes an issued sales invoice and produces a TicketBAI XML business payload — the anti-fraud invoicing record required by the Haciendas Forales of the Basque Country, carrying the invoice data, the chaining reference to the previous invoice (encadenamiento) and the fields from which the signed HuellaTBai (hash) and TBAI identifier/QR are derived.
Standard: TicketBAI (Haciendas Forales de Bizkaia, Gipuzkoa y Araba) — esquema TicketBai v1.2
The final TicketBAI file must be XAdES-signed (an enveloped XML digital signature) before it is valid; the signature, the HuellaTBai hash, the TBAI identifier and the QR code are all produced after signing by the issuing software. The three Diputaciones Forales share the v1.2 schema but have slightly different submission channels and XSD packagings — notably Bizkaia submits through Batuz / LROE (Libro Registro de Operaciones Económicas), while Gipuzkoa and Araba use their own TicketBAI front-ends. The example below shows the unsigned business payload only; insert the <ds:Signature> block and submit through the channel of the relevant Diputación. Validate against the active foral XSD before use.
When this applies
- An entity or self-employed person subject to a Basque foral tax regime (domiciled / operating under Bizkaia, Gipuzkoa or Araba) issues an invoice (ordinary or simplified/ticket) and must generate a TicketBAI record for it.
- One TicketBAI XML is produced per invoice (and per rectification/cancellation), each chained to the previous one via
EncadenamientoFacturaAnterior so the sequence is tamper-evident.
- Excluded / special cases: operations under regimes outside the foral TicketBAI obligation, and the first invoice in a chain (which omits the chaining block). Follow the calendar and subjective scope set by each Diputación.
Input data required
| Input |
TicketBAI element |
| Issuer NIF and name/business name |
Sujetos/Emisor/NIF, ApellidosNombreRazonSocial |
| Customer NIF and name (ordinary invoice) |
Destinatarios/IDDestinatario/NIF, ApellidosNombreRazonSocial |
| Invoice series and number |
CabeceraFactura/SerieFactura, NumFactura |
| Issue date / time |
FechaExpedicionFactura (dd-mm-yyyy), HoraExpedicionFactura (hh:mm:ss) |
| Simplified-invoice flag |
CabeceraFactura/FacturaSimplificada (S/N) |
| Invoice description |
DatosFactura/DescripcionFactura |
| Line items (description, qty, unit & total) |
DetallesFactura/IDDetalleFactura |
| Invoice total |
DatosFactura/ImporteTotalFactura |
| Operation regime key |
Claves/IDClave/ClaveRegimenIvaOpTrascendencia |
| VAT breakdown (rate, base, quota) |
TipoDesglose/.../DetalleIVA |
| Previous invoice reference (chaining) |
HuellaTBai/EncadenamientoFacturaAnterior |
| Issuing software licence & developer |
HuellaTBai/Software |
| Device serial |
HuellaTBai/NumSerieDispositivo |
Document structure
T:TicketBai (xmlns:T="urn:ticketbai:emision")
├── Cabecera
│ └── IDVersionTBai (1.2)
├── Sujetos
│ ├── Emisor
│ │ ├── NIF
│ │ └── ApellidosNombreRazonSocial
│ └── Destinatarios
│ └── IDDestinatario (omit for many simplified invoices)
│ ├── NIF
│ └── ApellidosNombreRazonSocial
├── Factura
│ ├── CabeceraFactura
│ │ ├── SerieFactura
│ │ ├── NumFactura
│ │ ├── FechaExpedicionFactura (dd-mm-yyyy)
│ │ ├── HoraExpedicionFactura (hh:mm:ss)
│ │ └── FacturaSimplificada (S | N)
│ └── DatosFactura
│ ├── DescripcionFactura
│ ├── DetallesFactura
│ │ └── IDDetalleFactura ... (one per line)
│ │ ├── DescripcionDetalle
│ │ ├── Cantidad
│ │ ├── ImporteUnitario
│ │ └── ImporteTotal
│ ├── ImporteTotalFactura
│ └── Claves
│ └── IDClave
│ └── ClaveRegimenIvaOpTrascendencia (e.g. 01)
│ └── TipoDesglose
│ └── DesgloseFactura
│ └── Sujeta
│ └── NoExenta
│ └── DetalleNoExenta
│ ├── TipoNoExenta (S1 | S2)
│ └── DesgloseIVA
│ └── DetalleIVA
│ ├── TipoImpositivo (e.g. 21.00)
│ ├── BaseImponible
│ └── CuotaImpuesto
└── HuellaTBai
├── EncadenamientoFacturaAnterior (omit on the FIRST invoice)
│ ├── SerieFacturaAnterior
│ ├── NumFacturaAnterior
│ ├── FechaExpedicionFacturaAnterior
│ └── SignatureValueFirmaFacturaAnterior
├── Software
│ ├── LicenciaTBAI
│ ├── EntidadDesarrolladora/NIF
│ ├── Nombre
│ └── Version
└── NumSerieDispositivo
Notes: exempt operations use Sujeta/Exenta/DetalleExenta with a CausaExencion instead of NoExenta; non-subject operations use NoSujeta. The ds:Signature element (XAdES) is appended as the last child of T:TicketBai and is what produces the HuellaTBai/QR after emission.
Source → TicketBAI field map
| From the source |
→ TicketBAI element |
| Schema version (fixed) |
Cabecera/IDVersionTBai = 1.2 |
| Seller tax ID |
Sujetos/Emisor/NIF |
| Seller name / razón social |
Sujetos/Emisor/ApellidosNombreRazonSocial |
| Buyer tax ID |
Destinatarios/IDDestinatario/NIF |
| Buyer name |
Destinatarios/IDDestinatario/ApellidosNombreRazonSocial |
| Invoice series |
CabeceraFactura/SerieFactura |
| Invoice number |
CabeceraFactura/NumFactura |
| Issue date |
CabeceraFactura/FechaExpedicionFactura (dd-mm-yyyy) |
| Issue time |
CabeceraFactura/HoraExpedicionFactura (hh:mm:ss) |
| Simplified? |
CabeceraFactura/FacturaSimplificada (S/N) |
| Free-text description |
DatosFactura/DescripcionFactura |
| Each line: description |
IDDetalleFactura/DescripcionDetalle |
| Each line: quantity |
IDDetalleFactura/Cantidad |
| Each line: unit price |
IDDetalleFactura/ImporteUnitario |
| Each line: line total |
IDDetalleFactura/ImporteTotal |
| Invoice grand total |
DatosFactura/ImporteTotalFactura |
| Operation/regime key |
Claves/IDClave/ClaveRegimenIvaOpTrascendencia |
| Subject, not exempt indicator |
DetalleNoExenta/TipoNoExenta (S1/S2) |
| VAT rate |
DetalleIVA/TipoImpositivo |
| Taxable base |
DetalleIVA/BaseImponible |
| VAT amount |
DetalleIVA/CuotaImpuesto |
| Previous invoice series/number/date |
EncadenamientoFacturaAnterior/SerieFacturaAnterior, NumFacturaAnterior, FechaExpedicionFacturaAnterior |
| Previous invoice signature value |
EncadenamientoFacturaAnterior/SignatureValueFirmaFacturaAnterior |
| Software licence |
Software/LicenciaTBAI |
| Developer NIF / name / version |
Software/EntidadDesarrolladora/NIF, Nombre, Version |
| Device serial number |
NumSerieDispositivo |
Code tables
ClaveRegimenIvaOpTrascendencia (Claves / IDClave)
| Code |
Meaning |
01 |
Operación de régimen general / general regime |
02 |
Exportación |
03 |
Bienes usados, objetos de arte, antigüedades (REBU) |
04 |
Régimen especial del oro de inversión |
05 |
Régimen especial agencias de viajes |
06 |
Grupo de entidades en IVA (nivel avanzado) |
07 |
Régimen especial criterio de caja |
51–53 |
Operaciones intragrupo / otras claves de trascendencia tributaria |
TipoNoExenta (subject, not exempt)
| Code |
Meaning |
S1 |
Sujeta y no exenta — sin inversión del sujeto pasivo (no reverse charge) |
S2 |
Sujeta y no exenta — con inversión del sujeto pasivo (reverse charge) |
CausaExencion (when Sujeta/Exenta is used)
| Code |
Meaning |
E1 |
Exenta por art. 20 (operaciones interiores exentas) |
E2 |
Exenta por art. 21 (exportaciones) |
E3 |
Exenta por art. 22 (operaciones asimiladas a exportaciones) |
E4 |
Exenta por arts. 23 y 24 (zonas y regímenes francos / suspensivos) |
E5 |
Exenta por art. 25 (entregas intracomunitarias) |
E6 |
Exenta — otras causas |
FacturaSimplificada flag
| Code |
Meaning |
S |
Factura simplificada (ticket; Destinatarios normally omitted) |
N |
Factura ordinaria/completa (Destinatarios identified) |
TipoHuella (hash algorithm of the chaining/footprint)
Calculation rules
- CuotaImpuesto (per VAT line) =
BaseImponible × TipoImpositivo ÷ 100, rounded to 2 decimals. Example: 1000.00 × 21.00% = 210.00.
- ImporteTotalFactura = sum over all VAT lines of (
BaseImponible + CuotaImpuesto), plus any non-subject/exempt amounts and surcharge/RecargoEquivalencia, rounded to 2 decimals. With one line: 1000.00 + 210.00 = 1210.00.
- Line ImporteTotal =
Cantidad × ImporteUnitario (line totals are the detail amounts; the legal VAT figures live in DetalleIVA).
- Amounts in EUR with a dot decimal separator and 2 decimals;
TipoImpositivo uses 2 decimals (21.00, 10.00, 4.00, 0.00).
- HuellaTBai / encadenamiento: each invoice references the immediately previous TicketBAI invoice of the same issuer in
EncadenamientoFacturaAnterior (SerieFacturaAnterior, NumFacturaAnterior, FechaExpedicionFacturaAnterior, and SignatureValueFirmaFacturaAnterior = the first characters of the previous invoice's XAdES SignatureValue). The first invoice of a chain omits EncadenamientoFacturaAnterior entirely. After XAdES-signing, the HuellaTBai (SHA-256, TipoHuella 01) and the TBAI identifier + QR are computed from this signed document; recompute, never copy.
Worked example (end-to-end)
Input — issued invoice (Bizkaia issuer, first invoice in chain)
Issuer: COMERCIAL BILBAO SL — NIF A12345678 (Bizkaia)
Customer: CLIENTE EJEMPLO SL — NIF B87654321
Invoice: serie TBAI / number 0001, issued 12-06-2026 at 10:15:00
Line: "Servicio de consultoría", qty 1, unit 1000.00, total 1000.00
VAT: 21% on base 1000.00 → cuota 210.00
Invoice total: 1210.00
Chaining: none (this is the first invoice)
Output — TicketBAI XML (unsigned business payload)
<?xml version="1.0" encoding="UTF-8"?>
<T:TicketBai xmlns:T="urn:ticketbai:emision">
<Cabecera>
<IDVersionTBai>1.2</IDVersionTBai>
</Cabecera>
<Sujetos>
<Emisor>
<NIF>A12345678</NIF>
<ApellidosNombreRazonSocial>COMERCIAL BILBAO SL</ApellidosNombreRazonSocial>
</Emisor>
<Destinatarios>
<IDDestinatario>
<NIF>B87654321</NIF>
<ApellidosNombreRazonSocial>CLIENTE EJEMPLO SL</ApellidosNombreRazonSocial>
</IDDestinatario>
</Destinatarios>
</Sujetos>
<Factura>
<CabeceraFactura>
<SerieFactura>TBAI</SerieFactura>
<NumFactura>0001</NumFactura>
<FechaExpedicionFactura>12-06-2026</FechaExpedicionFactura>
<HoraExpedicionFactura>10:15:00</HoraExpedicionFactura>
<FacturaSimplificada>N</FacturaSimplificada>
</CabeceraFactura>
<DatosFactura>
<DescripcionFactura>Servicios de consultoria junio 2026</DescripcionFactura>
<DetallesFactura>
<IDDetalleFactura>
<DescripcionDetalle>Servicio de consultoria</DescripcionDetalle>
<Cantidad>1.00</Cantidad>
<ImporteUnitario>1000.00</ImporteUnitario>
<ImporteTotal>1000.00</ImporteTotal>
</IDDetalleFactura>
</DetallesFactura>
<ImporteTotalFactura>1210.00</ImporteTotalFactura>
<Claves>
<IDClave>
<ClaveRegimenIvaOpTrascendencia>01</ClaveRegimenIvaOpTrascendencia>
</IDClave>
</Claves>
</DatosFactura>
<TipoDesglose>
<DesgloseFactura>
<Sujeta>
<NoExenta>
<DetalleNoExenta>
<TipoNoExenta>S1</TipoNoExenta>
<DesgloseIVA>
<DetalleIVA>
<TipoImpositivo>21.00</TipoImpositivo>
<BaseImponible>1000.00</BaseImponible>
<CuotaImpuesto>210.00</CuotaImpuesto>
</DetalleIVA>
</DesgloseIVA>
</DetalleNoExenta>
</NoExenta>
</Sujeta>
</DesgloseFactura>
</TipoDesglose>
</Factura>
<HuellaTBai>
<!-- First invoice in the chain: EncadenamientoFacturaAnterior is omitted -->
<Software>
<LicenciaTBAI>TBAILIC-0001</LicenciaTBAI>
<EntidadDesarrolladora>
<NIF>B99999999</NIF>
</EntidadDesarrolladora>
<Nombre>FinchContext Facturacion & TBAI</Nombre>
<Version>1.0</Version>
</Software>
<NumSerieDispositivo>DISPO-0001</NumSerieDispositivo>
</HuellaTBai>
<!--
XAdES enveloped <ds:Signature> (xmlns:ds="http://www.w3.org/2000/09/xmldsig#")
is appended here as the last child of T:TicketBai.
The HuellaTBai (SHA-256), the TBAI identifier (TBAI-A12345678-120626-...-NNN)
and the QR code are derived from this signed document AFTER signing.
-->
</T:TicketBai>
Normalisation shown: date 2026-06-12 → 12-06-2026; time → 10:15:00; rate 21% → 21.00; base 1000.00 × 21.00% → cuota 210.00; total 1000.00 + 210.00 → 1210.00; literal & in the software name escaped as &. On the second invoice of this chain, add an EncadenamientoFacturaAnterior block inside HuellaTBai referencing serie TBAI, número 0001, fecha 12-06-2026 and the leading characters of this invoice's signed SignatureValue.
Validation checklist
Last updated: 2026-06-12 — verify the active TicketBAI schema version and the specific Diputación Foral (Bizkaia/Gipuzkoa/Araba) requirements against the current specification before use.