Archivos de los ítems
Adjunta archivos a los ítems de una colección —subiendo los bytes o desde una URL—, descárgalos, renómbralos y bórralos.
Un ítem de una colección (ver Colecciones e ítems) puede llevar archivos adjuntos: la propuesta de un cliente, la factura de un pedido, la foto de un producto. Con met.files los adjuntas, los listas, los descargas, los renombras y los borras.
Leer pide items:read; adjuntar, renombrar y borrar, items:write. Los dos funcionan con una key de test. Las rutas son planas (/items/{itemId}/files, /item-files/{fileId}): operan sobre el workspace de la key, y un ítem o un archivo de otro workspace responde 404.
Adjuntar un archivo
Desde los bytes que ya tienes (multipart, campo file):
import { readFile } from 'node:fs/promises';
const bytes = await readFile('propuesta.pdf');
const archivo = await met.files.upload(41207, bytes, {
filename: 'Propuesta comercial (v2).pdf',
contentType: 'application/pdf',
});
console.log(archivo.id, archivo.download_url);with open("propuesta.pdf", "rb") as f:
archivo = met.files.upload(41207, f.read(), filename="Propuesta comercial (v2).pdf", content_type="application/pdf")
print(archivo["id"], archivo["download_url"])curl -X POST https://api.met.meteor.com.co/api/v1/items/41207/files \
-H "Authorization: Bearer $METEOR_API_KEY" \
-F "file=@propuesta.pdf;type=application/pdf"O desde una URL pública, sin bajar y volver a subir el archivo en tu servidor: Met lo descarga por ti.
await met.files.attachUrl(41207, 'https://mitienda.co/facturas/10293.pdf', { filename: 'Factura 10293.pdf' });met.files.attach_url(41207, "https://mitienda.co/facturas/10293.pdf", filename="Factura 10293.pdf")curl -X POST https://api.met.meteor.com.co/api/v1/items/41207/files \
-H "Authorization: Bearer $METEOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://mitienda.co/facturas/10293.pdf","filename":"Factura 10293.pdf"}'- El tope es 25 MB por archivo, por los dos caminos.
- La URL tiene que ser pública: Met no descarga direcciones internas ni privadas (protección contra SSRF). Tiene 20 segundos para responder; si responde un error o no trae contenido, el adjunto no se crea. El tipo del archivo sale de su
Content-Type. - Sin
filename, el nombre sale de la URL. - El archivo también aparece en la Mediateca del workspace (
asset_id), y Met extrae su texto en segundo plano para que un Met pueda leerlo en una conversación.
Qué devuelve
{
"id": 8123,
"item_id": 41207,
"original_name": "Propuesta comercial (v2).pdf",
"filename": "1753848291233-propuesta-comercial.pdf",
"mime_type": "application/pdf",
"size": 184320,
"storage_path": "items/41207/1753848291233-propuesta-comercial.pdf",
"created_by": 42,
"created_at": "2026-07-30T04:44:51.233Z",
"asset_id": null,
"download_url": "https://…/object/sign/…?token=…"
}
| Campo | Qué es |
|---|---|
original_name | El nombre que ve la gente y con el que se descarga. |
filename | El nombre saneado con el que se guardó. No lo muestres. |
storage_path | Lo que conviene guardar si guardas una referencia: es lo único estable. |
download_url | Solo al adjuntar: un enlace firmado que vence a los 7 días. Sirve para usarlo enseguida, no para guardarlo. |
Los archivos viven en un almacenamiento privado: no hay URL pública que se abra sin credenciales.
Listar y descargar
import { writeFile } from 'node:fs/promises';
const archivos = await met.files.list(41207); // del más reciente al más viejo
for await (const f of met.files.iterate(41207)) {
console.log(f.id, f.original_name, f.size);
}
const { data, contentType, filename } = await met.files.download(8123);
await writeFile(filename ?? 'archivo', data);archivos = met.files.list(41207)
for f in met.files.iterate(41207):
print(f["id"], f["original_name"], f["size"])
descarga = met.files.download(8123)
with open(descarga["filename"] or "archivo", "wb") as out:
out.write(descarga["data"])curl -L https://api.met.meteor.com.co/api/v1/item-files/8123/download \
-H "Authorization: Bearer $METEOR_API_KEY" -o propuesta.pdflist()sin parámetros trae los últimos 100.iterate()recorre todos, página por página, con cursor.download()devuelve bytes, no JSON, con el tipo y el nombre del archivo. A diferencia dedownload_url, esta ruta no vence: valida la key en cada llamada.
Renombrar y borrar
await met.files.update(8123, { name: 'Propuesta aprobada.pdf' });
await met.files.delete(8123); // { message: 'File deleted' }met.files.update(8123, name="Propuesta aprobada.pdf")
met.files.delete(8123)Renombrar cambia solo original_name: el contenido y storage_path no se tocan. Borrar elimina el archivo y su registro; el ítem sigue existiendo.
Desde un asistente (MCP)
El servidor MCP lista los archivos de un ítem, pero no sube ni descarga bytes: un archivo no viaja por la conversación de un asistente. Para eso, usa el SDK o la API.
Otros archivos del workspace
La Mediateca —imágenes, videos y documentos del workspace, organizados en carpetas— es otro recurso: met.assets, con los scopes files:read y files:write.
Errores comunes
| Código | Qué pasó |
|---|---|
400 validation_error | No mandaste ni file ni url; la URL no está permitida, respondió un error o no trajo contenido; o el archivo de la URL pasa de 25 MB. |
413 FILE_TOO_LARGE | El archivo subido por multipart pasa de 25 MB. |
404 not_found | El ítem o el archivo no existe en este workspace. |
403 missing_scope | La key no trae items:write (o items:read para leer). |