Documentación de la API
Referencia de inicio rápido. Ejemplos de cada endpoint — sin entrar en el detalle interno.
Authorization: Bearer eck_live_xxxxxxxxxxxx Content-Type: application/jsonBase URL única:
https://api.apifactu.es. El entorno lo decide la clave: eck_live_ factura de verdad, eck_test_ usa el entorno de pruebas sin efecto fiscal.
Guías por plataforma
Si tu tienda está en una de estas plataformas no necesitas programar: instala el plugin y pega tu clave. Si integras desde tu propio código, usa una de las librerías o la API REST de más abajo.
apifactu · disponible
JavaScript / TypeScriptLibrería @apifactu/sdk · disponible
MagentoExtensión · próximamente
OpenCartExtensión · próximamente
OdooMódulo · próximamente
Emitir una factura
Crea y envía una factura a Verifactu/TicketBai. Idempotente con X-Idempotency-Key.
# Petición POST /v1/invoices X-Idempotency-Key: WOO-1042 { "referencia": "WOO-1042", "serie": "A", "tipo_factura": "F1", "base_imponible": 100.00, "tipo_iva": 21, "nif_receptor": "12345678Z", "nombre_receptor": "Cliente SL" } # Respuesta 202 { "id": "d4e1…", "status": "QUEUED", "numero_completo": "A-2026-0042", "total": "121.00", "qr_url": "https://…", "huella": "2B8BD34D…", "fiscal_invoice_id": "8f3a1c…" }
Guarda el id: es el que necesitan anular y rectificar. Al repetir la
misma petición se devuelve exactamente esta respuesta, con "idempotent": true.
Consultar facturas
Listado paginado con filtros (status, serie, fecha_desde, fecha_hasta, receptor_nif).
# Petición GET /v1/invoices?status=ACCEPTED&page=1&per_page=20 # Respuesta 200 { "data": [ { "id": "…", "numero_completo": "A-2026-0042", "status": "ACCEPTED", "total": "121.00", "qr_url": "https://…", "aeat_csv": "AEAT-…" } ], "pagination": { "page": 1, "per_page": 20, "total": 87, "pages": 5 } }
Conteos por estado y totalizaciones: importe facturado, anulado y rechazado, por serie y por mes. Acotable con fecha_desde, fecha_hasta (fecha de expedición) y serie: lo que necesita un cierre de caja o de trimestre.
# Petición GET /v1/invoices/stats?fecha_desde=2026-01-01&fecha_hasta=2026-03-31 # Respuesta 200 { "total": 87, "accepted": 80, "rejected": 2, "cancelled": 5, "totales": { "facturas_validas": 80, "importe_facturado": "9640.20", "facturas_anuladas": 5, "importe_anulado": "412.00", "facturas_rechazadas": 2, "importe_rechazado": "99.00" }, "por_serie": [ { "serie": "A", "facturas": 85, "importe_facturado": "9640.20", "importe_anulado": "412.00" } ], "por_mes": [ { "mes": "2026-01", "facturas": 30, "importe_facturado": "3100.00", "importe_anulado": "0.00" }, … ] }
Detalle de una factura: estado fiscal, QR, hash y CSV de la AEAT. En TicketBAI incluye además identificador_tbai (el código TBAI-… que debe imprimirse en texto en la factura) y qr_legend (la leyenda que acompaña al QR).
# Respuesta 200
{ "id": "…", "numero_completo": "A-2026-0042", "status": "ACCEPTED",
"qr_url": "https://www.agenciatributaria.es/…", "aeat_csv": "AEAT-…",
"huella": "A3F2…" }
Imagen PNG del QR de verificación fiscal, lista para imprimir o incrustar.
# Respuesta 200 Content-Type: image/png (binario)
Anular y rectificar
Anula una factura: genera el registro de anulación y lo remite a Hacienda. Si la factura todavía no se había enviado, se cancela sin registro.
# Petición { "motivo": "pedido cancelado" } # Respuesta 202 { "id": "…", "status": "CANCELLATION_PENDING", "submission_status": "CANCELLATION_PENDING" }
Emite una factura rectificativa sobre {id}: S sustituye la original, I rectifica por diferencias (importes negativos para devoluciones). Con varios tipos de IVA, indica lineas.
# Petición { "tipo_rectificativa": "I", "amount": -20.00, "motivo": "devolución parcial" } # Respuesta 202 { "id": "…", "numero_completo": "R-2026-0007", "tipo_rectificativa": "I", "rectifies_numero_completo": "A-2026-0042", "status": "QUEUED" }
Corregir ante la Hacienda Foral de Gipuzkoa (Zuzendu y Osatu)
Solo para facturas bajo TicketBAI Gipuzkoa. La Diputación no admite reenviar un fichero rechazado por el servicio de alta: se corrige por el servicio Zuzendu (Orden Foral 16/2022). Fuera de Gipuzkoa estos endpoints responden 409.
SUBSANAR una factura REJECTED (pasa a ACCEPTED si la Diputación la recibe) o MODIFICAR una ACCEPTED con datos erróneos que no exijan rectificativa. Se pueden corregir descripcion, nif_receptor, nombre_receptor, direccion_receptor y codigo_postal_receptor; los importes y la numeración, no. Respuesta síncrona.
# Petición { "accion": "SUBSANAR", "correcciones": { "direccion_receptor": "Kale Nagusia 1", "codigo_postal_receptor": "20001" } } # Respuesta 200 { "id": "…", "status": "ACCEPTED", "submission_status": "ACCEPTED", "zuzendu": { "servicio": "ZUZENDU_ALTA", "accion": "SUBSANAR", "estado": "RECIBIDO", "codigo": null, "descripcion": null, "csv": "TBAI-…" } }
estado: RECIBIDO, RECIBIDO_CON_ERRORES (avisos de consolidación en codigo/descripcion), RECHAZADO o ERROR (no hubo respuesta: reintenta).
Subsana un fichero de anulación rechazado (factura en CANCELLATION_REJECTED). Si la Diputación lo recibe, la factura pasa a CANCELLED. Sin cuerpo.
Complementa una factura ACCEPTED con otros datos tributarios que el fichero de alta no lleva: referencia_externa, inmuebles[] (situacion 1-4, referencia_catastral), importe_transmision_inmuebles_sujeto_iva, nif_representante, nif_representante_contraparte, num_registro_acuerdo_facturacion, entidad_sucedida (nif, nombre), cupon, hidrocarburos_extraidos_deposito.
# Petición
{ "otros_datos_tributarios": { "inmuebles": [ { "situacion": "2", "referencia_catastral": "…" } ] } }
Histórico de envíos Zuzendu y Osatu de la factura. disponible es false fuera de Gipuzkoa.
KONTSULTA: lo que la Diputación tiene registrado del emisor (solo lectura). ejercicio, periodo (01…12, 1T…4T, 0A) y un filtro opcional por serie, número, fechas de expedición/operación/presentación, estado_envio (3 aceptado, 2 con errores), estado_registro (C correcto, A anulada, R rechazada, M modificada, Z rectificada), mostrar_errores y pagina.
# Petición { "ejercicio": 2026, "periodo": "1T", "filtro": { "estado_registro": "C", "pagina": 1 } } # Respuesta 200 { "resultado": { "existen_registros": true, "registros_totales": 42, "paginas_totales": 1, "error": null }, "facturas": [ { "serie": "A-2026", "numero": "7", "fecha_hora_expedicion": "15-02-2026 10:12:03", "importe_total": "121.00", "identificador_tbai": "TBAI-…", "estado": "C", "errores": { "ticketbai": [], "sii": [] } } ] }
Última factura del emisor registrada en Gipuzkoa (ultima_factura), útil para comprobar el encadenamiento tras una incidencia.
Todas estas operaciones están también en el panel del comerciante (Actividad → detalle de la factura y «Consulta en la Diputación»), que usa esta misma API.
Webhooks
Registra una URL para recibir el estado fiscal. Cada entrega va firmada con HMAC-SHA256 en X-Fiscal-Signature.
# Petición POST /v1/webhooks { "url": "https://mitienda.es/webhook", "events": ["invoice.accepted", "invoice.rejected"] } # Evento entregado { "event": "invoice.accepted", "numero_completo": "A-2026-0042", "submission_status": "ACCEPTED", "qr_url": "https://…", "aeat_csv": "AEAT-…" }
API keys
Lista tus API keys (prefijo enmascarado; el secreto solo se muestra al crearlas).
# Respuesta 200
[ { "id": "…", "key_prefix": "eck_live_a1…", "environment": "live", "is_active": true } ]
Errores y reintentos
| Código | Significado | Acción del cliente |
|---|---|---|
| 202 | Aceptada y encolada | Espera el webhook de confirmación |
| 422 | Validación (p.ej. tipo de IVA inválido) | Corrige el payload — no reintentes |
| 429 | Límite de tasa | Reintenta respetando Retry-After |
| 5xx | Error transitorio | Reintenta con backoff exponencial |
Las librerías oficiales de Python y JavaScript/TypeScript gestionan los reintentos y la idempotencia por ti.