Skip to content
Log in

TicketBAI

La loi anti-fraude (loi 11/2021) et sa réglementation technique ultérieure décret royal 1007/2023 imposent aux entreprises de garantir que leurs systèmes de facturation et de comptabilité respectent des normes techniques strictes afin d’empêcher la manipulation des données. Pour les entreprises situées en Euskadi, la loi anti-fraude impose l’utilisation de TicketBAI. L’API REST TicketBAI de B2Brouter est une solution technique qui permet à votre entreprise d’être facilement conforme à 100 %, en confiant la complexité à B2Brouter et en vous concentrant sur la logique métier de votre système.

B2Brouter fournit une API pratique pour soumettre les déclarations fiscales TicketBAI afin que vous puissiez vous conformer facilement à la législation des trois administrations fiscales basques (Araba, Bizkaia et Gipuzkoa). Notre API masque les différences entre elles et vous offre une interface unifiée totalement conforme aux trois administrations fiscales. Vous pouvez consulter le statut de B2Brouter en tant que « software garante » auprès des trois administrations fiscales : Araba, Bizkaia, Gipuzkoa.

TicketBAI est un projet commun des conseils provinciaux basques (Gipuzkoa, Bizkaia et Araba) et du gouvernement basque destiné à contrôler la facturation et à garantir la conformité fiscale. Il impose à tous les travailleurs indépendants et aux entreprises d’utiliser un logiciel de facturation certifié qui génère un code unique et un code QR pour chaque facture. Ce système vise à prévenir la fraude fiscale en garantissant que toutes les transactions économiques sont enregistrées et transmises à l’administration fiscale en temps réel ou quasi réel.

TicketBAI implique :

  • la génération d’un identifiant TicketBAI unique, d’un code QR pour chaque facture et d’une déclaration fiscale contenant les informations pertinentes de la facture ;
  • la signature numérique de chaque déclaration fiscale au moyen d’un certificat électronique qualifié ;
  • l’enchaînement cryptographique des déclarations fiscales afin de garantir leur immutabilité et d’empêcher toute altération ;
  • l’envoi de la déclaration fiscale à l’administration fiscale basque compétente (Hacienda Foral) dans un format déterminé et dans les délais ;
  • le traitement des réponses de l’administration fiscale pour chaque envoi.

Avec B2Brouter, vous pouvez abstraire une grande partie de la complexité de ce processus et vous conformer à la loi anti-fraude en n’émettant que quelques appels REST à l’API. Vous n’aurez pas besoin de votre propre certificat électronique qualifié, car B2Brouter est un collaborateur social dans la gestion fiscale. Vous avez simplement besoin d’une clé API B2Brouter valide.

B2Brouter fournit deux modes de fonctionnement selon que vous utilisez B2Brouter à la fois pour émettre les factures et pour les déclarer à l’administration fiscale, ou uniquement pour la déclaration fiscale.

Environnements de test : utilisez le sandbox pour les premiers tests API et la validation des payloads. Le sandbox simule les soumissions TicketBAI afin que vous puissiez tester le cycle de vie complet d’une facture sans contacter l’administration fiscale basque. Pour des tests de bout en bout avec le point de terminaison de test de l’administration, utilisez l’environnement de staging (api-staging.b2brouter.net).

La première étape consiste à configurer TicketBAI pour chacune des entreprises pour lesquelles vous souhaitez soumettre des déclarations fiscales. Vous pouvez consulter le guide des paramètres de déclaration fiscale pour une description complète du processus. L’appel pour configurer un compte est le suivant :

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": "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 vous utilisez B2Brouter à la fois pour émettre des factures et pour les déclarer à l’administration fiscale, une fois votre compte correctement configuré, vous pouvez travailler comme d’habitude pour l’émission de factures.

Les factures émises contiendront le code QR obligatoire, et la déclaration fiscale TicketBAI sera envoyée automatiquement à l’administration fiscale compétente. Voici un exemple d’appel permettant de créer et d’émettre une facture :

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": "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"
}
]
}
]
}
}'

Dans la réponse de l’appel REST POST de création d’une facture, si send_after_import est défini sur true, vous trouverez une section tax_report_ids dans laquelle figure l’identifiant de la déclaration fiscale associée à la facture. Notez que tax_report_ids est un tableau parce qu’une même facture peut avoir plus d’une déclaration fiscale en cas d’annulation ou de correction.

Vous pouvez accéder à la déclaration fiscale complète, y compris le code QR, son identifiant, son état et tous les autres champs, en appelant le point de terminaison d’obtention d’une déclaration fiscale avec l’identifiant de déclaration fiscale fourni dans la réponse à l’appel de création de facture.

L’état de la déclaration fiscale sera toujours processing dans la réponse à l’appel POST, car le processus en arrière-plan qui enchaîne et envoie la déclaration fiscale est exécuté de manière indépendante. C’est pourquoi vous devez vérifier le cycle de vie de la déclaration fiscale. Vous avez deux options :

Si vous n’utilisez pas B2Brouter pour émettre des factures, si vous avez besoin de davantage de contrôle sur le processus de génération et de traitement des déclarations fiscales, ou si vous prévoyez un volume élevé de déclarations, vous pouvez utiliser l’API Tax Report.

La structure du format JSON des déclarations fiscales B2Brouter est basée sur PEPPOL Continuous Transaction Control (CTC). L’API Tax Report de B2Brouter est une API universelle, non seulement orientée TicketBAI mais conçue pour gérer les déclarations fiscales dans le monde entier.

Il est important de noter que, pour TicketBAI, les déclarations fiscales comportent des tax report lines, qui représentent les lignes individuelles de la facture d’origine. Le modèle TaxReport n’effectue aucun calcul. Vous devez fournir toutes les valeurs pertinentes dans la déclaration fiscale.

Pour créer une déclaration fiscale, vous devez appeler le point de terminaison create tax report. Une déclaration fiscale minimale et valide peut être créée avec l’appel POST suivant :

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": "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 réponse à cet appel POST sera renvoyée immédiatement avec la déclaration fiscale dans l’état processing. Les champs qr et identifier seront initialement null. Pour les récupérer, effectuez ensuite des requêtes GET jusqu’à ce que l’état passe à signed ou registered.

L’exemple suivant est plus complexe : un TicketBAI avec deux lignes, une remise globale, une TVA de 21 % et un IRPF de 15 % :

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": "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
}
]
}
}'

Points clés à prendre en compte :

  • Calcul fiscal au niveau ligne : TicketBAI exige que toutes les taxes soient calculées ligne par ligne.
  • Remises et charges globales comme lignes : les remises globales doivent être traitées comme des lignes séparées avec un price négatif et un tax_inclusive_amount négatif.
  • Taxes retenues à la source : les taxes retenues (par ex. IRPF) sont déclarées au niveau du document à l’aide du champ tax_amount_withheld.

Vérifier l’état d’une déclaration fiscale

Section titled “Vérifier l’état d’une déclaration fiscale”

Vous devez vérifier le cycle de vie de la déclaration fiscale. Vous avez deux options :

  • la méthode recommandée consiste à utiliser le webhook de déclaration fiscale. Les états finaux sont : registered, error, annulled et registered_with_errors ;
  • interroger l’état de la déclaration fiscale en appelant le point de terminaison get tax report jusqu’à ce que le champ state soit l’un des suivants : registered, error, annulled et registered_with_errors.

Obtenir la représentation XML de la déclaration fiscale

Section titled “Obtenir la représentation XML de la déclaration fiscale”

Si vous avez besoin de la représentation XML de la déclaration fiscale, utilisez le point de terminaison download tax report. B2Brouter inclut également un champ nommé xml_base64 dans la réponse du GET. Notez que le XML ne peut être généré qu’après l’enchaînement de la déclaration fiscale (processus asynchrone).

B2Brouter a mis en place un ensemble exhaustif de validations des déclarations fiscales TicketBAI basées sur les spécifications publiées par les administrations fiscales basques. En cas d’erreur de validation, la déclaration fiscale ne sera pas créée. Vous recevrez une réponse 422: Unprocessable Entity avec toutes les erreurs au format JSON.

Pour annuler une déclaration fiscale, utilisez le verbe DELETE en appelant le point de terminaison d’annulation. Vérifiez l’évolution de l’annulation soit en traitant le webhook de déclaration fiscale, soit en interrogeant le point de terminaison get tax report jusqu’à ce que le champ state de la déclaration fiscale soit error ou annulled.

Pour lister vos déclarations fiscales, utilisez le verbe GET sur le point de terminaison list tax reports.

Équivalence entre les champs internes de déclaration fiscale B2Brouter et les nœuds XML TicketBAI

Section titled “Équivalence entre les champs internes de déclaration fiscale B2Brouter et les nœuds XML TicketBAI”
Champ B2Brouter (basé sur PEPPOL CTC)Nœud XML TicketBAI
supplier_party_tax_idSujetos > Emisor > NIF
supplier_party_nameSujetos > Emisor > ApellidosNombreRazonSocial
customer_party_tax_id (si customer_party_tax_scheme est 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 est présent)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 (non exonéré)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

Schémas TicketBAI fournis par les administrations fiscales basques.

Fichier XSDDescription
ticketbaiv1-2-2.xsdSchéma principal TicketBAI
anula_ticketbaiv1-2-2.xsdSchéma pour la soumission des annulations

Descriptions de code pour des champs spécifiques

Section titled “Descriptions de code pour des champs spécifiques”

Param : invoice_type_code

CodeDescription
F1Facture (art. 6, 7.2 et 7.3 du RD 1619/2012)
F2Facture simplifiée et factures sans identification du destinataire (art. 6.1.d du RD 1619/2012)
F3Facture émise en substitution de factures simplifiées facturées et déclarées
R1Facture rectificative (erreur fondée en droit et art. 80 un, deux et six LIVA)
R2Facture rectificative (art. 80.3)
R3Facture rectificative (art. 80.4)
R4Facture rectificative (autres cas)
R5Facture rectificative pour des factures simplifiées

Param : special_regime_key

CodeDescription
01Opération relevant du régime général.
02Exportation.
03Opérations soumises au régime spécial des biens d’occasion, objets d’art, antiquités et objets de collection.
04Régime spécial de l’or d’investissement.
05Régime spécial des agences de voyages.
06Régime spécial du groupe d’entités en TVA (niveau avancé)
07Régime spécial du critère de caisse.
08Opérations soumises à l’IPSI / IGIC.
51Opérations sous régime du recargo de equivalencia.
52Opérations sous régime simplifié.

Param : non_exemption_code

CodeDescription
S1Opération soumise et non exonérée - sans autoliquidation.
S2Opération soumise et non exonérée - avec autoliquidation.

Param : exemption_code

CodeDescription
E1Exonérée par l’article 20
E2Exonérée par l’article 21
E3Exonérée par l’article 22
E4Exonérée par les articles 23 et 24
E5Exonérée par l’article 25
E6Exonérée pour d’autres motifs

Param : no_subject_code

CodeDescription
OTNon soumis en vertu de l’article 7 de la norme forale TVA. Autres cas de non-soumission.
RLNon soumis en raison des règles de localisation.
VTNon soumis, ventes réalisées pour le compte de tiers.
IENon soumis dans le TAI selon les règles de localisation, mais avec répercussion d’un impôt étranger.

Param : customer_party_tax_scheme

CodeDescription
02Numéro de TVA intracommunautaire (NIF-IVA)
03Passeport
04Pièce d’identité officielle émise par le pays de résidence
05Certificat de résidence
06Autre document justificatif