Faxtal

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 hacerOperaciónFormatoFacturas por petición
Crear borradores en bloquePOST /api/v1.1/drafts/batchJSON json_1_1Varias
Registrar una emitida expedida fuera de FaxtalPOST /api/v1.1/issued-invoices/importJSON json_1_1Una
Registrar emitidas expedidas fuera de Faxtal, en bloquePOST /api/v1.1/issued-invoices/import/batchJSON json_1_1Varias
Registrar una recibida desde su XMLPOST /api/v1.1/received-invoices/importFacturaE, UBL o CIIUna
  • 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, y success es true igualmente.
  • Exige el permiso invoices:issue.

Además del resto de la factura, envía estos campos:

CampoDescripción
invoice.header.invoice_series_codeSerie de la factura
invoice.header.invoice_numberNúmero tal como figura en la factura, con la serie incluida
invoice.issue_data.issue_dateFecha de expedición (YYYY-MM-DD). No puede ser futura.
meta.external_refOpcional. 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, 409 con invoice_update_not_allowed. Si ya está incluida en un modelo presentado, 409. Si está anulada, 409 con invoice_update_not_allowed. Si ya se envió al cliente, se corrige y sigue como sent.
  • Mismo número que una emitida desde Faxtal. La API responde 409 con invoice_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": {}
    }
  ]
}
  • invoices lleva al menos una factura, y cada elemento, su bloque invoice.
  • De meta solo se usan external_ref y source_system. La dirección la fija la operación: los dos lotes son de emitidas.
  • En POST /drafts/batch, cada elemento necesita meta.external_ref y invoice.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: 422 con inferred_fields_not_allowed y, en items, el índice y los campos de cada elemento.
  • Permisos: invoices:write para borradores e invoices:issue para 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"]
        }
      ]
    }
  ]
}
CampoDescripción
statuscompleted si todo se aceptó, completed_with_errors si hubo rechazos, failed si el lote no se pudo procesar
total, accepted, rejectedRecuento de facturas
items[].indexPosición de la factura en invoices, desde 0
items[].statusaccepted o rejected
items[].idIdentificador de la factura creada o actualizada
items[].numberNúmero de factura, en importaciones
items[].errorsMotivo del rechazo
  • Un borrador aceptado puede tener errores de validación que no aparecen en items[].errors. Consúltalos con POST /api/v1.1/drafts/{invoice_id}/validate.
  • items detalla 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/xml o text/xml.
  • El parámetro format indica el formato: facturae_3_2_2, facturae_3_2_1, facturae_3_2, ubl_2_1 o cii_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ódigocodeCuándo
400empty_bodyImportación de XML sin cuerpo
402quota_exceededLa empresa ha agotado el cupo anual de facturas de su plan
409invoice_update_not_allowedLa factura que corresponde a esa clave ya no admite cambios
413payload_too_largeEl XML supera los 10 MB
415unsupported_media_typeEl Content-Type del XML no es application/xml ni text/xml
422inferred_fields_not_allowedEl payload trae campos que calcula la API
422missing_required_fieldsFalta la serie, el número, la fecha o meta.external_ref, según la operación
422future_issue_dateEmitida importada con fecha futura
422unsupported_invoice_source_transformEl formato indicado no se puede convertir
422request_validation_errorformat ausente o con un valor no admitido

Ver también

On this page