Facturas emitidas
Una factura emitida tiene número y fecha, y ya es definitiva. Lo normal es crearla como borrador y emitirla. La importación sirve para dar de alta facturas que ya emitiste con otro programa.
Todas las llamadas usan la URL base https://app.faxtal.com/api/v1.1 y la cabecera X-API-Key (ver Autenticación).
| Operación | Scope de la API key |
|---|---|
| Consultar, listar, validar, ver eventos, descargar documentos y PDF | invoices:read |
| Añadir y eliminar documentos | invoices:write |
| Emitir, importar, anular y eliminar importadas | invoices:issue |
Sin el scope necesario, la API responde 403 con el código scope_missing.
Estados
status | Significado |
|---|---|
draft | Borrador. Ver Borradores. |
issued | Emitida. |
sent | Emitida y enviada por email. Ver Envío por email. |
cancelled | Anulada. |
queued | Reservada por una emisión en bloque iniciada desde la aplicación. |
Emitir un borrador
POST /api/v1.1/issued-invoices/{invoice_id}/issue
El borrador lo creas antes con PUT /api/v1.1/drafts. El cuerpo es opcional:
| Campo | Descripción |
|---|---|
invoice_number | Número con el que se emite, si lo numera tu programa. Máximo 60 caracteres. Sin él, se asigna el siguiente número de la serie. Ver Emitir con el número de tu programa. |
Sin cuerpo:
curl -X POST "https://app.faxtal.com/api/v1.1/issued-invoices/00000000-0000-0000-0000-000000000001/issue" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY"
Qué hace la emisión:
- Comprueba que la empresa esté verificada.
- Valida el borrador. Si tiene errores, no emite y el borrador sigue en
draft. - Asigna la fecha del día y el número: el siguiente de la serie o el
invoice_numberque envías. El número sigue la plantilla de la serie y ya incluye su código: no concatenesseriesynumber. - Si tienes VeriFactu activo, genera el registro de alta y el QR. Si ese paso no valida, no emite. El envío a la AEAT se hace después, en segundo plano.
- Si tienes el SII activo, deja la factura pendiente de envío.
El estado de los envíos fiscales se consulta en Cumplimiento.
:::info Aún no disponible TicketBAI todavía no está disponible, así que la emisión no firma ni envía facturas a las haciendas forales. :::
Respuesta 200, resumida:
{
"id": "00000000-0000-0000-0000-000000000001",
"direction": "issued",
"status": "issued",
"series": "A",
"number": "A-1",
"issue_date": "2026-11-02",
"external_id": "PEDIDO-2026-001",
"supplier_tax_id": "B10000008",
"customer_tax_id": "B10000016",
"currency": "EUR",
"total_base": 1000.0,
"total_tax": 210.0,
"total": 1210.0
}
La API no emite en bloque: emite cada borrador con su llamada.
Emitir con el número de tu programa
Si tu programa ya numera las facturas, envía su número en invoice_number:
curl -X POST "https://app.faxtal.com/api/v1.1/issued-invoices/00000000-0000-0000-0000-000000000001/issue" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY" \
-H "Content-Type: application/json" \
-d '{"invoice_number": "A-0042"}'
- Envía el número completo, con la serie, tal como figura en la factura.
- Tiene que encajar con la plantilla de la serie del borrador: con el código, el prefijo y los ceros a la izquierda que usa esa serie. Si no encaja,
422conforced_number_invalid. - No puede tenerlo otra factura, de esa serie o de otra. Si lo tiene,
409conforced_number_in_use. - El borrador se valida antes de usar el número. Si tiene errores, el número no se usa y puedes volver a enviarlo cuando los corrijas.
- Si el número va por delante del contador de la serie, el contador avanza hasta él: la siguiente emisión sin
invoice_numbercontinúa desde ahí.
:::warning
La API no comprueba que la numeración sea correlativa. La numeración de una serie tiene que serlo (artículo 6.1.a del Reglamento de facturación, Real Decreto 1619/2012), y con invoice_number esa responsabilidad es tuya: no dejes huecos ni emitas números fuera de orden.
:::
Errores
| HTTP | code | Causa |
|---|---|---|
404 | invoice_not_found | La factura no existe o no es una emitida de tu empresa. |
409 | invalid_status_transition | La factura no es un borrador. El detalle trae from y to. |
409 | invoice_queued_for_bulk_issue | La factura está reservada por una emisión en bloque. |
409 | bulk_issue_series_active | Hay una emisión en bloque en curso en esa serie. |
409 | company_not_verified | La empresa no está verificada. |
409 | forced_number_in_use | El invoice_number ya lo tiene otra factura, de esa serie o de otra. |
409 | invoice_number_already_assigned | Un intento de emisión anterior ya asignó otro número al borrador. El detalle trae number. |
422 | validation_failed | El borrador no pasa la validación o la de VeriFactu. El detalle trae errors. |
422 | missing_emission_fields | Falta la serie. El detalle trae missing. |
422 | forced_number_invalid | El invoice_number no encaja con la plantilla de la serie. |
422 | request_validation_error | El cuerpo no es válido: invoice_number vacío, de más de 60 caracteres o con campos que no existen. |
Importar facturas emitidas en otro programa
POST /api/v1.1/issued-invoices/import
:::warning Una factura importada queda marcada como emitida fuera de la plataforma. No pasa por la emisión: no genera registro VeriFactu y no queda pendiente de envío al SII. Úsala para migrar históricos. Para facturar, crea un borrador y emítelo. :::
Qué enviar, además del formato canónico:
header.invoice_series_code,header.invoice_numbereissue_data.issue_date. Son obligatorios, y la fecha no puede ser futura.header.invoice_numbertal como figura en la factura.supplier.tax_id: obligatorio, y tiene que ser el NIF de tu empresa.meta.external_refes opcional. Si falta, se usa el número de factura.- No envíes los campos que deduce el sistema (ver Borradores).
{
"schema_version": "json_1_1",
"meta": {
"direction": "issued",
"source_system": "programa-anterior"
},
"invoice": {
"supplier": {
"person_type_code": "J",
"tax_id": "B10000008",
"name": "Empresa Demo S.L."
},
"customer": {
"person_type_code": "J",
"tax_id": "B10000016",
"name": "Cliente Prueba S.L."
},
"header": {
"invoice_series_code": "F",
"invoice_number": "F-2025-0042",
"invoice_type_code": "01"
},
"issue_data": {
"issue_date": "2025-12-15",
"tax_currency_code": "EUR"
},
"totals": {
"total_gross_amount_before_taxes": 500.0,
"total_tax_outputs": 105.0,
"invoice_total": 605.0
},
"lines": [
{
"item_description": "Mantenimiento diciembre",
"quantity": 1,
"unit_price_without_tax": 500.0,
"tax_treatment_code": "TAXABLE_NON_EXEMPT",
"tax_output_rate": 21.0
}
]
}
}
curl -X POST "https://app.faxtal.com/api/v1.1/issued-invoices/import" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY" \
-H "Content-Type: application/json" \
-d @importada.json
Respuesta 201:
{
"success": true,
"id": "00000000-0000-0000-0000-000000000002",
"errors": []
}
Cómo funciona:
- La factura queda en estado
issuedy su histórico muestra el eventoimported. - La validación no bloquea: la factura se guarda aunque tenga errores, que recibes en
errors.successestruetambién en ese caso, así que revisa siempreerrors. - Si ya existe una factura con el mismo número (el número incluye la serie): si es otra importada, se actualiza (una ya enviada sigue como
sent); si la emitió la plataforma, la importada está anulada o es de otra serie, responde409invoice_update_not_allowed. - Una importada que ya consta en un modelo presentado no admite cambios en sus datos fiscales.
Errores
| HTTP | code | Causa |
|---|---|---|
422 | missing_required_fields | Falta la serie, el número o la fecha. El detalle trae missing. |
422 | future_issue_date | La fecha de expedición es futura. |
422 | issuer_tax_id_required | Falta supplier.tax_id. |
422 | issuer_tax_id_mismatch | supplier.tax_id no es el NIF de tu empresa. |
422 | inferred_fields_not_allowed | Has enviado campos que deduce el sistema. |
409 | invoice_update_not_allowed | Ese número ya lo tiene una factura emitida por la plataforma, o una importada anulada. |
409 | issued_invoice_fiscally_locked | La importada ya consta en un modelo presentado. El detalle trae reasons y locked_fields_changed. |
Importar en bloque
POST /api/v1.1/issued-invoices/import/batch
El cuerpo es el mismo que el de los borradores en bloque: un objeto con invoices, y cada elemento con su invoice completa (serie, número y fecha incluidos).
curl -X POST "https://app.faxtal.com/api/v1.1/issued-invoices/import/batch" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY" \
-H "Content-Type: application/json" \
-d @lote-historico.json
- La llamada espera a que termine todo el lote.
- Cada factura va por separado: si una se rechaza, las demás se importan igual. Las de una misma serie se procesan en orden.
- La respuesta tiene la misma forma que en borradores (
batch_id,status,total,accepted,rejected,items), yitems[].numbertrae el número importado. - La respuesta detalla como máximo 500 facturas. Envía lotes de 500 o menos.
Anular una factura
POST /api/v1.1/issued-invoices/{invoice_id}/cancel
Sin cuerpo.
curl -X POST "https://app.faxtal.com/api/v1.1/issued-invoices/00000000-0000-0000-0000-000000000001/cancel" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY"
- Admite facturas en
issuedosent. En otro estado responde409invalid_status_transition. - La factura pasa a
cancelledy la respuesta200la devuelve con la forma de la consulta. - Si era una rectificativa, la original deja de figurar como rectificada por ella.
- Los cobros asociados a la factura se anulan.
:::warning La comunicación fiscal de la anulación tiene limitaciones conocidas:
- Solo se intenta si la factura estaba en
issued. Si estaba ensent, hoy no se comunica ninguna anulación. - El registro fiscal de la anulación no está garantizado: si falla, la factura queda anulada igualmente. Comprueba el resultado en Cumplimiento.
- Con el SII activo, la anulación queda pendiente como modificación, no como baja.
- No anules una factura importada: no tiene registro de alta. Si hay que retirarla, elimínala.
- No repitas la llamada: si no sabes si se aplicó, consulta antes el estado de la factura. :::
Para corregir una factura emitida, emite una rectificativa.
Emitir una rectificativa
No hay una operación propia: una rectificativa es un borrador con tipo rectificativo que emites como cualquier otro.
- Crea el borrador con
PUT /api/v1.1/drafts. Usaheader.invoice_type_code03(rectificativa) o04(rectificativa simplificada) y añade el bloqueheader.corrective. - Emítelo con
POST /api/v1.1/issued-invoices/{invoice_id}/issue.
Campo de header.corrective | Obligatorio | Descripción |
|---|---|---|
invoice_number | Sí | Número de la factura rectificada. Ya incluye la serie. |
invoice_issue_date | Sí | Fecha de expedición de la factura rectificada (YYYY-MM-DD). |
reason_code | Sí | Motivo de la rectificación: código de dos dígitos del catálogo (01 a 25). |
correction_type | Sí | S (por sustitución) o D (por diferencias). |
corrected_taxable_base, corrected_tax_amount | Con S | Base y cuota rectificadas de la factura original. |
reason_description | No | Texto del motivo. |
tax_period.start_date, tax_period.end_date | No | Periodo de la factura rectificada. |
"header": {
"invoice_series_code": "R",
"invoice_type_code": "03",
"corrective": {
"invoice_number": "A-1",
"invoice_issue_date": "2026-11-02",
"reason_code": "01",
"correction_type": "D"
}
}
Si falta un dato, el borrador se guarda con errores y no se puede emitir. Los códigos son corrective_reason_required, corrective_reason_unknown, corrective_invoice_number_required, corrective_invoice_issue_date_required, corrective_correction_type_required y corrective_substitution_amounts_required.
Al consultar una factura, corrections muestra la relación:
corrects: la factura a la que rectifica (correction_type,reason_code,corrected_series,corrected_number,corrected_issue_date,match_status).corrected_invoice_idesnullsi la original no está en la plataforma.corrected_by: las rectificativas que la corrigen (invoice_id,series,number,issue_date,correction_type).
Consultar y listar
Una factura
GET /api/v1.1/issued-invoices/{invoice_id}
curl "https://app.faxtal.com/api/v1.1/issued-invoices/00000000-0000-0000-0000-000000000001" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY"
| Campo | Descripción |
|---|---|
id | Identificador de la factura. |
direction | issued. |
status | Estado (ver la tabla del principio). |
series, number | Serie y número. El número ya incluye la serie. |
issue_date | Fecha de expedición. |
external_id | Tu meta.external_ref. |
supplier_tax_id, supplier_name | Emisor. |
customer_tax_id, customer_name | Cliente. |
currency | Divisa. |
total_base, total_tax, total | Base imponible, cuota y total. |
created_at, updated_at | Fechas de alta y de última modificación. |
corrections | Relación con rectificativas, o null. |
fiscal | Estado fiscal: qr_url, legend y status. Solo en esta ficha y solo si la factura está emitida, enviada o anulada; en los listados va a null. |
fiscal es lo que necesitas para imprimir la factura por tu cuenta: el QR y la leyenda que exige VeriFactu (o TicketBAI, si la empresa opera en territorio foral). status refleja el registro fiscal (verifactu_accepted, verifactu_pending, not_registered…).
El canónico
GET /api/v1.1/issued-invoices/{invoice_id}/canonical
Devuelve el JSON canónico tal y como lo guardó Faxtal: normalizado y con los campos que el sistema infiere (clasificación fiscal, taxable, exempt, is_simplified…). Es lo que se declara a Hacienda, y lleva las líneas y los impuestos que la ficha resumida no trae.
curl "https://app.faxtal.com/api/v1.1/issued-invoices/00000000-0000-0000-0000-000000000001/canonical" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY"
:::warning No se reenvía tal cual
La respuesta no vale como cuerpo de PUT /api/v1.1/drafts: ese endpoint rechaza los campos inferidos con 422 inferred_fields_not_allowed. Úsalo para leer y para conciliar, no para reeditar.
:::
Si la factura no tiene canónico guardado, responde 409 canonical_not_available.
La lista
GET /api/v1.1/issued-invoices
| Parámetro | Descripción |
|---|---|
status | draft, issued, sent, cancelled o queued. Sin él, incluye también los borradores. |
series | Código de serie. |
customer_tax_id | NIF del cliente. |
number | Número de factura exacto. Sirve para recuperar una factura cuyo id has perdido. |
external_ref | Tu referencia (meta.external_ref), exacta. |
issue_date_from, issue_date_to | Rango de fecha de expedición (YYYY-MM-DD). |
limit | De 1 a 500. Por defecto, 50. |
offset | Desplazamiento. Por defecto, 0. |
curl -G "https://app.faxtal.com/api/v1.1/issued-invoices" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY" \
-d status=issued -d issue_date_from=2026-11-01 -d issue_date_to=2026-11-30
Respuesta 200: items, total, limit y offset. Los resultados salen ordenados por serie y, dentro de cada serie, de la fecha más reciente a la más antigua. Un status desconocido responde 400 unknown_status.
Validar un JSON sin guardarlo
POST /api/v1.1/issued-invoices/validate funciona igual que la validación de borradores.
Eliminar una factura importada
DELETE /api/v1.1/issued-invoices/{invoice_id}
curl -X DELETE "https://app.faxtal.com/api/v1.1/issued-invoices/00000000-0000-0000-0000-000000000002" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY"
Respuesta 204, sin cuerpo. Solo se pueden eliminar facturas importadas. Con cualquier otra, responde 409 invoice_delete_not_allowed. También responde 409 si la importada ya consta en un modelo presentado, y entonces el detalle trae reasons.
Ver el histórico
GET /api/v1.1/issued-invoices/{invoice_id}/events
curl "https://app.faxtal.com/api/v1.1/issued-invoices/00000000-0000-0000-0000-000000000001/events" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY"
Respuesta 200, resumida:
[
{
"event_type": "state_transition",
"event_code": "issued",
"occurred_at": "2026-11-02T09:20:00",
"actor": { "user_id": null, "api_key_id": 42 },
"from_status": "VALIDATED",
"to_status": "ISSUED",
"details": { "issue_date": "2026-11-02" }
}
]
Algunos event_code: issued (o imported en una importada), sent, cancelled, document_added y document_deleted. from_status y to_status usan los nombres de estado internos, en mayúsculas.
Documentos adjuntos
| Operación | Ruta | Scope |
|---|---|---|
| Listar | GET /api/v1.1/issued-invoices/{invoice_id}/documents | invoices:read |
| Añadir | POST /api/v1.1/issued-invoices/{invoice_id}/documents | invoices:write |
| Descargar | GET /api/v1.1/issued-invoices/{invoice_id}/documents/{doc_id} | invoices:read |
| Eliminar | DELETE /api/v1.1/issued-invoices/{invoice_id}/documents/{doc_id} | invoices:write |
Para añadir, envía el fichero como multipart/form-data en el campo file:
curl -X POST "https://app.faxtal.com/api/v1.1/issued-invoices/00000000-0000-0000-0000-000000000001/documents" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY" \
-F "file=@albaran.pdf;type=application/pdf"
Respuesta 201:
{
"public_id": "00000000-0000-0000-0000-0000000000d1",
"doc_type": "pdf_render",
"file_name": "albaran.pdf",
"content_type": "application/pdf",
"metadata": null,
"created_at": "2026-11-02T09:30:00"
}
public_ides eldoc_idpara descargar o eliminar.doc_typesale del tipo de contenido:pdf_renderpara un PDF,xml_facturaepara un XML yattachmentpara el resto.- El fichero puede ocupar hasta 16 MB (
413file_too_large) y no puede estar vacío (422empty_file). - Descargar devuelve el fichero con su nombre. Un
doc_idque no existe responde404document_not_found. - Eliminar responde
204.
Descargar el PDF
GET /api/v1.1/issued-invoices/{invoice_id}/pdf
curl "https://app.faxtal.com/api/v1.1/issued-invoices/00000000-0000-0000-0000-000000000001/pdf" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY" \
-o factura.pdf
Devuelve application/pdf. Si la factura tiene registro VeriFactu, el PDF lleva su QR.
El parámetro template elige una plantilla general como <diseño>-<estilo> (por ejemplo, clasica-corporativo; la lista está en Formatos). Sin él, o con otro valor, se usa la plantilla de la serie de la factura o, si no tiene, la de la empresa.
Exportar y enviar por email
- Exportar a FacturaE, UBL o CII:
GET /api/v1.1/issued-invoices/{invoice_id}/export?format=.... Solo facturas enissuedosent. Las facturas con retención de IRPF no se exportan a UBL ni a CII: usa FacturaE. Ver Formatos. - Enviar por email:
POST /api/v1.1/issued-invoices/{invoice_id}/send. Ver Envío por email.
Ver también
- Borradores: crear y validar antes de emitir.
- Formato canónico: todos los campos de
json_1_1. - Cumplimiento: estado de VeriFactu y SII.
- Errores: formato común de las respuestas de error.
- Referencia interactiva.
Autenticación y seguridad
Cabecera `X-API-Key`, formato y ciclo de vida de la clave, permisos, restricción por IP, límites de uso y buenas prácticas.
Facturas recibidas
Registrar facturas de proveedores con JSON canónico o XML, reconocerlas desde un PDF o una imagen, validarlas, consultarlas y gestionar sus documentos.