Versión 2026-07-26 · Base: https://subemelo.com/v1 · Todo en JSON, autenticación con clave secreta.
Manda tu clave en la cabecera Authorization. Las claves sk_test_… funcionan igual pero no envÃan ningún correo: úsalas para probar.
curl https://subemelo.com/v1/ping \
-H "Authorization: Bearer sk_live_tu_clave"
âš ï¸ La clave es secreta: úsala solo desde tu servidor, nunca en el navegador ni en una app móvil.
POST /v1/requests — crea la lista y avisa por email al destinatario.
curl -X POST https://subemelo.com/v1/requests \
-H "Authorization: Bearer sk_live_tu_clave" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pedido-4821" \
-d '{
"title": "Documentación web Restaurante Marisol",
"items": ["DNI del titular", "Logo en vectorial", "10 fotos del local"],
"creator": { "email": "hola@tuagencia.com", "name": "Tu Agencia" },
"recipient": { "email": "cliente@email.com", "phone": "+34600000000" },
"metadata": { "crm_id": "4821" }
}'
Devuelve la solicitud con su id y el upload_url que puedes reenviar tú por WhatsApp si quieres.
GET /v1/requests (admite ?status=active|completed, ?limit=, ?offset=) y GET /v1/requests/{id}.
{
"id": "a1b2c3…",
"status": "active",
"progress": { "total": 3, "completed": 1, "percent": 33 },
"items": [ { "id": "1", "description": "DNI del titular", "completed": true, "files": [ … ] } ],
"upload_url": "https://subemelo.com/s/…"
}GET /v1/requests/{id}/download devuelve una URL firmada y temporal (por defecto 60 minutos, parámetro expires_in_minutes). Nunca expone el panel del creador.
{ "url": "https://subemelo.com/d/…", "expires_at": "2026-07-26T12:00:00.000Z", "format": "zip" }Configura tu URL con POST /v1/webhook y te avisamos de: request.completed, request.item_completed y request.expired.
curl -X POST https://subemelo.com/v1/webhook \
-H "Authorization: Bearer sk_live_tu_clave" \
-H "Content-Type: application/json" \
-d '{ "url": "https://tu-crm.com/hooks/subemelo" }'
Comprueba siempre la firma. Enviamos la cabecera X-Subemelo-Signature: t=<epoch>,v1=<hmac>, donde el HMAC-SHA256 se calcula sobre t + "." + cuerpo con tu whsec_…:
const firmado = crypto.createHmac('sha256', WHSEC).update(t + '.' + cuerpoCrudo).digest('hex');
if (firmado !== v1recibido) return res.status(400).end(); // no es nuestro: descártalo
Reintentamos hasta 3 veces si tu servidor no responde 2xx.
PATCH /v1/requests/{id} (cambiar tÃtulo, add_items, stop_reminders, metadata) · POST /v1/requests/{id}/remind (recordatorio manual) · DELETE /v1/requests/{id} (borra la solicitud y sus archivos).
600 llamadas/hora por clave · 30 documentos por solicitud · 500 solicitudes activas · repite Idempotency-Key y no se duplica nada (24 h).
Los errores llegan como { "error": { "type": "…", "message": "…", "status": 400 } } con los códigos HTTP habituales (400, 401, 404, 409, 429).
Para Make, Zapier o Postman: https://subemelo.com/v1/openapi.json