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ámetro | Valores | Significado |
|---|---|---|
format | SUMMARY (por defecto) · ITEMS | Layout 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_format | xlsx (por defecto) · csv | Formato de fichero. |
Elige las facturas a exportar de dos maneras:
- Por id — pasa
invoice_idscon los ids UUID v7 de facturas concretas. - Por filtro — omite
invoice_idsy acota el conjunto constatus,date_from,date_to,client_id,series_idysearch.date_fromydate_tofiltran por fecha de emisión (ambas incluidas);client_idyseries_idtoman 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.xlsxEl 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:
| Campo | Tipo | Significado |
|---|---|---|
file | fichero | El fichero CSV/XLSX/XLS/ODS/TXT, hasta 10 MB. |
mapping | objeto | { "cabecera_csv": "campo_destino" }. Debe mapear al menos name y tax_id. |
dry_run | booleano | Si 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.csvPrimero 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.