Salta al contingut
Log in

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.

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:

Finestra del terminal
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"
}
}'

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:

Finestra del terminal
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.

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.

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:

Finestra del terminal
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%:

Finestra del terminal
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 price i tax_inclusive_amount negatius.
  • 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.

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.

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.

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_idSujetos > Emisor > NIF
supplier_party_nameSujetos > Emisor > ApellidosNombreRazonSocial
customer_party_tax_id (si customer_party_tax_scheme és nil)Sujetos > Destinatarios > IDDestinatario > NIF
customer_party_countrySujetos > Destinatarios > IDDestinatario > IDOtro > CodigoPais
customer_party_tax_schemeSujetos > Destinatarios > IDDestinatario > IDOtro > IDType
customer_party_tax_id (si customer_party_tax_scheme és present)Sujetos > Destinatarios > IDDestinatario > IDOtro > ID
customer_party_nameSujetos > Destinatarios > IDDestinatario > ApellidosNombreRazonSocial
customer_party_postalcodeSujetos > Destinatarios > IDDestinatario > CodigoPostal
customer_party_addressSujetos > Destinatarios > IDDestinatario > Direccion
invoice_series_codeFactura > CabeceraFactura > SerieFactura
invoice_numberFactura > CabeceraFactura > NumFactura
invoice_dateFactura > CabeceraFactura > FechaExpedicionFactura
ticketFactura > CabeceraFactura > FacturaSimplificada
is_amendFactura > CabeceraFactura > FacturaRectificativa
invoice_type_code (si is_amend)Factura > CabeceraFactura > FacturaRectificativa > Codigo
amended_series_codeFactura > CabeceraFactura > FacturasRectificadasSustituidas > IDFacturaRectificadaSustituida > SerieFactura
amended_numberFactura > CabeceraFactura > FacturasRectificadasSustituidas > IDFacturaRectificadaSustituida > NumFactura
amended_dateFactura > CabeceraFactura > FacturasRectificadasSustituidas > IDFacturaRectificadaSustituida > FechaExpedicionFactura
tax_point_dateFactura > DatosFactura > FechaOperacion
descriptionFactura > DatosFactura > DescripcionFactura
tax_report_lines[].descriptionFactura > DatosFactura > DetallesFactura > IDDetalleFactura > DescripcionDetalle
tax_report_lines[].quantityFactura > DatosFactura > DetallesFactura > IDDetalleFactura > Cantidad
tax_report_lines[].priceFactura > DatosFactura > DetallesFactura > IDDetalleFactura > ImporteUnitario
tax_report_lines[].tax_inclusive_amountFactura > DatosFactura > DetallesFactura > IDDetalleFactura > ImporteTotal
tax_inclusive_amountFactura > DatosFactura > ImporteTotalFactura
tax_amount_withheldFactura > DatosFactura > RetencionSoportada
special_regime_keyFactura > DatosFactura > Claves > IDClave > ClaveRegimenIvaOpTrascendencia
tax_breakdowns[].taxable_base (no exempta)Factura > TipoDesglose > DesgloseFactura > Sujeta > NoExenta > DetalleNoExenta > DesgloseIVA > DetalleIVA > BaseImponible
tax_breakdowns[].percentFactura > TipoDesglose > DesgloseFactura > Sujeta > NoExenta > DetalleNoExenta > DesgloseIVA > DetalleIVA > TipoImpositivo
tax_breakdowns[].tax_amountFactura > TipoDesglose > DesgloseFactura > Sujeta > NoExenta > DetalleNoExenta > DesgloseIVA > DetalleIVA > CuotaImpuesto

Esquemes TicketBAI proporcionats per les hisendes forals basques.

Fitxer XSDDescripció
ticketbaiv1-2-2.xsdEsquema principal de TicketBAI
anula_ticketbaiv1-2-2.xsdEsquema per al subministrament de factures

Descripcions de codis per a camps específics

Section titled “Descripcions de codis per a camps específics”

Paràmetre: invoice_type_code

CodiDescripció
F1Factura (art. 6, 7.2 i 7.3 del RD 1619/2012)
F2Factura simplificada i factures sense identificació del destinatari (art. 6.1.d) RD 1619/2012
F3Factura emesa en substitució de factures simplificades facturades i declarades
R1Factura rectificativa (error fonamentat en dret i art. 80 u, dos i sis LIVA)
R2Factura rectificativa (art. 80.3)
R3Factura rectificativa (art. 80.4)
R4Factura rectificativa (resta de casos)
R5Factura rectificativa en factures simplificades

Paràmetre: special_regime_key

CodiDescripció
01Operació de règim general.
02Exportació.
03Operacions a les quals s’aplica el règim especial de béns usats, objectes d’art, antiguitats i objectes de col·lecció.
04Règim especial de l’or d’inversió.
05Règim especial de les agències de viatges.
06Règim especial de grup d’entitats en IVA (nivell avançat)
07Règim especial del criteri de caixa.
08Operacions subjectes a l’IPSI / IGIC.
51Operacions en recàrrec d’equivalència.
52Operacions en règim simplificat.

Paràmetre: non_exemption_code

CodiDescripció
S1Operació subjecta i no exempta, sense inversió del subjecte passiu.
S2Operació subjecta i no exempta, amb inversió del subjecte passiu.

Paràmetre: exemption_code

CodiDescripció
E1Exempta per l’article 20
E2Exempta per l’article 21
E3Exempta per l’article 22
E4Exempta pels articles 23 i 24
E5Exempta per l’article 25
E6Exempta per altres motius

Paràmetre: no_subject_code

CodiDescripció
OTNo subjecte per l’article 7 de la Norma Foral de l’IVA. Altres supòsits de no subjecció.
RLNo subjecte per regles de localització.
VTNo subjecte, vendes realitzades per compte de tercers.
IENo subjecte al TAI per regles de localització, però repercuteix impost estranger.

Paràmetre: customer_party_tax_scheme

CodiDescripció
02EU VAT ID (NIF-IVA)
03Passaport
04Identificador oficial emès pel país de residència
05Certificat de residència
06Altre document acreditatiu