[Beta] Informa registros de IVA a la AEAT mediante SII (Suministro Inmediato de Información) con la API de B2Brouter
[Beta] — solo en staging. La API JSON Tax Report para SII descrita en esta guía está disponible actualmente en el entorno de staging (
https://api-staging.b2brouter.net) para pruebas de integración. Todavía no está habilitada en producción. Los nombres de campos, endpoints y comportamiento pueden cambiar antes del lanzamiento en producción.
El sistema español Suministro Inmediato de Información (SII) obliga a las empresas registradas a mantener sus libros de IVA — facturas emitidas, facturas recibidas, bienes de inversión, operaciones intracomunitarias, operaciones en metálico superiores a 6.000 €, entre otros — enviados en tiempo casi real a la AEAT (“Agencia Estatal de Administración Tributaria”). El SII es obligatorio para las Grandes Empresas (facturación > 6.010.121,04 €), los miembros de grupos de IVA, los participantes en el REDEME y otras empresas que se hayan acogido voluntariamente.
B2Brouter ofrece una API JSON Tax Report para SII para que tu sistema no tenga que gestionar SOAP, certificados de la AEAT, envíos por lotes, análisis de respuestas ni los wrappers XML por libro. Tú realizas llamadas REST; B2Brouter se encarga del resto, agrupando los registros en “Libros de Registro” de la AEAT y enviándolos bajo un certificado de Colaborador Social.
¿Qué es el SII?
Sección titulada «¿Qué es el SII?»El SII es un sistema de información tributaria distinto de la facturación — la factura subyacente no lleva ningún código QR ni hay ningún paso de verificación de cara al consumidor. Cada registro representa una entrada en un libro (una factura emitida, una factura recibida, la prorrata anual de un bien de inversión, etc.). La AEAT recopila los registros a lo largo del año y los utiliza para la comprobación cruzada del IVA.
El SII tiene nueve tipos de libros (“libros”), cada uno con su propio wrapper XML de la AEAT y sus reglas de validación:
| Tipo de libro | Qué registra | A0 (alta) | A1 (modificación) | B (baja / anulación) |
|---|---|---|---|---|
| Expedida | Facturas emitidas | ✓ | ✓ | ✓ |
| Recibida | Facturas recibidas | ✓ | ✓ | ✓ |
| Inversion | Bienes de inversión | ✓ | ✓ | ✓ |
| Intracomunitaria | Operaciones intracomunitarias | ✓ | ✓ | ✓ |
| Metalico | Operaciones en metálico ≥ 6.000 € / contrapartida / período | ✓ | ✓ | ✓ |
| Seguro | Operaciones de seguros | ✓ | ✓ | ✓ |
| Viajesagencia | Régimen especial de agencias de viajes | ✓ | ✓ | ✓ |
| Cobro | Cobros recibidos de facturas emitidas | ✓ | — | — |
| Pago | Pagos realizados de facturas recibidas | ✓ | — | — |
Cobro y Pago devuelven HTTP 422 en PATCH y DELETE — el XSD de la AEAT no contempla variantes A1 ni B para esos libros.
Expedida y Recibida concentran el 98%+ del volumen en producción. Los siete libros restantes cubren la larga cola de requisitos de información de IVA.
Configuración y trabajo con la API de B2Brouter
Sección titulada «Configuración y trabajo con la API de B2Brouter»El primer paso es habilitar la autoridad tributaria SII para la empresa que va a informar. Puedes consultar la Tax Report Settings Guide para una descripción completa. La llamada mínima:
Ejemplo de petición:
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 } }'Una vez que existe una configuración con code: "sii" en la cuenta, todas las llamadas a la API Tax Report SII de esa cuenta la utilizan.
API Tax Report
Sección titulada «API Tax Report»La API Tax Report es una familia de endpoints que gestiona los nueve libros SII. El libro se selecciona con el campo book_type del cuerpo de la petición. El campo type es SiiDocument para todos los registros SII independientemente del libro.
Crear un Tax Report
Sección titulada «Crear un Tax Report»POST /accounts/{ACCOUNT_ID}/tax_reports crea un registro SII. El mismo endpoint lo utilizan Verifactu, TicketBai y KSeF; el campo type determina qué conjunto de validación + qué wrapper XML de la AEAT se aplica.
La estructura del payload JSON se basa en el PEPPOL Continuous Transaction Control (CTC) — los nombres de campos CTC no coinciden con los nombres de nodos del XML de la AEAT. La sección Equivalencia entre los campos internos de tax report de B2Brouter y los nodos XML del SII más abajo recoge el mapeo para cada libro.
Los tax reports tienen desgloses fiscales (“desglose”), no líneas de factura. Tu sistema agrega las líneas de factura subyacentes por tipo/categoría fiscal y envía las sumas del desglose. B2Brouter realiza la validación pero no calcula los desgloses a partir de los datos de las líneas.
Ciclo de vida
Sección titulada «Ciclo de vida»Tras un POST /tax_reports satisfactorio, la respuesta lleva un state: "processing" y un ledger_id. Los registros SII se agrupan en “Libros de Registro” (Ledgers) en el servidor y se envían a la AEAT de manera asíncrona. Para hacer el seguimiento del ciclo de vida:
- Recomendado: configura el webhook de tax report. B2Brouter llama a tu endpoint cuando el registro llega a un estado final (
registered,error,registered_with_errors,annulledorefused). - Polling: llama a
GET /tax_reports/{id}repetidamente hasta questatellegue a uno de los valores finales.
La respuesta de la AEAT se refleja en tres campos específicos de SII en el registro una vez recibida:
csv— el Código Seguro de Verificación asignado por la AEATfecha_presentacion— el timestamp de presentación asignado por la AEATestado— el estado interno del SII. Comienza enNuevo, pasa aEnviandomientras está en tránsito y se estabiliza en un valor terminal:Correcto,Incorrecto,AceptadoConErroresoError.
Para los estados de error, el array errors del registro se rellena con el rechazo de la AEAT, donde cada entrada lleva un code y una description:
{ "errors": [ { "code": "4102", "description": "El NIF no está identificado en el censo de la AEAT" } ]}Obtener la representación XML
Sección titulada «Obtener la representación XML»GET /tax_reports/{id}/download devuelve el XML por registro que B2Brouter incluirá (o incluyó) en el envío a la AEAT. El XML se genera en el momento de la creación y se persiste, de modo que está disponible inmediatamente después del POST. El paquete que se envía realmente es el XML del Ledger concatenado — consulta la API de Ledgers.
Corregir un Tax Report (A1)
Sección titulada «Corregir un Tax Report (A1)»PATCH /tax_reports/{id} con los campos corregidos crea un registro hermano con operacion: A1 (modificación). El registro original se mantiene; el nuevo hermano se enlaza mediante corrected_by_id en el original y es el que se reenvía a la AEAT.
El libro al que pertenece un registro queda fijado en el momento de la creación — book_type no puede cambiarse en un hermano A1. Cobro y Pago devuelven 422; su XSD de la AEAT no define ningún wrapper A1.
Cancelar un Tax Report (B)
Sección titulada «Cancelar un Tax Report (B)»DELETE /tax_reports/{id} crea un registro hermano con operacion: B (baja / anulación). El original se enlaza mediante annulled_by_id. Cobro y Pago devuelven 422 — su XSD de la AEAT no define ningún wrapper de baja.
Listar Tax Reports
Sección titulada «Listar Tax Reports»GET /accounts/{ACCOUNT_ID}/tax_reports devuelve los tax reports de la cuenta — SII, Verifactu, TicketBai, KSeF, todos en una sola lista. Filtra por rango de fechas u otros criterios tal como se documenta en el endpoint de listado de tax reports.
Expedida (facturas emitidas)
Sección titulada «Expedida (facturas emitidas)»El libro SII más común. La empresa que informa es la emisora de la factura; el cliente es la contrapartida.
Ejemplo de petición
Sección titulada «Ejemplo de petición»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 } ] } }'Campos específicos de Expedida (además de los campos CTC comunes):
| Campo | Mapea al elemento AEAT | Notas |
|---|---|---|
simplified_art7273 | FacturaSimplificadaArticulos7.2_7.3 | Booleano. Emite S cuando es true. |
reg_previo_ggee | RegPrevioGGEEoREDEMEoCompetencia | Booleano. |
macrodata | Macrodato | Booleano (SII), a diferencia de la versión string de Verifactu. |
facturacion_disp_adicional_mercado_gas | FacturacionDispAdicionalTerceraYsextayDelMercadoOrganizadoDelGas | Booleano. Exclusivo de Expedida. |
sin_identif_destinatario_art_6_1_d | FacturaSinIdentifDestinatarioAritculo6.1.d | Booleano. Exclusivo de Expedida. |
succession_party_name + _tax_id | EntidadSucedida > NombreRazon / NIF | Ambos obligatorios conjuntamente cuando se usan. |
billing_agreement_number | NumRegistroAcuerdoFacturacion | Máximo 15 caracteres. |
external_reference | RefExterna | Máximo 60 caracteres. |
tax_point_date | FechaOperacion | Opcional; se omite por defecto. |
El wrapper XML de la AEAT es SuministroLRFacturasEmitidas. Los cinco flags S/N anteriores son opcionales y se emiten solo cuando son true.
Recibida (facturas recibidas)
Sección titulada «Recibida (facturas recibidas)»Recibida tiene la inversión emisor/receptor respecto a Expedida: el proveedor externo es el emisor (registrado en IDEmisorFactura), y la empresa que informa es la receptora (Titular). Usa supplier_party_* para el proveedor externo; customer_party_* no es necesario (los valores por defecto de la empresa se usan como receptor).
Ejemplo de petición
Sección titulada «Ejemplo de petición»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 } ] } }'Campos específicos de Recibida:
| Campo | Mapea al elemento AEAT | Notas |
|---|---|---|
supplier_party_tax_id / _name | IDEmisorFactura > NIF / Contraparte > NombreRazon | El proveedor externo — el emisor de la factura recibida. |
supplier_party_country | IDOtro > CodigoPais | Cuando no es es, el emisor se renderiza mediante IDOtro en lugar de NIF. |
tax_point_date | FechaOperacion | Fecha de la operación/servicio. Se omite cuando no se facilita. |
fecha_contable | FechaRegContable | Fecha en que la factura se registró en tus libros contables. Si no está presente, usa tax_point_date y luego invoice_date como fallback. |
cuota_deducible_in_cents | CuotaDeducible | Cuota deducible. Cuando se omite, se deriva de sum(tax_breakdowns.tax_amount). Establécela explícitamente para sobreescribir (deducibilidad parcial, etc.). |
simplified_art7273 | FacturaSimplificadaArticulos7.2_7.3 | Booleano. Misma forma que Expedida. |
reg_previo_ggee | RegPrevioGGEEoREDEMEoCompetencia | Booleano. |
macrodata | Macrodato | Booleano. |
succession_party_* | EntidadSucedida | Igual que Expedida. |
billing_agreement_number | NumRegistroAcuerdoFacturacion | Igual que Expedida. |
external_reference | RefExterna | Igual que Expedida. |
Los dos flags exclusivos de Expedida (facturacion_disp_adicional_mercado_gas, sin_identif_destinatario_art_6_1_d) no aparecen en Recibida — el XSD de la AEAT los define solo en FacturaExpedidaType.
El wrapper XML de la AEAT es SuministroLRFacturasRecibidas.
Proveedores no españoles
Sección titulada «Proveedores no españoles»Cuando supplier_party_country no es es, el emisor se emite como IDOtro en lugar 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>El bloque Contraparte también se renderiza con IDOtro para que coincida.
Otros libros (Inversion, Intracomunitaria, Metalico, Seguro, Viajesagencia, Cobro, Pago)
Sección titulada «Otros libros (Inversion, Intracomunitaria, Metalico, Seguro, Viajesagencia, Cobro, Pago)»Los siete libros restantes cubren cada uno un requisito de información específico. Comparten los campos CTC comunes y el mismo ciclo de vida, pero llevan escalares específicos del libro. Consulta la referencia OpenAPI para la lista completa de campos.
Inversion (bienes de inversión)
Sección titulada «Inversion (bienes de inversión)»Registra la prorrata anual + la regularización de los bienes de inversión. Wrapper AEAT: SuministroLRBienesInversion. Campos obligatorios (además del wrapper CTC común):
identificacion_bien— identificador del bien (IdentificacionBien, máx. 40 caracteres)fecha_inicio_utilizacion— fecha en que el bien entró en uso (FechaInicioUtilizacion)prorrata_anual_definitiva— prorrata anual definitiva (ProrrataAnualDefinitiva, 0–100, 2 decimales)
Opcionales: regularizacion_anual_deduccion_in_cents, identificacion_entrega, regularizacion_deduccion_efectuada_in_cents, external_reference, billing_agreement_number, succession_party_*.
Intracomunitaria (operaciones intracomunitarias)
Sección titulada «Intracomunitaria (operaciones intracomunitarias)»Wrapper AEAT: SuministroLRDetOperacionIntracomunitaria. Obligatorios: clave_declarado (enum D o R), external_reference (por el XSD de la AEAT), más description mapeado a DescripcionBienes. Opcionales: plazo_operacion, facturas_o_documentacion.
Metalico / Seguro / Viajesagencia (agregados por período)
Sección titulada «Metalico / Seguro / Viajesagencia (agregados por período)»Estos libros se agregan por período: un solo registro representa el total de una contrapartida en un período fiscal. No hay invoice_number ni invoice_date — el XSD de la AEAT omite el bloque IDFactura. La contrapartida se facilita mediante customer_party_* (B2Brouter lo refleja en nombre_contraparte en el servidor).
- Metalico: wrapper
SuministroLRCobrosMetalico. Agrega los cobros en efectivo de una contrapartida ≥ 6.000 € en un período fiscal. - Seguro: wrapper
SuministroLROperacionesSeguros. Añade unClaveOperacionobligatorio mapeado desdeoperation_type. - Viajesagencia: wrapper
SuministroLRAgenciasViajes. Estructuralmente idéntico a Metalico según el XSD de la AEAT.
Cobro / Pago (seguimiento de pagos)
Sección titulada «Cobro / Pago (seguimiento de pagos)»Cobro: cobros recibidos de facturas emitidas. Pago: pagos realizados de facturas recibidas. Ambos llevan un array de pagos por registro en 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..." } ] }}(Usa pagos en lugar de cobros para Pago.)
No existen variantes A1 ni B para estos libros según el XSD de la AEAT — PATCH y DELETE devuelven 422.
Endpoint masivo (asíncrono)
Sección titulada «Endpoint masivo (asíncrono)»Para integraciones de alto volumen (agregaciones de punto de venta, migraciones CSV a JSON, etc.), usa POST /accounts/{ACCOUNT_ID}/tax_report_batches para enviar hasta 5.000 registros en una sola petición. El procesamiento es asíncrono: la llamada valida solo el wrapper y devuelve 202 Accepted con un id de lote; la construcción, validación y asignación al ledger de cada registro se ejecutan en un proceso en segundo plano. Luego debes consultar el endpoint de estado del lote (o confiar en el webhook tax_report.state_change por registro cuando la AEAT responda).
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", ... }, ... ] }'Respuesta aceptada (202):
{ "batch_id": 4567, "status": "processing", "total": 2, "status_url": "https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/tax_report_batches/4567"}Consulta el estado del lote en GET /accounts/{ACCOUNT_ID}/tax_report_batches/{BATCH_ID}. Mientras el proceso se ejecuta, status es "processing"; una vez finalizado es "done" y results se rellena, en orden de envío:
{ "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, ... } } ]}Semántica:
- Asíncrono: el
202significa únicamente que el lote ha sido aceptado para su procesamiento — no que se haya creado ningún registro. Consultastatus_urlhasta questatussea"done", o consume el webhooktax_report.state_changepara el resultado de la AEAT de cada registro creado. - Éxito parcial: cada registro se valida independientemente en el proceso. Un error en un registro (mal
book_type, XML inválido según XSD,typeno soportado) no aborta el lote — aparece comoerrorpor registro enresults. - Errores de wrapper (clave
tax_reportsausente, no es un array, más de 5.000 registros) devuelven HTTP400de forma síncrona, antes de que nada se encole. - Solo SII en v1: este endpoint acepta únicamente
type: "SiiDocument". Untypeno SII o ausente en cualquier registro se rechaza síncronamente con HTTP422(code: "unsupported_type") antes de que nada se encole — es un error de contrato de endpoint, distinto de los errores de datos SII por registro (malbook_type, XML inválido por XSD), que se notifican como errores parciales en el estado del lote. - Asignación a ledger + envío: los registros creados se asignan a ledgers SII segregados por modo agrupados por
(document_type_code, NIF de la empresa informadora)— es decir, por el Titular declarado en laCabecerade la AEAT, no por elsupplier_party_tax_idpor registro. Para Recibida/Pago ese campo contiene el proveedor externo, por lo que los registros de distintos proveedores comparten un ledger siempre que pertenezcan al mismo libro y empresa informadora. Los ledgers se envían a la AEAT por el cron por minutos (consulta la API de Ledgers) — nunca en el hilo de la petición.
Saber cuándo ha finalizado el lote
Sección titulada «Saber cuándo ha finalizado el lote»Dos opciones, usa una o ambas:
-
Polling a
status_urlhasta questatussea"done". -
Webhook — suscribe un webhook habilitado en tu grupo de integración al evento
sii_batch.finished. Cuando el proceso de ingesta finaliza, B2Brouter hace 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"}}El cuerpo del webhook contiene solo el resumen (acotado independientemente del tamaño del lote); llama a
GET status_urlpara los resultados completos por registro. El resultado de la AEAT de cada registro creado sigue llegando mediante su propio webhooktax_report.state_change.
API de Ledgers
Sección titulada «API de Ledgers»Los tax reports SII no se envían individualmente a la AEAT — se agrupan en “Libros de Registro” (Ledger en términos de B2Brouter), que contienen hasta 5.000 registros por libro / empresa informadora (Titular). Cada tax report tiene un campo ledger_id que apunta al ID interno del Ledger. Con ese ID puedes:
- Obtener la representación XML del Ledger mediante el endpoint de descarga del ledger. Este es el documento que B2Brouter envía a la AEAT.
- Obtener la respuesta XML de la AEAT a ese Ledger mediante el endpoint de descarga de la respuesta.
Los Ledgers SII modernos se vacían a la AEAT exclusivamente por el cron por minutos impulsado por la política Strategy::Sii (60 segundos entre envíos, o inmediatamente una vez que un Ledger alcanza los 5.000 registros). Ni POST /tax_reports, PATCH/DELETE, ni el endpoint masivo envían nunca a la AEAT en el hilo de la petición — asignan el/los registro/s y devuelven; el cron hace el envío. Prevé hasta ~60 s entre la creación y el envío.
Equivalencia entre los campos internos de tax report de B2Brouter y los nodos XML del SII
Sección titulada «Equivalencia entre los campos internos de tax report de B2Brouter y los nodos XML del SII»Expedida (SuministroLRFacturasEmitidas)
Sección titulada «Expedida (SuministroLRFacturasEmitidas)»| Campo de B2Brouter | Nodo XML de la 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 (se omite cuando es cero) |
Recibida (SuministroLRFacturasRecibidas)
Sección titulada «Recibida (SuministroLRFacturasRecibidas)»| Campo de B2Brouter | Nodo XML de la AEAT |
|---|---|
fiscal_year | PeriodoLiquidacion > Ejercicio |
fiscal_period | PeriodoLiquidacion > Periodo |
supplier_party_tax_id | IDFactura > IDEmisorFactura > NIF (o IDOtro > ID para no-ES) |
supplier_party_country | IDFactura > IDEmisorFactura > IDOtro > CodigoPais (solo no-ES) |
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 (se omite cuando es cero) |
fecha_contable | FacturaRecibida > FechaRegContable |
cuota_deducible_in_cents | FacturaRecibida > CuotaDeducible |
category del desglose fiscal → bucket de desglose
Sección titulada «category del desglose fiscal → bucket de desglose»Cada tax_breakdowns[*].category (el código de categoría de IVA estándar PEPPOL/UN-CEFACT) determina en qué bucket de desglose de la AEAT aterriza la línea. Esta es la señal canónica — envía la category correcta; los flags booleanos se derivan de ella.
Expedida (TipoDesglose > DesgloseFactura):
category | Bucket AEAT |
|---|---|
S, Z, H, AA, AAA, N1 (sujeto) | Sujeta > NoExenta, TipoNoExenta = S1 |
AE (inversión del sujeto pasivo) | Sujeta > NoExenta, TipoNoExenta = S2 |
E, K, N2.*, N3.2, N3.6, N4, N5, N7, IC (exento) | Sujeta > Exenta > DetalleExenta (CausaExencion ← exemption_code) |
NS, O, G, N3.1, N3.3–N3.5 (no sujeto) | NoSujeta (ImporteTAIReglasLocalizacion cuando no_subject_code = RL, si no ImportePorArticulos7_14_Otros) |
Una combinación de líneas S1 y S2 colapsa a un único TipoNoExenta = S3. Una línea sin categoría reconocida se renderiza como S1 (totalmente sujeta).
Recibida (DesgloseFactura): las líneas con inversión del sujeto pasivo (category AE) van a InversionSujetoPasivo; el resto a DesgloseIVA.
Aún no soportado:
DesgloseTipoOperacion(la división bienes/servicios que la AEAT requiere para algunas contrapartidas transfronterizas). Las facturas que lo necesiten deben usar la ruta CSV heredada hasta que una versión posterior añada el soporte — refleja el aplazamiento deDatosInmueblepara bienes inmuebles.
Archivos XSD
Sección titulada «Archivos XSD»La AEAT publica los XSD canónicos del SII. B2Brouter valida el XML generado contra SuministroInformacion.xsd y SuministroLR.xsd (v1.1) en cada envío. Los esquemas se encuentran en este repositorio en vendor/xsd-validator/lib/xsd/schemas/sii_v11/.
Descripción de los códigos para campos específicos
Sección titulada «Descripción de los códigos para campos específicos»book_type
Sección titulada «book_type»Los valores se listan en ¿Qué es el SII? más arriba. El book_type determina el wrapper XML de la AEAT, el conjunto de campos obligatorios y las reglas de validación.
invoice_type_code
Sección titulada «invoice_type_code»Para Expedida y 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)
Sección titulada «special_regime_key (ClaveRegimenEspecialOTrascendencia)»Un código de dos dígitos de la AEAT que describe el régimen especial aplicado a la operación. Los valores más comunes son 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). Consulta las especificaciones de la AEAT para la lista completa y la aplicabilidad por libro.
clave_declarado (solo Intracomunitaria)
Sección titulada «clave_declarado (solo Intracomunitaria)»D— DeclaranteR— Receptor
Comprobación de errores
Sección titulada «Comprobación de errores»B2Brouter valida los payloads SII contra los XSD de la AEAT antes de cualquier envío. Un error de validación devuelve HTTP 422 con los campos que fallan detallados en JSON. Si la AEAT rechaza un envío (p. ej. NIF de contrapartida desconocido), el rechazo se refleja en el state del registro (normalmente error o registered_with_errors) y en los campos error_code / error_description de la AEAT. Configura el webhook de tax report para reaccionar a los estados finales sin polling.