TicketBAI
La Llei antifrau (Llei 11/2021) i el seu desenvolupament tècnic posterior, el Reial decret 1007/2023, estableixen que les empreses han d’assegurar que els seus sistemes de facturació i comptabilitat compleixin uns estàndards tècnics estrictes per evitar la manipulació de dades. Per a les empreses ubicades a Euskadi, la Llei antifrau imposa l’ús de TicketBAI. La REST API TicketBAI de B2Brouter és una solució tècnica que permet que la teva empresa sigui fàcilment 100% compliant, delegant la complexitat a B2Brouter i centrant-te en la lògica de negoci del teu sistema.
B2Brouter proporciona una API convenient per enviar declaracions fiscals TicketBAI, de manera que puguis complir fàcilment la legislació de les tres hisendes forals basques (Araba, Bizkaia i Gipuzkoa). La nostra API amaga les diferències entre elles i t’ofereix una interfície unificada totalment compatible amb les tres administracions tributàries. Pots comprovar l’estat de B2Brouter com a “software garante” a les tres hisendes: Araba, Bizkaia, Gipuzkoa.
Què és TicketBAI?
Section titled “Què és TicketBAI?”TicketBAI és un projecte conjunt de les diputacions forals basques (Gipuzkoa, Bizkaia i Araba) i del Govern Basc per controlar la facturació i garantir el compliment fiscal. Exigeix que tots els autònoms i empreses utilitzin programari de facturació certificat que generi un codi únic i un codi QR per a cada factura. Aquest sistema pretén prevenir el frau fiscal assegurant que totes les transaccions econòmiques quedin registrades i es transmetin a l’administració tributària en temps real o gairebé real.
TicketBAI implica:
- Generar un identificador TicketBAI únic, un codi QR per a cada factura i una declaració fiscal que inclogui la informació rellevant de la factura.
- Signar digitalment cada declaració fiscal amb un certificat electrònic qualificat.
- Encadenar criptogràficament les declaracions fiscals per garantir-ne la immutabilitat i evitar manipulacions.
- Enviar la declaració fiscal a l’hisenda foral corresponent en el format establert i dins del termini requerit.
- Processar les respostes de l’administració tributària per a cada enviament.
Amb B2Brouter, pots abstraure bona part de la complexitat d’aquest procés i complir la Llei antifrau fent només unes poques crides REST a l’API. No et caldrà tenir el teu propi certificat electrònic qualificat perquè B2Brouter és col·laborador social en la gestió tributària. Només necessites una API Key vàlida de B2Brouter.
B2Brouter ofereix dues modalitats de funcionament segons si utilitzes B2Brouter tant per emetre factures com per informar-ne a l’administració tributària, o només per a la declaració fiscal.
Entorns de proves: Fes servir el sandbox per a les primeres proves d’API i validació de payloads; el sandbox simula els enviaments TicketBAI perquè puguis provar el cicle de vida de la factura sense connectar amb l’administració tributària basca. Per fer proves completes end-to-end amb l’endpoint de proves de l’administració, fes servir l’entorn de staging (
api-staging.b2brouter.net).
Configurar i treballar amb l’API de B2Brouter
Section titled “Configurar i treballar amb l’API de B2Brouter”El primer pas és configurar TicketBAI per a cadascuna de les empreses per a les quals vulguis enviar declaracions fiscals. Pots consultar la guia de Tax Report Settings per a una descripció completa del procés. La crida per configurar un compte és la següent:
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": "tbai", "enabled": true, "start_date": "2025-04-06", "auto_generate": true, "auto_send": true, "reason_vat_exempt": "E1", "special_regime_key": "01", "reason_no_subject": "OT", "credit_note_code": "R1", "delegation": "gipuzkoa", "type_operation": "services" } }'Invoice API
Section titled “Invoice API”Si utilitzes B2Brouter tant per emetre factures com per informar-ne a l’administració tributària, un cop hagis configurat correctament el compte, podràs operar com faries habitualment per emetre factures.
Les factures emeses inclouran el codi QR obligatori, i la declaració fiscal TicketBAI s’enviarà automàticament a l’administració tributària corresponent. Aquest és un exemple d’una crida per crear i emetre una factura:
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": "Ejemplo S.L.", "address": "Calle Falsa 123, 3ºA", "city": "Madrid", "province": "Madrid", "postalcode": "28001", "country": "es", "email": "john.doe@example.com", "language": "es", "currency": "EUR", "terms": "15", "payment_method": 1, "tin_scheme": 9920, "tin_value": "ESB12345678" }, "invoice_lines_attributes": [ { "quantity": 10.0, "description": "Servicio de Ejemplo", "price": 11.0, "unit": 9, "taxes_attributes": [ { "name": "IVA", "percent": 21.0, "category": "S" } ] } ] } }'A la resposta de la crida REST POST per crear una factura, si send_after_import està a true, trobaràs una secció tax_report_ids on veuràs l’identificador de la declaració fiscal associada a la factura. Tingues en compte que tax_report_ids és un array perquè cada factura pot tenir més d’una declaració fiscal en casos d’anul·lacions i correccions.
Pots accedir a la declaració fiscal completa, incloent-hi el codi QR, el seu identificador, l’estat i la resta de camps, cridant el endpoint d’obtenció de tax report amb el tax report ID retornat a la resposta de la creació de factura.
L’estat de la declaració fiscal sempre serà processing a la resposta del POST perquè el procés en segon pla que encadena i envia la declaració es fa de manera independent. Per aquest motiu has de comprovar el cicle de vida de la declaració fiscal. Tens dues opcions:
-
La manera recomanada és utilitzar el webhook de tax report. El webhook farà una crida POST al teu sistema cada vegada que l’estat de la declaració fiscal arribi a un estat final: registered, error i registered_with_errors.
-
Fer polling de l’estat de la declaració fiscal amb el endpoint d’obtenció de tax report fins que el camp state sigui registered, error o registered_with_errors.
Tax Report API per a TicketBAI
Section titled “Tax Report API per a TicketBAI”Si no utilitzes B2Brouter per emetre factures, necessites més control sobre el procés de generació i tractament de declaracions fiscals, o esperes un volum alt de declaracions, pots utilitzar la Tax Report API.
L’estructura del format JSON de les declaracions fiscals de B2Brouter es basa en PEPPOL Continuous Transaction Control (CTC). La Tax Report API de B2Brouter és una API universal no només orientada a TicketBAI, sinó dissenyada per gestionar tax reporting arreu del món.
És important remarcar que, per a TicketBAI, les declaracions fiscals tenen tax report lines que representen les línies individuals de la factura original. El model TaxReport no fa càlculs. Has de proporcionar totes les xifres rellevants a la declaració fiscal.
Crear una declaració fiscal
Section titled “Crear una declaració fiscal”Per crear una declaració fiscal has de cridar l’endpoint create tax report. Es pot crear una declaració fiscal mínima i vàlida amb la següent crida POST:
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": "TicketBai", "invoice_date": "2025-04-03", "invoice_number": "11", "description": "Consulting service", "customer_party_tax_id": "B12345678", "customer_party_country": "es", "customer_party_postalcode": "28001", "customer_party_address": "Calle Falsa 123, 3ºA", "customer_party_name": "Ejemplo S.L.", "tax_inclusive_amount": 121.0, "tax_amount": 21.0, "invoice_type_code": "F1", "currency": "EUR", "tax_report_lines": [ { "quantity": 1.0, "description": "Service", "price": 100.0, "tax_inclusive_amount": 121.0, "tax_exclusive_amount": 100.0, "tax_amount": 21.0 } ], "tax_breakdowns": [ { "category": "S", "non_exempt": true, "non_exemption_code": "S1", "percent": 21, "taxable_base": 100.0, "tax_amount": 21.0 } ] } }'La resposta a aquesta crida POST es retornarà immediatament amb la declaració fiscal en estat processing. Els camps qr i identifier seran inicialment null. Per recuperar-los, fes crides GET successives fins que l’estat canviï a signed o registered.
El següent és un exemple més complex d’un TicketBAI amb dues línies, un descompte global, IVA del 21% i IRPF del 15%:
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": "TicketBai", "invoice_date": "2025-08-13", "invoice_number": "2025-128", "description": "Invoice with multiple lines, global discount, IVA, and IRPF (tax withheld)", "customer_party_tax_id": "B12345678", "customer_party_country": "es", "customer_party_postalcode": "28001", "customer_party_address": "Calle Falsa 123, 3ºA", "customer_party_name": "Ejemplo S.L.", "tax_inclusive_amount": 217.8, "tax_amount": 37.8, "tax_amount_withheld": 27, "invoice_type_code": "F1", "currency": "EUR", "tax_report_lines": [ { "quantity": 1, "description": "Product A", "price": 100, "tax_inclusive_amount": 121, "tax_exclusive_amount": 100, "tax_amount": 21 }, { "quantity": 2, "description": "Product B", "price": 50, "tax_inclusive_amount": 121, "tax_exclusive_amount": 100, "tax_amount": 21 }, { "quantity": 1, "description": "Global Discount 10%", "price": -20, "tax_inclusive_amount": -24.2, "tax_exclusive_amount": -20, "tax_amount": -4.2 } ], "tax_breakdowns": [ { "category": "S", "non_exempt": true, "non_exemption_code": "S1", "percent": 21, "taxable_base": 180, "tax_amount": 37.8 } ] } }'Punts clau a tenir en compte:
- Càlcul d’impostos per línia: TicketBAI requereix que tots els impostos es calculin línia per línia.
- Descomptes i recàrrecs globals com a línies: Els descomptes globals s’han de tractar com a línies separades amb
priceitax_inclusive_amountnegatius. - Impostos retinguts: Els impostos retinguts (per exemple, IRPF) s’informen a nivell de document amb el camp
tax_amount_withheld.
Comprovar l’estat d’una declaració fiscal
Section titled “Comprovar l’estat d’una declaració fiscal”Has de comprovar el cicle de vida de la declaració fiscal. Tens dues opcions:
-
La manera recomanada és utilitzar el webhook de tax report. Els estats finals són: registered, error, annulled i registered_with_errors.
-
Fer polling de l’estat de la declaració fiscal cridant el endpoint d’obtenció de tax report fins que el camp state sigui un de: registered, error, annulled i registered_with_errors.
Obtenir la representació XML de la declaració fiscal
Section titled “Obtenir la representació XML de la declaració fiscal”Si necessites la representació XML de la declaració fiscal, utilitza el endpoint de descàrrega de tax report. B2Brouter també inclou un camp anomenat xml_base64 a la resposta del GET. Tingues en compte que l’XML només es pot generar després que la declaració fiscal hagi estat encadenada, que és un procés asíncron.
Comprovació d’errors
Section titled “Comprovació d’errors”B2Brouter ha implementat un conjunt exhaustiu de validacions de les declaracions fiscals TicketBAI basades en les especificacions publicades per les hisendes forals basques. Si hi ha un error de validació, la declaració fiscal no es crearà. Rebràs una resposta 422: Unprocessable Entity amb tots els errors en format JSON.
Anul·lar una declaració fiscal
Section titled “Anul·lar una declaració fiscal”Per anul·lar una declaració fiscal utilitza el verb DELETE cridant l’endpoint d’anul·lació. Comprova l’evolució de l’anul·lació processant el webhook de tax report o fent polling de l’endpoint d’obtenció de tax report fins que el camp state de la declaració fiscal sigui error o annulled.
Llistar declaracions fiscals
Section titled “Llistar declaracions fiscals”Per llistar les teves declaracions fiscals, utilitza el verb GET a l’endpoint de llistar tax reports.
Equivalència entre els camps interns de tax report de B2Brouter i els nodes XML TicketBAI
Section titled “Equivalència entre els camps interns de tax report de B2Brouter i els nodes XML TicketBAI”| Camp de B2Brouter (basat en PEPPOL CTC) | Node XML TicketBAI |
|---|---|
supplier_party_tax_id | Sujetos > Emisor > NIF |
supplier_party_name | Sujetos > Emisor > ApellidosNombreRazonSocial |
customer_party_tax_id (si customer_party_tax_scheme és nil) | Sujetos > Destinatarios > IDDestinatario > NIF |
customer_party_country | Sujetos > Destinatarios > IDDestinatario > IDOtro > CodigoPais |
customer_party_tax_scheme | Sujetos > Destinatarios > IDDestinatario > IDOtro > IDType |
customer_party_tax_id (si customer_party_tax_scheme és present) | Sujetos > Destinatarios > IDDestinatario > IDOtro > ID |
customer_party_name | Sujetos > Destinatarios > IDDestinatario > ApellidosNombreRazonSocial |
customer_party_postalcode | Sujetos > Destinatarios > IDDestinatario > CodigoPostal |
customer_party_address | Sujetos > Destinatarios > IDDestinatario > Direccion |
invoice_series_code | Factura > CabeceraFactura > SerieFactura |
invoice_number | Factura > CabeceraFactura > NumFactura |
invoice_date | Factura > CabeceraFactura > FechaExpedicionFactura |
ticket | Factura > CabeceraFactura > FacturaSimplificada |
is_amend | Factura > CabeceraFactura > FacturaRectificativa |
invoice_type_code (si is_amend) | Factura > CabeceraFactura > FacturaRectificativa > Codigo |
amended_series_code | Factura > CabeceraFactura > FacturasRectificadasSustituidas > IDFacturaRectificadaSustituida > SerieFactura |
amended_number | Factura > CabeceraFactura > FacturasRectificadasSustituidas > IDFacturaRectificadaSustituida > NumFactura |
amended_date | Factura > CabeceraFactura > FacturasRectificadasSustituidas > IDFacturaRectificadaSustituida > FechaExpedicionFactura |
tax_point_date | Factura > DatosFactura > FechaOperacion |
description | Factura > DatosFactura > DescripcionFactura |
tax_report_lines[].description | Factura > DatosFactura > DetallesFactura > IDDetalleFactura > DescripcionDetalle |
tax_report_lines[].quantity | Factura > DatosFactura > DetallesFactura > IDDetalleFactura > Cantidad |
tax_report_lines[].price | Factura > DatosFactura > DetallesFactura > IDDetalleFactura > ImporteUnitario |
tax_report_lines[].tax_inclusive_amount | Factura > DatosFactura > DetallesFactura > IDDetalleFactura > ImporteTotal |
tax_inclusive_amount | Factura > DatosFactura > ImporteTotalFactura |
tax_amount_withheld | Factura > DatosFactura > RetencionSoportada |
special_regime_key | Factura > DatosFactura > Claves > IDClave > ClaveRegimenIvaOpTrascendencia |
tax_breakdowns[].taxable_base (no exempta) | Factura > TipoDesglose > DesgloseFactura > Sujeta > NoExenta > DetalleNoExenta > DesgloseIVA > DetalleIVA > BaseImponible |
tax_breakdowns[].percent | Factura > TipoDesglose > DesgloseFactura > Sujeta > NoExenta > DetalleNoExenta > DesgloseIVA > DetalleIVA > TipoImpositivo |
tax_breakdowns[].tax_amount | Factura > TipoDesglose > DesgloseFactura > Sujeta > NoExenta > DetalleNoExenta > DesgloseIVA > DetalleIVA > CuotaImpuesto |
Fitxers XSD
Section titled “Fitxers XSD”Esquemes TicketBAI proporcionats per les hisendes forals basques.
| Fitxer XSD | Descripció |
|---|---|
| ticketbaiv1-2-2.xsd | Esquema principal de TicketBAI |
| anula_ticketbaiv1-2-2.xsd | Esquema per al subministrament de factures |
Descripcions de codis per a camps específics
Section titled “Descripcions de codis per a camps específics”Codis de tipus de factura
Section titled “Codis de tipus de factura”Paràmetre: invoice_type_code
| Codi | Descripció |
|---|---|
| F1 | Factura (art. 6, 7.2 i 7.3 del RD 1619/2012) |
| F2 | Factura simplificada i factures sense identificació del destinatari (art. 6.1.d) RD 1619/2012 |
| F3 | Factura emesa en substitució de factures simplificades facturades i declarades |
| R1 | Factura rectificativa (error fonamentat en dret i art. 80 u, dos i sis LIVA) |
| R2 | Factura rectificativa (art. 80.3) |
| R3 | Factura rectificativa (art. 80.4) |
| R4 | Factura rectificativa (resta de casos) |
| R5 | Factura rectificativa en factures simplificades |
Codis de clau de règim especial
Section titled “Codis de clau de règim especial”Paràmetre: special_regime_key
| Codi | Descripció |
|---|---|
| 01 | Operació de règim general. |
| 02 | Exportació. |
| 03 | Operacions a les quals s’aplica el règim especial de béns usats, objectes d’art, antiguitats i objectes de col·lecció. |
| 04 | Règim especial de l’or d’inversió. |
| 05 | Règim especial de les agències de viatges. |
| 06 | Règim especial de grup d’entitats en IVA (nivell avançat) |
| 07 | Règim especial del criteri de caixa. |
| 08 | Operacions subjectes a l’IPSI / IGIC. |
| 51 | Operacions en recàrrec d’equivalència. |
| 52 | Operacions en règim simplificat. |
Codis de no exempció
Section titled “Codis de no exempció”Paràmetre: non_exemption_code
| Codi | Descripció |
|---|---|
| S1 | Operació subjecta i no exempta, sense inversió del subjecte passiu. |
| S2 | Operació subjecta i no exempta, amb inversió del subjecte passiu. |
Codis d’exempció
Section titled “Codis d’exempció”Paràmetre: exemption_code
| Codi | Descripció |
|---|---|
| E1 | Exempta per l’article 20 |
| E2 | Exempta per l’article 21 |
| E3 | Exempta per l’article 22 |
| E4 | Exempta pels articles 23 i 24 |
| E5 | Exempta per l’article 25 |
| E6 | Exempta per altres motius |
Codis de no subjecció
Section titled “Codis de no subjecció”Paràmetre: no_subject_code
| Codi | Descripció |
|---|---|
| OT | No subjecte per l’article 7 de la Norma Foral de l’IVA. Altres supòsits de no subjecció. |
| RL | No subjecte per regles de localització. |
| VT | No subjecte, vendes realitzades per compte de tercers. |
| IE | No subjecte al TAI per regles de localització, però repercuteix impost estranger. |
Tipus d’identificador del client
Section titled “Tipus d’identificador del client”Paràmetre: customer_party_tax_scheme
| Codi | Descripció |
|---|---|
| 02 | EU VAT ID (NIF-IVA) |
| 03 | Passaport |
| 04 | Identificador oficial emès pel país de residència |
| 05 | Certificat de residència |
| 06 | Altre document acreditatiu |