Importación
Cómo dar de alta muchas facturas a la vez por la API y cómo registrar facturas que ya existen en otro sistema o en XML.
| Qué quieres hacer | Operación | Formato | Facturas por petición |
|---|---|---|---|
| Crear borradores en bloque | POST /api/v1.1/drafts/batch | JSON json_1_1 | Varias |
| Registrar una emitida expedida fuera de Faxtal | POST /api/v1.1/issued-invoices/import | JSON json_1_1 | Una |
| Registrar emitidas expedidas fuera de Faxtal, en bloque | POST /api/v1.1/issued-invoices/import/batch | JSON json_1_1 | Varias |
| Registrar una recibida desde su XML | POST /api/v1.1/received-invoices/import | FacturaE, UBL o CII | Una |
- Los lotes solo aceptan JSON
json_1_1. La API no importa XML de facturas emitidas ni lotes de XML. - Toda factura se valida con las reglas del formato canónico.
- La importación desde Excel se hace en la aplicación, no por la API.
Importar una emitida
POST /api/v1.1/issued-invoices/import registra una factura que ya expediste fuera de Faxtal, tal como está. Sirve para cargar históricos o para migrar desde otro programa.
- Conserva el número y la fecha que envías: no asigna número de serie ni fecha.
- No genera registros VeriFactu.
- La factura queda con
status: "issued"desde el primer momento. - Los errores de validación no impiden registrarla. La respuesta los devuelve en
errors, ysuccessestrueigualmente. - Exige el permiso
invoices:issue.
Además del resto de la factura, envía estos campos:
| Campo | Descripción |
|---|---|
invoice.header.invoice_series_code | Serie de la factura |
invoice.header.invoice_number | Número tal como figura en la factura, con la serie incluida |
invoice.issue_data.issue_date | Fecha de expedición (YYYY-MM-DD). No puede ser futura. |
meta.external_ref | Opcional. Si falta, se usa el número de factura. |
{
"header": {
"invoice_series_code": "A",
"invoice_number": "A-15",
"invoice_type_code": "01"
},
"issue_data": {
"issue_date": "2026-03-10"
}
}
El resto de invoice sigue el formato canónico.
curl -s -X POST https://app.faxtal.com/api/v1.1/issued-invoices/import \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY" \
-H "Content-Type: application/json" \
-d @factura-A-15.json
Respuesta 201:
{
"success": true,
"id": "3f1c9a52-8e7b-4d1a-9c0e-2b6f4a7d8e91",
"errors": []
}
- Repetir la importación. La clave es el número, que ya incluye la serie. Si la envías otra vez, se actualiza la factura importada en lugar de crear otra. Si ese número lo tiene una factura de otra serie,
409coninvoice_update_not_allowed. Si ya está incluida en un modelo presentado,409. Si está anulada,409coninvoice_update_not_allowed. Si ya se envió al cliente, se corrige y sigue comosent. - Mismo número que una emitida desde Faxtal. La API responde
409coninvoice_update_not_allowed.
Lotes JSON
POST /api/v1.1/drafts/batch guarda borradores y POST /api/v1.1/issued-invoices/import/batch importa emitidas. Los dos reciben el mismo cuerpo:
{
"invoices": [
{
"schema_version": "json_1_1",
"meta": {
"source_system": "mi-erp",
"external_ref": "PEDIDO-2026-001"
},
"invoice": {}
},
{
"schema_version": "json_1_1",
"meta": {
"source_system": "mi-erp",
"external_ref": "PEDIDO-2026-002"
},
"invoice": {}
}
]
}
invoiceslleva al menos una factura, y cada elemento, su bloqueinvoice.- De
metasolo se usanexternal_refysource_system. La dirección la fija la operación: los dos lotes son de emitidas. - En
POST /drafts/batch, cada elemento necesitameta.external_refyinvoice.header.invoice_series_code, y no lleva número ni fecha. - En
POST /issued-invoices/import/batch, cada elemento sigue las reglas de Importar una emitida. - El lote se procesa entero antes de responder. Una factura con error no detiene a las demás.
- Si algún elemento trae campos que calcula la API, se rechaza el lote completo:
422coninferred_fields_not_allowedy, enitems, el índice y los campos de cada elemento. - Permisos:
invoices:writepara borradores einvoices:issuepara importar.
curl -s -X POST https://app.faxtal.com/api/v1.1/drafts/batch \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY" \
-H "Content-Type: application/json" \
-d @lote.json
Respuesta 200:
{
"batch_id": "66e6f0c2a1b2c3d4e5f60718",
"status": "completed_with_errors",
"total": 2,
"accepted": 1,
"rejected": 1,
"items": [
{
"index": 0,
"status": "accepted",
"id": "3f1c9a52-8e7b-4d1a-9c0e-2b6f4a7d8e91",
"number": null,
"errors": []
},
{
"index": 1,
"status": "rejected",
"id": null,
"number": null,
"errors": [
{
"code": "missing_required_fields",
"missing": ["invoice.header.invoice_series_code"]
}
]
}
]
}
| Campo | Descripción |
|---|---|
status | completed si todo se aceptó, completed_with_errors si hubo rechazos, failed si el lote no se pudo procesar |
total, accepted, rejected | Recuento de facturas |
items[].index | Posición de la factura en invoices, desde 0 |
items[].status | accepted o rejected |
items[].id | Identificador de la factura creada o actualizada |
items[].number | Número de factura, en importaciones |
items[].errors | Motivo del rechazo |
- Un borrador aceptado puede tener errores de validación que no aparecen en
items[].errors. Consúltalos conPOST /api/v1.1/drafts/{invoice_id}/validate. itemsdetalla como máximo 500 facturas. Si tu lote es mayor, divídelo.- Un lote cuenta como una sola petición en el límite de peticiones.
Importar una recibida desde XML
POST /api/v1.1/received-invoices/import registra una factura recibida a partir de su XML. Admite una factura por petición.
- El cuerpo es el XML tal cual, sin JSON ni formulario, con
Content-Type: application/xmlotext/xml. - El parámetro
formatindica el formato:facturae_3_2_2,facturae_3_2_1,facturae_3_2,ubl_2_1ocii_d16b. - El fichero puede ocupar hasta 10 MB.
- El XML se convierte al formato canónico y se valida. Cualquier error de validación impide registrarla.
- Exige el permiso
received:write.
curl -s -X POST "https://app.faxtal.com/api/v1.1/received-invoices/import?format=facturae_3_2_2" \
-H "X-API-Key: fctXXXXXXXX_YYYYYYYYYYYYYYYY" \
-H "Content-Type: application/xml" \
--data-binary @factura-proveedor.xml
Respuesta 201:
{
"success": true,
"id": "7d2e4b10-5a3c-4f8e-b1d6-0c9a8e7f6d54",
"errors": []
}
Para registrar una recibida que ya tienes en JSON, usa PUT /api/v1.1/received-invoices. Ver Facturas recibidas.
Errores
| Código | code | Cuándo |
|---|---|---|
400 | empty_body | Importación de XML sin cuerpo |
402 | quota_exceeded | La empresa ha agotado el cupo anual de facturas de su plan |
409 | invoice_update_not_allowed | La factura que corresponde a esa clave ya no admite cambios |
413 | payload_too_large | El XML supera los 10 MB |
415 | unsupported_media_type | El Content-Type del XML no es application/xml ni text/xml |
422 | inferred_fields_not_allowed | El payload trae campos que calcula la API |
422 | missing_required_fields | Falta la serie, el número, la fecha o meta.external_ref, según la operación |
422 | future_issue_date | Emitida importada con fecha futura |
422 | unsupported_invoice_source_transform | El formato indicado no se puede convertir |
422 | request_validation_error | format ausente o con un valor no admitido |
Ver también
- Formato canónico
- Conceptos: estados e idempotencia.
- Borradores
- Facturas emitidas
- Facturas recibidas