Documentación
Enviar facturas
El endpoint central de la API. Cada llamada crea un registro de facturación de alta conforme al RD 1007/2023: FactuBridge calcula la huella encadenada, genera el QR y remite el registro a la AEAT.
/v1/createPOST /v1/create
Authorization: Bearer $FACTUBRIDGE_API_KEY
Content-Type: application/json
{
"serie": "A",
"numero": "2026-0001",
"fecha_expedicion": "01-10-2026",
"tipo_factura": "F1",
"descripcion": "Servicios de consultoría — octubre 2026",
"nif": "B87654321",
"nombre": "CLIENTE EJEMPLO SL",
"lineas": [
{
"base_imponible": "1000.00",
"tipo_impositivo": "21.00",
"cuota_repercutida": "210.00"
},
{
"base_imponible": "500.00",
"tipo_impositivo": "10.00",
"cuota_repercutida": "50.00"
}
],
"importe_total": "1760.00"
}La respuesta es síncrona:
{
"uuid": "9b2e7c1a-4f6d-4c1e-9a3b-2f8e5d7c0a11",
"estado": "Pendiente",
"url": "https://www2.agenciatributaria.gob.es/wlpl/TIKE-CONT/ValidarQR?...",
"qr": "iVBORw0KGgoAAAANSUhEUgAA...",
"huella": "3AD5CA54A0DE383B0C1F79E1B2C4D6E8..."
}huella— hash SHA-256 encadenado con el registro anterior del mismo obligado. Es lo que hace la factura inmutable.qr— imagen PNG en Base64, lista para incrustar en el PDF o el ticket. El reglamento exige imprimirla entre 30×30 y 40×40 mm, al inicio de la factura.url— URL de cotejo de la AEAT codificada en el QR.estado—Pendiente: el registro está aceptado por FactuBridge y en cola de remisión. El resultado AEAT llega después (ver estados).
No esperes a la AEAT para entregar la factura. La norma permite emitir en el momento; la remisión del registro es responsabilidad del sistema (nuestra). Tu flujo de caja o de venta no depende de la latencia de la Agencia Tributaria.
Tipos de factura
| Código | Tipo | Destinatario |
|---|---|---|
F1 | Factura completa | Obligatorio (nombre + nif o id_otro) |
F2 | Simplificada (ticket), máx. 3.000 € | Prohibido |
F3 | Sustitución de simplificadas | Obligatorio |
R1–R4 | Rectificativas (art. 80 LIVA, error fundado, concurso, incobrables, resto) | Obligatorio |
R5 | Rectificativa de simplificada | Prohibido |
Para rectificar una simplificada (F2) usa siempreR5. Las rectificativas requieren tipo_rectificativa(I por diferencias, S por sustitución — esta última con importe_rectificativa) y la listafacturas_rectificadas:
{
"serie": "R",
"numero": "2026-0003",
"fecha_expedicion": "15-10-2026",
"tipo_factura": "R1",
"tipo_rectificativa": "I",
"facturas_rectificadas": [
{ "serie": "A", "numero": "2026-0001", "fecha_expedicion": "01-10-2026" }
],
"descripcion": "Rectificación por descuento no aplicado",
"nif": "B87654321",
"nombre": "CLIENTE EJEMPLO SL",
"lineas": [
{
"base_imponible": "-100.00",
"tipo_impositivo": "21.00",
"cuota_repercutida": "-21.00"
}
],
"importe_total": "-121.00"
}Líneas de detalle
Cada factura admite hasta 12 líneas; cada línea agrupa los importes con el mismo tipo impositivo. Campos principales:base_imponible, tipo_impositivo,cuota_repercutida; opcionales para casos especiales:operacion_exenta, clave_regimen,calificacion_operacion, recargo de equivalencia (tipo_recargo_equivalencia, cuota_recargo_equivalencia).
importe_total debe cuadrar con la suma de las líneas (tolerancia ±10 €, la misma que aplica la AEAT). Los importes se envían como cadenas decimales con dos decimales; las fechas aceptan DD-MM-YYYY oYYYY-MM-DD.
Envío en lote
/v1/create_bulkAcepta un array de facturas y las registra en orden, en una única transacción: todo o nada. Si una factura del lote es inválida, el lote completo se rechaza con 400 y ningún registro queda creado — la cadena de huellas nunca queda a medias.
POST /v1/create_bulk
Content-Type: application/json
[
{ "serie": "A", "numero": "2026-0002", ... },
{ "serie": "A", "numero": "2026-0003", ... }
]La respuesta devuelve resultados (uno por factura, en el mismo orden) y total. Es la vía recomendada para migraciones y para software que factura por tandas.
Duplicados y reintentos
La clave natural de un registro es serie + numero +fecha_expedicion por obligado. Reenviar la misma factura no crea un segundo registro: la API responde 409 Conflict incluyendo el registro ya existente (con su huella, su QR y su estado actual), de modo que reintentar una llamada que se cortó por red es seguro — adopta el registro devuelto como éxito y continúa.
Si prefieres un reintento sin lógica de 409, envía la cabecera opcional Idempotency-Key: el reintento con la misma clave y el mismo cuerpo devuelve directamente 200 con el estado actual del registro y la cabecera de respuesta Idempotent-Replayed: true. En /create_bulk la clave cubre el lote completo: el replay devuelve el array de respuestas íntegro, en el orden original y con el estado actual de cada registro. Por qué la protección no caduca nunca y cómo elegir una clave determinista:guía de idempotencia.