Cómo subir archivos usando la API de FacturaScripts
FacturaScripts permite subir y administrar archivos mediante tres endpoints:
uploadFiles: permite subir uno o varios archivos en una sola petición.attachedfiles: permite consultar, descargar, crear, modificar o eliminar registros de archivos adjuntos.productoimagenes: sube una imagen y la vincula a un producto en una sola petición. También permite consultar las imágenes de los productos con sus miniaturas.
Como el resto de la API, todas las peticiones necesitan la clave de API en la cabecera Token. Consulta la guía de la API para crear una clave y ver los errores de autenticación.
📤 Subir uno o varios archivos con uploadFiles
Este es el endpoint más sencillo cuando solamente queremos subir archivos. Acepta peticiones POST y PUT:
POST /api/3/uploadFiles
La petición debe usar multipart/form-data y cada archivo debe incluirse en el parámetro files[]. FacturaScripts rechaza las extensiones que podrían permitir ejecutar código en el servidor, como .php, .phar o .phtml.
Ejemplo con curl:
curl -X POST 'https://TU-DOMINIO/api/3/uploadFiles' \
-H 'Token: TU_TOKEN' \
-F 'files[]=@/ruta/imagen1.jpg' \
-F 'files[]=@/ruta/documento.pdf'
Ejemplo en PHP:
<?php
$ch = curl_init('https://TU-DOMINIO/api/3/uploadFiles');
$body = [
'files[0]' => new CURLFile('/ruta/imagen1.jpg'),
'files[1]' => new CURLFile('/ruta/documento.pdf'),
];
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => ['Token: TU_TOKEN'],
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ejemplo en JavaScript con Axios:
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
async function subirArchivos() {
const form = new FormData();
form.append('files[]', fs.createReadStream('/ruta/imagen1.jpg'));
form.append('files[]', fs.createReadStream('/ruta/documento.pdf'));
const response = await axios.post(
'https://TU-DOMINIO/api/3/uploadFiles',
form,
{
headers: {
Token: 'TU_TOKEN',
...form.getHeaders(),
},
}
);
console.log(response.data);
}
subirArchivos();
Ejemplo de petición con Insomnia:

La respuesta contiene un array files con un registro AttachedFile por cada archivo guardado correctamente:
{
"files": [
{
"idfile": 123,
"filename": "imagen1.jpg",
"mimetype": "image/jpeg",
"path": "MyFiles/2026/08/123_imagen1.jpg",
"size": 15432
}
]
}
Los archivos no válidos se omiten. Por tanto, conviene comprobar que el número de elementos devuelto en files coincide con el número de archivos enviados. Si ninguno se pudo guardar, se devuelve un array vacío.
Se rechazan los archivos que podrían ejecutarse en el servidor, como php o html. El resto se guardan, pero después solo se pueden descargar los de la lista de tipos permitidos.
Al guardar un archivo, FacturaScripts:
- crea su registro
AttachedFile; - lo organiza dentro de
MyFilespor año y mes; - genera un nombre único que comienza por
idfile; - detecta su tipo MIME y tamaño reales;
- comprueba el límite de almacenamiento configurado;
- elimina los metadatos EXIF, XMP e IPTC de imágenes JPEG, PNG y WebP cuando GD está disponible.
🗂️ Administrar archivos con attachedfiles
El endpoint /api/3/attachedfiles es el CRUD completo del modelo AttachedFile. La ruta se escribe en minúsculas.
📋 Listar archivos
GET /api/3/attachedfiles
Admite paginación, ordenación y filtros mediante limit, offset, sort, filter y operation. La cabecera X-Total-Count contiene el número total de registros que cumplen los filtros.
Por ejemplo:
GET /api/3/attachedfiles?limit=20&offset=0&sort[idfile]=DESC
⬇️ Consultar y descargar un archivo
GET /api/3/attachedfiles/123
Además de los datos del archivo, la respuesta incorpora:
download: URL firmada válida durante el día en que se genera.download-permanent: URL firmada permanente.
📄 Subir un único archivo
También puede crearse un archivo con POST /api/3/attachedfiles y una petición multipart/form-data:
curl -X POST 'https://TU-DOMINIO/api/3/attachedfiles' \
-H 'Token: TU_TOKEN' \
-F 'file=@/ruta/documento.pdf'
Este endpoint crea un único registro AttachedFile por petición. Si se envían varios archivos, solo se usa el primero válido y el resto se ignora; para una carga múltiple debe utilizarse uploadFiles.
✏️ Modificar o eliminar
PUT /api/3/attachedfiles/123
PATCH /api/3/attachedfiles/123
DELETE /api/3/attachedfiles/123
PUT y PATCH modifican los campos del registro. DELETE elimina tanto el registro como el archivo físico.
También puede consultarse el esquema del recurso:
GET /api/3/attachedfiles/schema
🔗 Vincular el archivo con productos, clientes o documentos
Subir un archivo no lo vincula automáticamente con una factura, pedido, producto, cliente, proveedor u otro registro. Para crear esa relación se utiliza el endpoint attachedfilerelations, indicando:
idfile: identificador devuelto al subir el archivo.model: nombre del modelo relacionado, por ejemploFacturaCliente.modelid: identificador numérico del registro, por ejemplo elidfacturade una factura.modelcode: código del registro cuando se utiliza una clave textual. Según el modelo relacionado se utilizarámodelid,modelcodeo ambos.
🖼️ Imágenes de productos con productoimagenes
Para las imágenes de productos existe el endpoint /api/3/productoimagenes, que trabaja con el modelo ProductoImagen. En una sola petición sube la imagen y la vincula al producto, igual que la pestaña de imágenes de la ficha del producto.
📤 Subir una imagen a un producto
curl -X POST 'https://TU-DOMINIO/api/3/productoimagenes' \
-H 'Token: TU_TOKEN' \
-F 'idproducto=15' \
-F 'file=@/ruta/foto.jpg'
Campos admitidos:
idproducto: producto al que pertenece la imagen (obligatorio).referencia: referencia de una variante, si la imagen es solo de esa variante (opcional).orden: posición de la imagen en el listado (opcional).- Archivo: un campo de archivo con cualquier nombre (
file,files[]...).
Al recibir la imagen, FacturaScripts:
- comprueba que sea una imagen válida: gif, jpeg, jpg, png o webp, revisando también su contenido;
- crea el archivo adjunto (
AttachedFile), igual queuploadFiles; - crea la imagen del producto con su
idfile; - la añade a los archivos adjuntos del producto (
attachedfilerelations).
Si se envían varios archivos, solo se usa la primera imagen válida. Si ninguno es una imagen válida, la respuesta es un error y no se guarda nada. Si la imagen del producto no se puede guardar (por ejemplo, porque falta idproducto), se elimina también el archivo subido.
Si el archivo ya está subido, basta con enviar su idfile junto con idproducto, sin archivo.
🔍 Consultar las imágenes
GET /api/3/productoimagenes?filter[idproducto]=15
GET /api/3/productoimagenes/7
Además de los datos de la imagen, cada resultado incluye download, download-permanent y thumbnails, la lista de miniaturas ya generadas. Con los parámetros width y height se genera, si no existe, una miniatura de ese tamaño:
GET /api/3/productoimagenes/7?width=300&height=300
PUT y PATCH modifican los campos de la imagen (por ejemplo, orden). DELETE elimina la imagen del producto y sus miniaturas, pero no el archivo adjunto.
Versiones anteriores: desde la 2025.7, en la que se añadió, hasta la 2026.72, este endpoint responde a todas las peticiones con el error
405 method-not-allowed, por lo que no se puede usar. En esas versiones, sube la imagen conuploadFilesy vincúlala al producto creando un registroProductoImagendesde un plugin.
En resumen: usa uploadFiles para cargas simples o múltiples, attachedfiles para listar, descargar, administrar o subir un único archivo, y productoimagenes para las imágenes de los productos.