Factuarea API

Exportación e importación

Exporta facturas a una hoja de cálculo Excel/CSV (SUMMARY o ITEMS, con tope de 5000) e importa clientes desde un CSV con previsualización dry-run, mapeo de columnas, plantilla descargable y partial-success.

La API pública mueve datos dentro y fuera de Factuarea con dos operaciones basadas en fichero: exportar facturas a una hoja de cálculo e importar clientes desde un CSV. Ambas reutilizan los mismos motores que el panel, y la importación sigue el contrato partial-success: una fila errónea nunca hunde el fichero entero.

Exportar facturas a una hoja de cálculo

POST /v1/invoices/export/excel (scope invoices:read) genera una hoja XLSX o CSV de tus facturas y devuelve el fichero binario. Es una operación de lectura: no crea ni modifica nada.

Dos ejes ortogonales controlan la salida:

ParámetroValoresSignificado
formatSUMMARY (por defecto) · ITEMSLayout de contenido. SUMMARY es una fila por factura; ITEMS es una fila por línea de factura (las columnas de cabecera se repiten en cada línea).
file_formatxlsx (por defecto) · csvFormato de fichero.

Elige las facturas a exportar de dos maneras:

  • Por id — pasa invoice_ids con los ids UUID v7 de facturas concretas.
  • Por filtro — omite invoice_ids y acota el conjunto con status, date_from, date_to, client_id, series_id y search. date_from y date_to filtran por fecha de emisión (ambas incluidas); client_id y series_id toman el UUID v7 público del cliente/serie.
curl -s -X POST https://api.factuarea.com/v1/invoices/export/excel \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "format": "ITEMS",
    "file_format": "xlsx",
    "status": "paid",
    "date_from": "2026-01-01",
    "date_to": "2026-03-31"
  }' \
  -o facturas-t1.xlsx

El tope de 5000 facturas

El conjunto seleccionado tiene un tope de 5000 facturas. Si tus filtros casan con más, la API no trunca de forma silenciosa: devuelve 422 con el código de error export_limit_exceeded:

{
  "error": {
    "type": "invalid_request_error",
    "code": "export_limit_exceeded",
    "message": "La exportación supera el máximo de 5000 facturas."
  }
}

Acota el rango de fechas, el estado o el cliente, o divide la exportación en varias llamadas, para que cada petición quede por debajo del tope.

client_id, series_id y las entradas de invoice_ids se resuelven dentro de tu empresa. Un UUID inexistente o de otra empresa simplemente se descarta de la selección: nunca filtra datos entre empresas ni devuelve un 404 global.

Importar clientes desde un CSV

POST /v1/clients/import (scope clients:write) lee un fichero delimitado y crea un cliente por cada fila válida. La petición es multipart/form-data —lleva un fichero, no un cuerpo JSON— con tres campos:

CampoTipoSignificado
fileficheroEl fichero CSV/XLSX/XLS/ODS/TXT, hasta 10 MB.
mappingobjeto{ "cabecera_csv": "campo_destino" }. Debe mapear al menos name y tax_id.
dry_runbooleanoSi es true, valida y previsualiza sin crear nada. Por defecto false.

El mapping indica al importador qué columna de la hoja alimenta cada campo del cliente. El conjunto de destino debe incluir name y tax_id: sin ellos no se puede crear un cliente y la petición se rechaza con 422 antes de procesar ninguna fila.

Descargar la plantilla

GET /v1/clients/import/template devuelve un CSV listo para rellenar (UTF-8 con BOM para que Excel lo abra bien) cuya fila de cabecera lista todas las columnas que entiende el importador: Nombre, NIF/CIF, Razón social, Email, Teléfono, campos de dirección, IVA/retención por defecto, IBAN y más. Dos filas de ejemplo muestran el formato esperado.

curl -s https://api.factuarea.com/v1/clients/import/template \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -o plantilla-clientes.csv

Primero dry run, luego importar

Valida siempre con dry_run=true antes de confirmar. La previsualización devuelve un informe por fila y no escribe nada:

curl -s -X POST https://api.factuarea.com/v1/clients/import \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -F "file=@clientes.csv" \
  -F 'mapping={"Nombre":"name","NIF/CIF":"tax_id","Email":"email"};type=application/json' \
  -F "dry_run=true"
{
  "data": {
    "object": "client_import_preview",
    "total_rows": 3,
    "rows": [
      { "row": 2, "status": "valid", "errors": [], "warnings": [] },
      {
        "row": 3,
        "status": "error",
        "errors": [{ "param": "tax_id", "code": "invalid_tax_id", "message": "El NIF no es válido." }],
        "warnings": []
      },
      { "row": 4, "status": "valid", "errors": [], "warnings": [] }
    ]
  }
}

row es el número de línea (en base 1) en el fichero (la cabecera es la fila 1, así que la primera fila de datos es la 2). status es valid o error; cada item de errors[] lleva el param afectado, un code estable y un message en español.

Cuando la previsualización está limpia, reenvía el mismo fichero y mapeo con dry_run=false (u omítelo). Solo se crean las filas válidas; las rechazadas vuelven en failures[], y la respuesta sigue la forma partial-success con un results[] por fila:

{
  "data": {
    "total": 3,
    "successful": 2,
    "failed": 1,
    "failures": [
      {
        "index": 1,
        "error_code": "invalid_tax_id",
        "error_message": "El NIF no es válido.",
        "errors": [{ "param": "tax_id", "code": "invalid_tax_id", "message": "El NIF no es válido." }],
        "warnings": []
      }
    ],
    "results": [
      { "row": 3, "status": "error", "errors": [{ "param": "tax_id", "code": "invalid_tax_id", "message": "El NIF no es válido." }], "warnings": [] }
    ]
  }
}

Siempre se cumple total === successful + failed. Una fila duplicada (un cliente ya existente, según la regla de deduplicación) se omite (skipped), no falla: cuenta como successful y no se vuelve a crear, así que reejecutar el mismo fichero es seguro.

Ramifica por error_code / code, nunca por el mensaje: el mensaje es texto en español, orientado a personas. Los códigos por fila salen del catálogo de errores v1.

Tope de tamaño de fichero

La importación v1 es síncrona para poder devolver el resultado por fila en la misma respuesta. Los ficheros tienen un tope de menos de 200 filas; un fichero mayor se rechaza con 422 y el código client_import_too_large. Divide una lista grande en lotes por debajo del tope e impórtalos en secuencia.

Los rechazos de file (10 MB) y dry_run, y los topes de 5000/200, se aplican antes de escribir ninguna fila. La previsualización dry-run es la forma más barata de cazar filas malformadas: úsala antes de cada importación real.

En esta página