[Beta] Guide SII
[Beta] Déclarer les enregistrements de TVA à l’AEAT via le SII (Suministro Inmediato de Información) avec l’API B2Brouter
Section titled “[Beta] Déclarer les enregistrements de TVA à l’AEAT via le SII (Suministro Inmediato de Información) avec l’API B2Brouter”[Beta] — staging uniquement. L’API JSON Tax Report pour le SII décrite dans ce guide est actuellement disponible sur l’environnement de staging (
https://api-staging.b2brouter.net) pour les tests d’intégration. Elle n’est pas encore activée en production. Les noms de champs, les endpoints et le comportement peuvent encore changer avant la mise en production.
Le système espagnol Suministro Inmediato de Información (SII) oblige les entreprises enregistrées à tenir leurs livres de TVA — factures émises, factures reçues, biens d’investissement, opérations intra-UE, transactions en espèces supérieures à 6 000 €, et autres — soumis en temps quasi réel à l’AEAT (« Agencia Estatal de Administración Tributaria »). Le SII est obligatoire pour les Grandes Empresas (chiffre d’affaires > 6 010 121,04 €), les membres de groupes de TVA, les participants au REDEME et d’autres entreprises ayant choisi de s’y inscrire volontairement.
B2Brouter propose une API JSON Tax Report pour le SII afin que ton système n’ait pas à gérer SOAP, les certificats AEAT, les soumissions par lots, l’analyse des réponses ni les enveloppes XML par livre. Tu effectues des appels REST ; B2Brouter s’occupe du reste, en regroupant les enregistrements dans des « Libros de Registro » de l’AEAT et en les soumettant sous un certificat de Collaborateur Social.
Qu’est-ce que le SII ?
Section titled “Qu’est-ce que le SII ?”Le SII est un système de déclaration fiscale distinct de la facturation — la facture sous-jacente ne porte aucun code QR et il n’y a aucune étape de vérification côté consommateur. Chaque enregistrement représente une entrée dans un livre (une facture émise, une facture reçue, la prorata annuelle d’un bien d’investissement, etc.). L’AEAT collecte les enregistrements tout au long de l’année et les utilise pour le rapprochement croisé de la TVA.
Le SII comporte neuf types de livres (« libros »), chacun avec sa propre enveloppe XML AEAT et ses règles de validation :
| Type de livre | Ce qu’il enregistre | A0 (alta) | A1 (modificación) | B (baja / annulation) |
|---|---|---|---|---|
| Expedida | Factures émises | ✓ | ✓ | ✓ |
| Recibida | Factures reçues | ✓ | ✓ | ✓ |
| Inversion | Biens d’investissement (bienes de inversión) | ✓ | ✓ | ✓ |
| Intracomunitaria | Opérations intra-UE | ✓ | ✓ | ✓ |
| Metalico | Transactions en espèces ≥ 6 000 € / contrepartie / période | ✓ | ✓ | ✓ |
| Seguro | Opérations d’assurance | ✓ | ✓ | ✓ |
| Viajesagencia | Régime spécial des agences de voyage | ✓ | ✓ | ✓ |
| Cobro | Paiements reçus sur factures émises | ✓ | — | — |
| Pago | Paiements effectués sur factures reçues | ✓ | — | — |
Cobro et Pago retournent HTTP 422 sur PATCH et DELETE — le XSD de l’AEAT ne prévoit pas de variantes A1 ni B pour ces livres.
Expedida et Recibida concentrent 98 %+ du volume en production. Les sept livres restants couvrent la longue traîne des exigences de déclaration de TVA.
Configuration et utilisation de l’API B2Brouter
Section titled “Configuration et utilisation de l’API B2Brouter”La première étape consiste à activer l’autorité fiscale SII pour l’entreprise qui déclarera. Tu peux consulter le Tax Report Settings Guide pour une description complète. L’appel minimal :
Exemple de requête :
curl --request POST \ --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": "sii", "start_date": "2026-04-15", "auto_send": true } }'Une fois qu’une configuration avec code: "sii" existe sur le compte, tous les appels à l’API Tax Report SII de ce compte l’utilisent.
API Tax Report
Section titled “API Tax Report”L’API Tax Report est une famille d’endpoints qui gère les neuf livres SII. Le livre est sélectionné par le champ book_type du corps de la requête. Le champ type est SiiDocument pour tous les enregistrements SII quel que soit le livre.
Créer un Tax Report
Section titled “Créer un Tax Report”POST /accounts/{ACCOUNT_ID}/tax_reports crée un enregistrement SII. Le même endpoint est utilisé par Verifactu, TicketBai et KSeF ; le champ type détermine quel ensemble de validation + quelle enveloppe XML AEAT s’applique.
La structure du payload JSON est basée sur le PEPPOL Continuous Transaction Control (CTC) — les noms de champs CTC ne correspondent pas aux noms de nœuds XML de l’AEAT. La section Équivalence entre les champs internes de tax report B2Brouter et les nœuds XML du SII ci-dessous liste le mapping pour chaque livre.
Les tax reports ont des ventilations fiscales (« desglose » en espagnol), et non des lignes de facture. Ton système agrège les lignes de facture sous-jacentes par type/catégorie fiscale et soumet les totaux de la ventilation. B2Brouter effectue la validation mais ne calcule pas les ventilations à partir des données de lignes.
Cycle de vie
Section titled “Cycle de vie”Après un POST /tax_reports réussi, la réponse porte un state: "processing" et un ledger_id. Les enregistrements SII sont regroupés en « Libros de Registro » (Ledgers) côté serveur et soumis à l’AEAT de manière asynchrone. Pour suivre le cycle de vie :
- Recommandé : configure le webhook de tax report. B2Brouter appelle ton endpoint lorsque l’enregistrement atteint un état final (
registered,error,registered_with_errors,annulledourefused). - Polling : appelle
GET /tax_reports/{id}répétitivement jusqu’à ce questateatteigne l’une des valeurs finales.
La réponse de l’AEAT est reflétée dans trois champs spécifiques au SII sur l’enregistrement une fois reçue :
csv— le Código Seguro de Verificación assigné par l’AEATfecha_presentacion— le timestamp de présentation assigné par l’AEATestado— l’état interne du SII. Il commence àNuevo, passe àEnviandopendant le transit et se stabilise sur une valeur terminale :Correcto,Incorrecto,AceptadoConErroresouError.
Pour les états d’erreur, le tableau errors de l’enregistrement est renseigné avec le rejet de l’AEAT, chaque entrée portant un code et une description :
{ "errors": [ { "code": "4102", "description": "El NIF no está identificado en el censo de la AEAT" } ]}Obtenir la représentation XML
Section titled “Obtenir la représentation XML”GET /tax_reports/{id}/download retourne le XML par enregistrement que B2Brouter inclura (ou a inclus) dans la soumission à l’AEAT. Le XML est généré au moment de la création et persisté, il est donc disponible immédiatement après le POST. Le paquet qui transite réellement est le XML du Ledger concaténé — voir l’API Ledgers.
Corriger un Tax Report (A1)
Section titled “Corriger un Tax Report (A1)”PATCH /tax_reports/{id} avec les champs corrigés crée un enregistrement frère avec operacion: A1 (modificación). L’enregistrement original est conservé ; le nouveau frère est lié via corrected_by_id sur l’original et c’est lui qui est re-soumis à l’AEAT.
Le livre auquel appartient un enregistrement est fixé à la création — book_type ne peut pas être modifié sur un frère A1. Cobro et Pago retournent 422 ; leur XSD AEAT ne définit pas d’enveloppe A1.
Annuler un Tax Report (B)
Section titled “Annuler un Tax Report (B)”DELETE /tax_reports/{id} crée un enregistrement frère avec operacion: B (baja / annulation). L’original est lié via annulled_by_id. Cobro et Pago retournent 422 — leur XSD AEAT ne définit pas d’enveloppe de baja.
Lister les Tax Reports
Section titled “Lister les Tax Reports”GET /accounts/{ACCOUNT_ID}/tax_reports retourne les tax reports du compte — SII, Verifactu, TicketBai, KSeF, tous dans une seule liste. Filtre par plage de dates ou d’autres critères comme documenté dans l’endpoint de liste des tax reports.
Expedida (factures émises)
Section titled “Expedida (factures émises)”Le livre SII le plus courant. L’entreprise déclarante est l’émettrice de la facture ; le client est la contrepartie.
Exemple de requête
Section titled “Exemple de requête”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": "SiiDocument", "book_type": "Expedida", "invoice_number": "INV-2026-001", "invoice_date": "2026-04-15", "fiscal_year": 2026, "fiscal_period": 4, "invoice_type_code": "F1", "special_regime_key": "01", "description": "Servicios de consultoría", "customer_party_name": "Cliente Ejemplo S.L.", "customer_party_tax_id": "B87654321", "customer_party_country": "es", "tax_inclusive_amount": 1210.0, "tax_amount": 210.0, "currency": "EUR", "tax_breakdowns": [ { "name": "IVA", "category": "S", "percent": 21.0, "taxable_base": 1000.0, "tax_amount": 210.0 } ] } }'Champs spécifiques à Expedida (en plus des champs CTC communs) :
| Champ | Correspond à l’élément AEAT | Notes |
|---|---|---|
simplified_art7273 | FacturaSimplificadaArticulos7.2_7.3 | Booléen. Émet S quand true. |
reg_previo_ggee | RegPrevioGGEEoREDEMEoCompetencia | Booléen. |
macrodata | Macrodato | Booléen (SII), contrairement à la version string de Verifactu. |
facturacion_disp_adicional_mercado_gas | FacturacionDispAdicionalTerceraYsextayDelMercadoOrganizadoDelGas | Booléen. Exclusif à Expedida. |
sin_identif_destinatario_art_6_1_d | FacturaSinIdentifDestinatarioAritculo6.1.d | Booléen. Exclusif à Expedida. |
succession_party_name + _tax_id | EntidadSucedida > NombreRazon / NIF | Les deux obligatoires ensemble quand utilisés. |
billing_agreement_number | NumRegistroAcuerdoFacturacion | 15 caractères maximum. |
external_reference | RefExterna | 60 caractères maximum. |
tax_point_date | FechaOperacion | Optionnel ; omis par défaut. |
L’enveloppe XML AEAT est SuministroLRFacturasEmitidas. Les cinq flags S/N ci-dessus sont optionnels et ne sont émis que lorsqu’ils sont true.
Recibida (factures reçues)
Section titled “Recibida (factures reçues)”Recibida présente l’inversion émetteur/récepteur par rapport à Expedida : le fournisseur externe est l’émetteur (enregistré dans IDEmisorFactura), et l’entreprise déclarante est la réceptrice (Titular). Utilise supplier_party_* pour le fournisseur externe ; customer_party_* n’est pas requis (les valeurs par défaut de l’entreprise sont utilisées comme récepteur).
Exemple de requête
Section titled “Exemple de requête”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": "SiiDocument", "book_type": "Recibida", "invoice_number": "PROV-555", "invoice_date": "2026-04-15", "tax_point_date": "2026-04-10", "fecha_contable": "2026-04-22", "fiscal_year": 2026, "fiscal_period": 4, "invoice_type_code": "F1", "special_regime_key": "01", "description": "Compra de material", "supplier_party_name": "Proveedor Test S.L.", "supplier_party_tax_id": "A12345674", "supplier_party_country": "es", "tax_inclusive_amount": 1210.0, "tax_amount": 210.0, "cuota_deducible_in_cents": 21000, "currency": "EUR", "tax_breakdowns": [ { "name": "IVA", "category": "S", "percent": 21.0, "taxable_base": 1000.0, "tax_amount": 210.0 } ] } }'Champs spécifiques à Recibida :
| Champ | Correspond à l’élément AEAT | Notes |
|---|---|---|
supplier_party_tax_id / _name | IDEmisorFactura > NIF / Contraparte > NombreRazon | Le fournisseur externe — l’émetteur de la facture reçue. |
supplier_party_country | IDOtro > CodigoPais | Quand ce n’est pas es, l’émetteur est rendu via IDOtro au lieu de NIF. |
tax_point_date | FechaOperacion | Date de l’opération/service. Omis quand non fourni. |
fecha_contable | FechaRegContable | Date à laquelle la facture a été enregistrée dans tes livres comptables. Si absent, utilise tax_point_date puis invoice_date en fallback. |
cuota_deducible_in_cents | CuotaDeducible | Quote déductible. Quand omis, dérivé de sum(tax_breakdowns.tax_amount). À définir explicitement pour surcharger (déductibilité partielle, etc.). |
simplified_art7273 | FacturaSimplificadaArticulos7.2_7.3 | Booléen. Même forme qu’Expedida. |
reg_previo_ggee | RegPrevioGGEEoREDEMEoCompetencia | Booléen. |
macrodata | Macrodato | Booléen. |
succession_party_* | EntidadSucedida | Identique à Expedida. |
billing_agreement_number | NumRegistroAcuerdoFacturacion | Identique à Expedida. |
external_reference | RefExterna | Identique à Expedida. |
Les deux flags exclusifs à Expedida (facturacion_disp_adicional_mercado_gas, sin_identif_destinatario_art_6_1_d) n’apparaissent pas sur Recibida — le XSD AEAT les définit uniquement sur FacturaExpedidaType.
L’enveloppe XML AEAT est SuministroLRFacturasRecibidas.
Fournisseurs non espagnols
Section titled “Fournisseurs non espagnols”Quand supplier_party_country n’est pas es, l’émetteur est rendu comme IDOtro au lieu de NIF :
<sii:IDEmisorFactura> <sii:IDOtro> <sii:CodigoPais>FR</sii:CodigoPais> <sii:IDType>04</sii:IDType> <sii:ID>FR12345678901</sii:ID> </sii:IDOtro></sii:IDEmisorFactura>Le bloc Contraparte est également rendu avec IDOtro pour correspondre.
Autres livres (Inversion, Intracomunitaria, Metalico, Seguro, Viajesagencia, Cobro, Pago)
Section titled “Autres livres (Inversion, Intracomunitaria, Metalico, Seguro, Viajesagencia, Cobro, Pago)”Les sept livres restants couvrent chacun une exigence de déclaration spécifique. Ils partagent les champs CTC communs et le même cycle de vie, mais portent des scalaires spécifiques au livre. Consulte la référence OpenAPI pour la liste complète des champs.
Inversion (biens d’investissement)
Section titled “Inversion (biens d’investissement)”Enregistre la prorata annuelle + la régularisation des biens d’investissement. Enveloppe AEAT : SuministroLRBienesInversion. Champs obligatoires (en plus de l’enveloppe CTC commune) :
identificacion_bien— identifiant du bien (IdentificacionBien, max. 40 caractères)fecha_inicio_utilizacion— date à laquelle le bien est entré en service (FechaInicioUtilizacion)prorrata_anual_definitiva— prorata annuelle définitive (ProrrataAnualDefinitiva, 0–100, 2 décimales)
Optionnels : regularizacion_anual_deduccion_in_cents, identificacion_entrega, regularizacion_deduccion_efectuada_in_cents, external_reference, billing_agreement_number, succession_party_*.
Intracomunitaria (opérations intra-UE)
Section titled “Intracomunitaria (opérations intra-UE)”Enveloppe AEAT : SuministroLRDetOperacionIntracomunitaria. Obligatoires : clave_declarado (enum D ou R), external_reference (selon le XSD AEAT), plus description mappé à DescripcionBienes. Optionnels : plazo_operacion, facturas_o_documentacion.
Metalico / Seguro / Viajesagencia (agrégés par période)
Section titled “Metalico / Seguro / Viajesagencia (agrégés par période)”Ces livres sont agrégés par période : un seul enregistrement représente le total d’une contrepartie sur une période fiscale. Il n’y a pas de invoice_number ni de invoice_date — le XSD AEAT omet le bloc IDFactura. La contrepartie est fournie via customer_party_* (B2Brouter la reflète dans nombre_contraparte côté serveur).
- Metalico : enveloppe
SuministroLRCobrosMetalico. Agrège les encaissements en espèces d’une contrepartie ≥ 6 000 € sur une période fiscale. - Seguro : enveloppe
SuministroLROperacionesSeguros. Ajoute unClaveOperacionobligatoire mappé depuisoperation_type. - Viajesagencia : enveloppe
SuministroLRAgenciasViajes. Structurellement identique à Metalico selon le XSD AEAT.
Cobro / Pago (suivi des paiements)
Section titled “Cobro / Pago (suivi des paiements)”Cobro : paiements reçus sur factures émises. Pago : paiements effectués sur factures reçues. Les deux portent un tableau d’événements de paiement par enregistrement dans payload_data :
{ "payload_data": { "cobros": [ { "fecha": "2026-03-01", "importe_in_cents": 50000, "medio": "01", "cuenta_o_medio": "ES1234..." }, { "fecha": "2026-04-01", "importe_in_cents": 50000, "medio": "01", "cuenta_o_medio": "ES1234..." } ] }}(Utilise pagos à la place de cobros pour Pago.)
Il n’existe pas de variantes A1 ni B pour ces livres selon le XSD AEAT — PATCH et DELETE retournent 422.
Endpoint en masse (asynchrone)
Section titled “Endpoint en masse (asynchrone)”Pour les intégrations à haut volume (agrégations de points de vente, migrations CSV vers JSON, etc.), utilise POST /accounts/{ACCOUNT_ID}/tax_report_batches pour soumettre jusqu’à 5 000 enregistrements en une seule requête. Le traitement est asynchrone : l’appel valide uniquement l’enveloppe et retourne 202 Accepted avec un id de lot ; la construction, la validation et l’attachement au ledger de chaque enregistrement s’exécutent en arrière-plan. Tu dois ensuite interroger l’endpoint de statut du lot (ou te fier au webhook tax_report.state_change par enregistrement une fois que l’AEAT répond).
curl --request POST \ --url 'https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/tax_report_batches' \ --header 'X-B2B-API-Key: {YOUR_API_KEY}' \ --header 'X-B2B-API-Version: {YOUR_API_VERSION}' \ --header 'Content-Type: application/json' \ --data '{ "tax_reports": [ { "type": "SiiDocument", "book_type": "Expedida", "invoice_number": "INV-001", ... }, { "type": "SiiDocument", "book_type": "Expedida", "invoice_number": "INV-002", ... }, ... ] }'Réponse acceptée (202) :
{ "batch_id": 4567, "status": "processing", "total": 2, "status_url": "https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/tax_report_batches/4567"}Interroge le statut du lot sur GET /accounts/{ACCOUNT_ID}/tax_report_batches/{BATCH_ID}. Pendant l’exécution du traitement, status est "processing" ; une fois terminé, il est "done" et results est renseigné, dans l’ordre de soumission :
{ "batch_id": 4567, "status": "done", "summary": { "total": 3, "accepted": 2, "rejected": 1 }, "results": [ { "index": 0, "status": "created", "tax_report": { "id": 12345, ... } }, { "index": 1, "status": "error", "errors": [{ "code": "invalid_book_type", ... }] }, { "index": 2, "status": "created", "tax_report": { "id": 12346, ... } } ]}Sémantique :
- Asynchrone : le
202signifie uniquement que le lot a été accepté pour traitement — pas qu’un enregistrement ait été créé. Interrogestatus_urljusqu’à ce questatussoit"done", ou consomme le webhooktax_report.state_changepour le résultat AEAT de chaque enregistrement créé. - Succès partiel : chaque enregistrement est validé indépendamment dans le traitement. Un échec sur un enregistrement (mauvais
book_type, XML invalide selon XSD,typenon supporté) n’interrompt pas le lot — il apparaît commeerrorpar enregistrement dansresults. - Erreurs d’enveloppe (clé
tax_reportsabsente, pas un tableau, plus de 5 000 enregistrements) retournent HTTP400de manière synchrone, avant que quoi que ce soit soit mis en file d’attente. - SII uniquement en v1 : cet endpoint accepte uniquement
type: "SiiDocument". Untypenon SII ou absent sur un enregistrement est rejeté de manière synchrone avec HTTP422(code: "unsupported_type") avant que quoi que ce soit soit mis en file d’attente — c’est une erreur de contrat d’endpoint, distincte des erreurs de données SII par enregistrement (mauvaisbook_type, XML invalide par XSD), qui sont signalées comme erreurs partielles dans le statut du lot. - Attachement au ledger + envoi : les enregistrements créés sont attachés à des ledgers SII ségrégués par mode regroupés par
(document_type_code, NIF de l'entreprise déclarante)— c’est-à-dire par le Titular déclaré dans laCabeceraAEAT, pas par lesupplier_party_tax_idpar enregistrement. Pour Recibida/Pago ce champ contient le fournisseur externe, donc les enregistrements de différents fournisseurs partagent un même ledger tant qu’ils appartiennent au même livre et à la même entreprise déclarante. Les ledgers sont ensuite soumis à l’AEAT par le cron par minute (voir l’API Ledgers) — jamais sur le thread de la requête.
Savoir quand le lot est terminé
Section titled “Savoir quand le lot est terminé”Deux options, utilise l’une ou les deux :
-
Polling sur
status_urljusqu’à ce questatussoit"done". -
Webhook — abonne un webhook activé sur ton groupe d’intégration à l’événement
sii_batch.finished. Quand le job d’ingestion se termine, B2Brouter envoie un POST :{"code": "sii_batch.finished","triggered_at": 1748000000,"data": {"batch_id": 4567,"status": "done","summary": { "total": 3, "accepted": 2, "rejected": 1 },"status_url": "https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/tax_report_batches/4567"}}Le corps du webhook ne contient que le résumé (borné quelle que soit la taille du lot) ; appelle
GET status_urlpour les résultats complets par enregistrement. Le résultat AEAT de chaque enregistrement créé arrive toujours via son propre webhooktax_report.state_change.
API Ledgers
Section titled “API Ledgers”Les tax reports SII ne sont pas envoyés individuellement à l’AEAT — ils sont regroupés dans des « Libros de Registro » (Ledger dans la terminologie B2Brouter), contenant jusqu’à 5 000 enregistrements par livre / entreprise déclarante (Titular). Chaque tax report a un champ ledger_id pointant vers l’ID interne du Ledger. Avec cet ID tu peux :
- Récupérer la représentation XML du Ledger via l’endpoint de téléchargement du ledger. C’est le document que B2Brouter envoie à l’AEAT.
- Récupérer la réponse XML de l’AEAT à ce Ledger via l’endpoint de téléchargement de la réponse.
Les Ledgers SII modernes sont envoyés à l’AEAT exclusivement par le cron par minute piloté par la politique Strategy::Sii (60 secondes entre les soumissions, ou immédiatement dès qu’un Ledger atteint 5 000 enregistrements). Ni POST /tax_reports, PATCH/DELETE, ni l’endpoint en masse n’envoient jamais à l’AEAT sur le thread de la requête — ils attachent le ou les enregistrement(s) et retournent ; le cron effectue l’envoi. Prévois jusqu’à ~60 s entre la création et la soumission.
Équivalence entre les champs internes de tax report B2Brouter et les nœuds XML du SII
Section titled “Équivalence entre les champs internes de tax report B2Brouter et les nœuds XML du SII”Expedida (SuministroLRFacturasEmitidas)
Section titled “Expedida (SuministroLRFacturasEmitidas)”| Champ B2Brouter | Nœud XML AEAT |
|---|---|
fiscal_year | PeriodoLiquidacion > Ejercicio |
fiscal_period | PeriodoLiquidacion > Periodo |
supplier_party_tax_id | IDFactura > IDEmisorFactura > NIF |
invoice_number | IDFactura > NumSerieFacturaEmisor |
invoice_date | IDFactura > FechaExpedicionFacturaEmisor |
invoice_type_code | FacturaExpedida > TipoFactura |
tax_point_date | FacturaExpedida > FechaOperacion |
special_regime_key | FacturaExpedida > ClaveRegimenEspecialOTrascendencia |
billing_agreement_number | FacturaExpedida > NumRegistroAcuerdoFacturacion |
tax_inclusive_amount | FacturaExpedida > ImporteTotal |
description | FacturaExpedida > DescripcionOperacion |
external_reference | FacturaExpedida > RefExterna |
simplified_art7273 | FacturaExpedida > FacturaSimplificadaArticulos7.2_7.3 |
succession_party_name | FacturaExpedida > EntidadSucedida > NombreRazon |
succession_party_tax_id | FacturaExpedida > EntidadSucedida > NIF |
reg_previo_ggee | FacturaExpedida > RegPrevioGGEEoREDEMEoCompetencia |
macrodata | FacturaExpedida > Macrodato |
facturacion_disp_adicional_mercado_gas | FacturaExpedida > FacturacionDispAdicionalTerceraYsextayDelMercadoOrganizadoDelGas |
sin_identif_destinatario_art_6_1_d | FacturaExpedida > FacturaSinIdentifDestinatarioAritculo6.1.d |
customer_party_name | FacturaExpedida > Contraparte > NombreRazon |
customer_party_tax_id | FacturaExpedida > Contraparte > NIF |
tax_breakdowns[*].percent | DetalleIVA > TipoImpositivo |
tax_breakdowns[*].taxable_base | DetalleIVA > BaseImponible |
tax_breakdowns[*].tax_amount | DetalleIVA > CuotaRepercutida (omis quand zéro) |
Recibida (SuministroLRFacturasRecibidas)
Section titled “Recibida (SuministroLRFacturasRecibidas)”| Champ B2Brouter | Nœud XML AEAT |
|---|---|
fiscal_year | PeriodoLiquidacion > Ejercicio |
fiscal_period | PeriodoLiquidacion > Periodo |
supplier_party_tax_id | IDFactura > IDEmisorFactura > NIF (ou IDOtro > ID pour non-ES) |
supplier_party_country | IDFactura > IDEmisorFactura > IDOtro > CodigoPais (non-ES seul.) |
supplier_party_name | FacturaRecibida > Contraparte > NombreRazon |
invoice_number | IDFactura > NumSerieFacturaEmisor |
invoice_date | IDFactura > FechaExpedicionFacturaEmisor |
invoice_type_code | FacturaRecibida > TipoFactura |
tax_point_date | FacturaRecibida > FechaOperacion |
special_regime_key | FacturaRecibida > ClaveRegimenEspecialOTrascendencia |
billing_agreement_number | FacturaRecibida > NumRegistroAcuerdoFacturacion |
tax_inclusive_amount | FacturaRecibida > ImporteTotal |
description | FacturaRecibida > DescripcionOperacion |
external_reference | FacturaRecibida > RefExterna |
simplified_art7273 | FacturaRecibida > FacturaSimplificadaArticulos7.2_7.3 |
succession_party_name | FacturaRecibida > EntidadSucedida > NombreRazon |
succession_party_tax_id | FacturaRecibida > EntidadSucedida > NIF |
reg_previo_ggee | FacturaRecibida > RegPrevioGGEEoREDEMEoCompetencia |
macrodata | FacturaRecibida > Macrodato |
tax_breakdowns[*].percent | DetalleIVA > TipoImpositivo |
tax_breakdowns[*].taxable_base | DetalleIVA > BaseImponible |
tax_breakdowns[*].tax_amount | DetalleIVA > CuotaSoportada (omis quand zéro) |
fecha_contable | FacturaRecibida > FechaRegContable |
cuota_deducible_in_cents | FacturaRecibida > CuotaDeducible |
category de la ventilation fiscale → bucket de desglose
Section titled “category de la ventilation fiscale → bucket de desglose”Chaque tax_breakdowns[*].category (le code de catégorie de TVA standard PEPPOL/UN-CEFACT) détermine dans quel bucket de desglose de l’AEAT la ligne atterrit. C’est le signal canonique — envoie la bonne category ; les flags booléens en sont dérivés.
Expedida (TipoDesglose > DesgloseFactura) :
category | Bucket AEAT |
|---|---|
S, Z, H, AA, AAA, N1 (taxable) | Sujeta > NoExenta, TipoNoExenta = S1 |
AE (autoliquidation) | Sujeta > NoExenta, TipoNoExenta = S2 |
E, K, N2.*, N3.2, N3.6, N4, N5, N7, IC (exonéré) | Sujeta > Exenta > DetalleExenta (CausaExencion ← exemption_code) |
NS, O, G, N3.1, N3.3–N3.5 (hors champ) | NoSujeta (ImporteTAIReglasLocalizacion quand no_subject_code = RL, sinon ImportePorArticulos7_14_Otros) |
Un mélange de lignes S1 et S2 se réduit à un unique TipoNoExenta = S3. Une ligne sans catégorie reconnue est rendue comme S1 (entièrement taxable).
Recibida (DesgloseFactura) : les lignes en autoliquidation (category AE) vont dans InversionSujetoPasivo ; tout le reste dans DesgloseIVA.
Pas encore supporté :
DesgloseTipoOperacion(la division biens/services que l’AEAT exige pour certaines contreparties transfrontalières). Les factures qui en ont besoin doivent utiliser le chemin CSV hérité jusqu’à ce qu’une version ultérieure ajoute le support — reflète le report deDatosInmueblepour les biens immobiliers.
Fichiers XSD
Section titled “Fichiers XSD”L’AEAT publie les XSD canoniques du SII. B2Brouter valide le XML généré contre SuministroInformacion.xsd et SuministroLR.xsd (v1.1) à chaque envoi. Les schémas se trouvent dans ce dépôt à vendor/xsd-validator/lib/xsd/schemas/sii_v11/.
Description des codes pour les champs spécifiques
Section titled “Description des codes pour les champs spécifiques”book_type
Section titled “book_type”Les valeurs sont listées dans Qu’est-ce que le SII ? ci-dessus. Le book_type détermine l’enveloppe XML AEAT, l’ensemble des champs obligatoires et les règles de validation.
invoice_type_code
Section titled “invoice_type_code”Pour Expedida et Recibida :
F1— Factura (art. 6, 7.2 y 7.3 del RD 1619/2012)F2— Factura Simplificada y Facturas sin identificación del destinatario (art. 6.1.d) RD 1619/2012F3— Factura emitida en sustitución de facturas simplificadas facturadas y declaradasF4— Asiento resumen de facturasF5— Importaciones (DUA)F6— Otros justificantes contablesR1— Factura Rectificativa (Error fundado en derecho y Art. 80 Uno Dos y Seis LIVA)R2— Factura Rectificativa (Art. 80.3)R3— Factura Rectificativa (Art. 80.4)R4— Factura Rectificativa (Resto)R5— Factura Rectificativa en facturas simplificadas
special_regime_key (ClaveRegimenEspecialOTrascendencia)
Section titled “special_regime_key (ClaveRegimenEspecialOTrascendencia)”Un code à deux chiffres de l’AEAT décrivant le régime spécial appliqué à l’opération. Les valeurs les plus courantes sont 01 (régimen general), 02 (exportaciones), 03 (régimen especial bienes usados), 04 (régimen especial oro de inversión), 05 (régimen especial agencias de viajes), 06 (régimen especial grupo de entidades), 07 (régimen especial criterio de caja), 08 (operaciones IPSI / IGIC). Consulte les spécifications AEAT pour la liste complète et l’applicabilité par livre.
clave_declarado (Intracomunitaria uniquement)
Section titled “clave_declarado (Intracomunitaria uniquement)”D— DeclaranteR— Receptor
Vérification des erreurs
Section titled “Vérification des erreurs”B2Brouter valide les payloads SII contre les XSD de l’AEAT avant toute soumission. Un échec de validation retourne HTTP 422 avec les champs défaillants détaillés en JSON. Si l’AEAT elle-même rejette une soumission (p. ex. NIF de contrepartie inconnu), le rejet est reflété dans le state de l’enregistrement (typiquement error ou registered_with_errors) et dans les champs error_code / error_description de l’AEAT. Configure le webhook de tax report pour réagir aux états finaux sans polling.