Skip to content
Log in

TicketBAI

Das Anti-Betrugsgesetz (Gesetz 11/2021) und die nachfolgende technische Verordnung Königliches Dekret 1007/2023 verpflichten Unternehmen dazu, sicherzustellen, dass ihre Rechnungsstellungs- und Buchhaltungssysteme strenge technische Standards erfüllen, um Datenmanipulation zu verhindern. Für Unternehmen im Baskenland schreibt das spanische Anti-Betrugsgesetz die Nutzung von TicketBAI vor. Die TicketBAI REST API von B2Brouter ist eine technische Lösung, mit der Ihr Unternehmen problemlos 100 % konform sein kann, indem die Komplexität an B2Brouter ausgelagert wird und Sie sich auf die Geschäftslogik Ihres Systems konzentrieren können.

B2Brouter bietet eine komfortable API zur Einreichung von TicketBAI-Steuerberichten, damit Sie die Gesetzgebung der drei baskischen Steuerbehörden (Araba, Bizkaia und Gipuzkoa) problemlos einhalten können. Unsere API abstrahiert die Unterschiede zwischen ihnen und bietet eine einheitliche Schnittstelle, die vollständig mit allen drei Steuerbehörden konform ist. Sie können den Status von B2Brouter als „software garante” bei allen drei Steuerbehörden überprüfen: Araba, Bizkaia, Gipuzkoa.

TicketBAI ist ein gemeinsames Projekt der baskischen Provinzräte (Gipuzkoa, Bizkaia und Araba) und der Baskischen Regierung zur Kontrolle der Rechnungsstellung und zur Sicherstellung der Steuerkonformität. Es verpflichtet alle Selbstständigen und Unternehmen, zertifizierte Rechnungssoftware zu verwenden, die für jede Rechnung einen eindeutigen Code und einen QR-Code erzeugt. Dieses System zielt darauf ab, Steuerbetrug zu verhindern, indem sichergestellt wird, dass alle Wirtschaftstransaktionen in Echtzeit oder nahezu in Echtzeit aufgezeichnet und an die Steuerbehörden übermittelt werden.

TicketBAI umfasst:

  • Die Generierung eines eindeutigen TicketBAI-Bezeichners, eines QR-Codes für jede Rechnung und eines Steuerberichts mit den relevanten Rechnungsinformationen.
  • Die digitale Signierung jedes Steuerberichts mit einem qualifizierten elektronischen Zertifikat.
  • Die kryptografische Verkettung von Steuerberichten, um Unveränderlichkeit zu gewährleisten und Manipulationen zu verhindern.
  • Die Übermittlung des Steuerberichts an die zuständige baskische Steuerbehörde (Hacienda Foral) in einem bestimmten Format und innerhalb der vorgesehenen Fristen.
  • Die Verarbeitung der Antworten der Steuerbehörde für jede Einreichung.

Mit B2Brouter können Sie einen Großteil der Komplexität dieses Prozesses abstrahieren und durch nur wenige REST-Aufrufe an die API die Anti-Betrugsgesetzgebung einhalten. Sie benötigen kein eigenes qualifiziertes elektronisches Zertifikat, da B2Brouter ein Social Collaborator im Steuerbereich ist. Sie benötigen lediglich einen gültigen B2Brouter API-Schlüssel.

B2Brouter bietet zwei Betriebsmodalitäten, je nachdem, ob Sie B2Brouter sowohl für die Rechnungsausstellung als auch für die Meldung an die Steuerbehörde verwenden, oder nur für die Steuerberichterstattung.

Testumgebungen: Verwenden Sie die Sandbox für erste API-Tests und Payload-Validierung — die Sandbox simuliert TicketBAI-Einreichungen, sodass Sie den Rechnungslebenszyklus durchlaufen können, ohne die baskische Steuerbehörde zu kontaktieren. Für vollständige End-to-End-Tests mit dem Test-Endpunkt der Behörde verwenden Sie die Staging-Umgebung (api-staging.b2brouter.net).

Einrichtung und Arbeiten mit der B2Brouter API

Section titled “Einrichtung und Arbeiten mit der B2Brouter API”

Der erste Schritt ist die Konfiguration von TicketBAI für jedes Unternehmen, für das Sie Steuerberichte einreichen möchten. Eine vollständige Beschreibung des Prozesses finden Sie im Leitfaden zu den Steuerberichtseinstellungen. Der Aufruf zur Konfiguration eines Kontos lautet wie folgt:

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

Wenn Sie B2Brouter sowohl für die Rechnungsausstellung als auch für die Meldung an die Steuerbehörde verwenden, können Sie nach der korrekten Konfiguration Ihres Kontos wie gewohnt Rechnungen ausstellen.

Die ausgestellten Rechnungen enthalten den obligatorischen QR-Code, und der TicketBAI-Steuerbericht wird automatisch an die zuständige Steuerbehörde gesendet. Dies ist ein Beispiel für einen Aufruf zum Erstellen und Ausstellen einer Rechnung:

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

In der Antwort des POST-REST-Aufrufs zum Erstellen einer Rechnung finden Sie, wenn send_after_import auf true gesetzt ist, einen Abschnitt tax_report_ids mit der ID des der Rechnung zugeordneten Steuerberichts. Beachten Sie, dass tax_report_ids ein Array ist, da jede Rechnung mehr als einen Steuerbericht für Stornierungen und Korrekturen haben kann.

Sie können auf den vollständigen Steuerbericht — einschließlich QR-Code, Bezeichner, Status und aller anderen Felder — zugreifen, indem Sie den Endpunkt zum Abrufen eines Steuerberichts mit der in der Antwort des Erstellungsaufrufs angegebenen Steuerbericht-ID aufrufen.

Der Status des Steuerberichts ist in der Antwort des POST-Aufrufs immer processing, da der Hintergrundprozess, der den Steuerbericht verkettet und sendet, unabhängig ausgeführt wird. Aus diesem Grund müssen Sie den Lebenszyklus des Steuerberichts überwachen. Sie haben zwei Möglichkeiten:

  • Die empfohlene Methode ist die Verwendung des Steuerbericht-Webhooks. Der Webhook sendet einen POST-Aufruf an Ihr System, sobald der Status des Steuerberichts einen finalen Status erreicht: registered, error und registered_with_errors.

  • Abfrage des Steuerberichtstatus über den Endpunkt zum Abrufen eines Steuerberichts, bis das Feld state den Wert registered, error oder registered_with_errors hat.

Wenn Sie B2Brouter nicht für die Rechnungsausstellung verwenden, mehr Kontrolle über den Prozess der Generierung und Verarbeitung von Steuerberichten benötigen oder ein hohes Volumen an Steuerberichten erwarten, können Sie die Steuerbericht-API verwenden.

Die Struktur des JSON-Formats für B2Brouter-Steuerberichte basiert auf PEPPOL Continuous Transaction Control (CTC). Die B2Brouter Steuerbericht-API ist eine universelle API, die nicht nur für TicketBAI konzipiert ist, sondern für die Steuerberichterstattung weltweit.

Es ist wichtig zu beachten, dass Steuerberichte für TicketBAI Steuerberichtspositionen haben, die die einzelnen Zeilen der ursprünglichen Rechnung repräsentieren. Das TaxReport-Modell führt keine Berechnungen durch. Sie müssen alle relevanten Beträge im Steuerbericht angeben.

Um einen Steuerbericht zu erstellen, müssen Sie den Endpunkt Steuerbericht erstellen aufrufen. Ein minimaler und gültiger Steuerbericht kann mit dem folgenden POST-Aufruf erstellt werden:

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

Die Antwort auf diesen POST-Aufruf wird sofort mit dem Steuerbericht im Status processing zurückgegeben. Die Felder qr und identifier sind zunächst null. Um sie abzurufen, führen Sie weitere GET-Anfragen durch, bis sich der state auf signed oder registered ändert.

Das folgende Beispiel zeigt einen komplexeren TicketBAI mit zwei Positionen, einem globalen Rabatt, 21 % IVA und 15 % IRPF:

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

Wichtige Punkte:

  • Steuerberechnung auf Positionsebene: TicketBAI erfordert, dass alle Steuern auf Basis jeder einzelnen Position berechnet werden.
  • Globale Rabatte und Zuschläge als Positionen: Globale Rabatte müssen als separate Positionen mit negativem price und tax_inclusive_amount behandelt werden.
  • Einbehaltene Steuern: Einbehaltene Steuern (z. B. IRPF) werden auf Dokumentebene über das Feld tax_amount_withheld ausgewiesen.

Sie müssen den Lebenszyklus des Steuerberichts überwachen. Sie haben zwei Möglichkeiten:

  • Die empfohlene Methode ist die Verwendung des Steuerbericht-Webhooks. Finale Status sind: registered, error, annulled und registered_with_errors.

  • Abfrage des Steuerberichtstatus über den Endpunkt zum Abrufen eines Steuerberichts, bis das Feld state einen der folgenden Werte hat: registered, error, annulled und registered_with_errors.

XML-Darstellung des Steuerberichts abrufen

Section titled “XML-Darstellung des Steuerberichts abrufen”

Wenn Sie die XML-Darstellung des Steuerberichts benötigen, verwenden Sie den Endpunkt zum Herunterladen eines Steuerberichts. B2Brouter enthält in der GET-Antwort auch ein Feld namens xml_base64. Beachten Sie, dass die XML-Datei nur nach der Verkettung des Steuerberichts generiert werden kann (ein asynchroner Prozess).

B2Brouter hat einen umfangreichen Satz an Validierungen von TicketBAI-Steuerberichten implementiert, basierend auf den von den baskischen Steuerbehörden veröffentlichten Spezifikationen. Bei einem Validierungsfehler wird der Steuerbericht nicht erstellt. Sie erhalten eine Antwort 422: Unprocessable Entity mit allen Fehlern im JSON-Format.

Um einen Steuerbericht zu stornieren, verwenden Sie das Verb DELETE und rufen Sie den Annullierungsendpunkt auf. Verfolgen Sie den Fortschritt der Stornierung entweder über den Steuerbericht-Webhook oder durch Abfrage des Endpunkts zum Abrufen eines Steuerberichts, bis das Feld state des Steuerberichts error oder annulled lautet.

Um Ihre Steuerberichte aufzulisten, verwenden Sie das Verb GET am Endpunkt zum Auflisten von Steuerberichten.

Entsprechung zwischen internen B2Brouter-Steuerberichtsfeldern und TicketBAI XML-Knoten

Section titled “Entsprechung zwischen internen B2Brouter-Steuerberichtsfeldern und TicketBAI XML-Knoten”
B2Brouter-Feld (basierend auf PEPPOL CTC)TicketBAI XML-Knoten
supplier_party_tax_idSujetos > Emisor > NIF
supplier_party_nameSujetos > Emisor > ApellidosNombreRazonSocial
customer_party_tax_id (wenn customer_party_tax_scheme null ist)Sujetos > Destinatarios > IDDestinatario > NIF
customer_party_countrySujetos > Destinatarios > IDDestinatario > IDOtro > CodigoPais
customer_party_tax_schemeSujetos > Destinatarios > IDDestinatario > IDOtro > IDType
customer_party_tax_id (wenn customer_party_tax_scheme vorhanden ist)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 (wenn 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 (nicht befreit)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

TicketBAI-Schemata der baskischen Steuerbehörden.

XSD-DateiBeschreibung
ticketbaiv1-2-2.xsdEsquema principal de TicketBAI
anula_ticketbaiv1-2-2.xsdEsquema para el suministro de facturas

Parameter: invoice_type_code

CodeBeschreibung
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

Parameter: special_regime_key

CodeBeschreibung
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.
51Operaciones en recargo de equivalencia.
52Operaciones en régimen simplificado.

Parameter: non_exemption_code

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

Parameter: exemption_code

CodeBeschreibung
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

Parameter: no_subject_code

CodeBeschreibung
OTNo sujeto por el artículo 7 de la Norma Foral de IVA Otros supuestos de no sujeción.
RLNo sujeto por reglas de localización.
VTNo sujeto, ventas realizadas por cuenta de terceros.
IENo sujeto en el TAI por reglas de localización, pero repercute impuesto extranjero.

Parameter: customer_party_tax_scheme

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