Una sola clave de API y un único formato de solicitud para modelos de generación de imágenes y videos. Las imágenes se devuelven en la respuesta; los videos se ejecutan como tareas que puedes consultar periódicamente o recibir mediante webhook.
Crea una clave en Consola → Claves API. La clave completa solo se muestra una vez, así que guárdala de inmediato, por ejemplo como MLMUX_API_KEY.
Llama a un endpoint de imagen o video con un ID de modelo y un prompt. El uso se cobra a la cuenta propietaria de la clave.
Las solicitudes de imagen devuelven URLs en la respuesta. Las solicitudes de video devuelven una tarea: consulta periódicamente su poll_url o suscríbete a un webhook.
Envía tu clave en el encabezado Authorization: Bearer en cada solicitud a https://api.mlmux.com. Las claves comienzan con sk-. La API no acepta claves en otros encabezados ni en la cadena de consulta.
Para comprobar que una clave funciona, lista los modelos a los que puede llamar:
https://api.mlmux.com/v1/modelscurl https://api.mlmux.com/v1/models \
-H "Authorization: Bearer $MLMUX_API_KEY"{
"object": "list",
"data": [
{ "id": "nano-banana-2", "object": "model", "owned_by": "platform" },
{ "id": "model/seedance-2.5-max", "object": "model", "owned_by": "platform" }
]
}Todos los endpoints están bajo https://api.mlmux.com. Los cuerpos de solicitud y respuesta son JSON a menos que se indique lo contrario.
| Método | Ruta | Descripción |
|---|---|---|
GET | /v1/models | Lista los ID de los modelos a los que puedes llamar. |
POST | /v1/images/generations | Genera imágenes a partir de un prompt. |
POST | /v1/images/edits | Edita o combina imágenes de entrada. Acepta JSON o multipart. |
GET | /v1/images/generations/{task_id} | Obtén una tarea asíncrona de imagen. Las ediciones usan /v1/images/edits/{task_id}. |
POST | /v1/videos/generations | Crea una tarea de video. |
GET | /v1/videos/generations/{task_id} | Obtén una tarea de video. |
GET | /v1/tasks/{task_id} | Obtén cualquier tarea por su ID. |
POST | /v1/tasks/{task_id}/cancel | Cancela una tarea que no haya finalizado. |
POST | /v1/uploads | Sube un archivo de referencia y obtén una URL. |
GET | /v1/account/balance | Consulta tu saldo de créditos. |
Define route_mode en el cuerpo de la solicitud para elegir el nivel upstream. Una solicitud permanece en su nivel y nunca pasa a otro de forma silenciosa; si el nivel está desactivado para el modelo, la solicitud falla con route_mode_disabled. Cuando se omite el campo, MLMux utiliza los modos de enrutamiento configurados en la clave de API y, luego, el valor predeterminado del modelo, que es official-cheap.
| Valor | Descripción |
|---|---|
official | La ruta oficial del proveedor, facturada al precio de lista del proveedor. |
official-cheap | Una ruta oficial de menor costo. Predeterminada para nuevas solicitudes y claves API. |
El uso se cobra en créditos, y 1 crédito equivale a 1 dólar estadounidense. Los modelos de video se facturan por token de salida; los modelos de imagen se facturan por token del proveedor o por imagen, según el modelo. Consulta la página de precios para ver las tarifas de cada ruta.
Las respuestas de las tareas muestran estimated_charge_credits cuando se crea la tarea y actual_charge_credits después de completarse con éxito, ambos en créditos. Los payloads de webhook muestran actual_charge_nano_credits como un entero, donde 1,000,000,000 de nano-créditos equivalen a 1 crédito.
Consulta tu saldo restante con GET /v1/account/balance.
Las solicitudes de video y las solicitudes de imagen enviadas con "async": true devuelven HTTP 202 con una tarea. Sondea el poll_url de la tarea cada pocos segundos hasta que su estado sea succeeded, failed, expired o canceled.
| Estado | Descripción |
|---|---|
queued | Aceptada y esperando para comenzar. |
submitted | Enviada al proveedor ascendente. |
running | Generando. progress va de 0 a 100. |
succeeded | Finalizada. La respuesta ahora incluye las URL de salida. |
failed | Fallida. message explica el motivo. |
expired | No finalizó dentro del límite de tiempo de la tarea. |
canceled | Cancelada a través del endpoint de cancelación. |
https://api.mlmux.com/v1/tasks/{task_id}/cancelLas tareas en estado queued, submitted o running se pueden cancelar, y sus créditos retenidos se liberan. La respuesta es {"id": "task_…", "status": "canceled"}. Las tareas en cualquier otro estado devuelven 409 task_not_cancelable.
Las solicitudes asíncronas de generación de imagen y video admiten un encabezado Idempotency-Key de hasta 160 caracteres. Enviar la misma clave con el mismo cuerpo nuevamente devuelve la tarea original en lugar de crear una nueva. Enviar la misma clave con un cuerpo diferente devuelve 409 idempotency_key_reused. Las solicitudes síncronas y las ediciones de imagen no admiten este encabezado.
Para usar un archivo local como referencia, cárguelo como el campo multipart file. Se admiten imágenes, videos y audio de hasta 50 MB, los cuales se conservan durante 3 días. Pase la url devuelta en cualquier campo URL de una solicitud de generación.
https://api.mlmux.com/v1/uploadscurl https://api.mlmux.com/v1/uploads \
-H "Authorization: Bearer $MLMUX_API_KEY" \
-F "file=@start-frame.jpg"{
"url": "https://.../uploads/3f8a....jpg",
"asset_id": 1024,
"mime_type": "image/jpeg",
"size_bytes": 482113,
"asset_type": "image"
}Cree un endpoint en Console → Webhooks y elija los eventos que desea recibir. Cuando finaliza una solicitud o tarea, MLMux envía una solicitud POST con un cuerpo JSON a su URL.
| Evento | Descripción |
|---|---|
request.succeeded | Una solicitud o tarea se completó correctamente. |
request.failed | Una solicitud o tarea falló. data.error_code y data.error_message explican el motivo. |
webhook.test | Se envía al probar el endpoint en Console. |
{
"event_id": "evt_5b0d...",
"event_type": "request.succeeded",
"created_at": "2026-10-26T08:00:00Z",
"data": {
"request_id": "task_task_01a9...",
"task_id": "task_01a9...",
"public_model_id": "model/seedance-2.5-max",
"api_method": "videos.generations.create",
"image_count": 0,
"image_resolution": "",
"video_seconds": 8,
"video_resolution": "720p",
"actual_charge_nano_credits": 1790000000,
"latency_ms": 94210
}
}Cada entrega se firma con el secreto de firma del endpoint (whsec_…), que se muestra una sola vez al crearlo o rotarlo. El encabezado X-MLMux-Signature contiene una marca de tiempo Unix t y una firma v1: el HMAC-SHA256 en hexadecimal de la marca de tiempo, un punto y el cuerpo sin procesar de la solicitud. Calcule el mismo valor, compárelo y rechace marcas de tiempo antiguas.
import crypto from "node:crypto";
// header: X-MLMux-Signature: t=1767225600,v1=5f8c...
export function verifyMLMuxSignature(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map((part) => part.split("=")));
const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
return fresh && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1 ?? ""));
}Devuelva cualquier estado 2xx en un plazo de 10 segundos. MLMux realiza hasta 6 intentos de entrega a lo largo de unas 11 horas. Use X-MLMux-Event-ID para ignorar entregas duplicadas.
Los errores comparten una misma estructura JSON. Condicione la lógica en función de code y no de message. Incluya request_id, que también se devuelve en el encabezado X-Request-ID, al ponerse en contacto con soporte.
{
"error": {
"message": "Invalid API key",
"type": "invalid_request_error",
"code": "invalid_api_key",
"request_id": "req_9f2c..."
}
}| HTTP | Código | Significado |
|---|---|---|
| 400 | invalid_request | El cuerpo no es un JSON válido o un campo tiene un tipo incorrecto, como un route_mode desconocido en una generación de imagen. |
| 400 | invalid_value | Un valor como resolution, size, aspect_ratio o n no es compatible con el modelo. |
| 400 | model_not_found | El ID del modelo no existe o no está disponible. |
| 400 | invalid_video_request | El modo de video, la cantidad de referencias, la relación de aspecto, la resolución o la duración no son válidos. |
| 400 | content_policy_violation | El prompt o una entrada fueron bloqueados por moderación de contenido. |
| 401 | invalid_api_key | La clave API falta, no es válida, venció o está deshabilitada. |
| 402 | insufficient_credits | El saldo no cubre el cargo estimado. Agregue créditos e intente de nuevo. |
| 402 | spend_limit_exceeded | La solicitud superaría un límite de gasto configurado en Console. |
| 402 | api_key_monthly_limit_exceeded | La solicitud superaría el presupuesto mensual de esta clave API. |
| 403 | email_verification_required | Verifique la dirección de correo de la cuenta antes de usar la API. |
| 403 | model_not_allowed | Esta clave API está restringida a otros modelos. |
| 403 | forbidden_asset_reference | Una referencia asset:// no pertenece a esta cuenta. |
| 404 | task_not_found | La tarea no existe o pertenece a otra cuenta. |
| 409 | idempotency_key_reused | El Idempotency-Key ya se utilizó con un cuerpo diferente. |
| 409 | task_not_cancelable | La tarea ya finalizó. |
| 429 | rate_limit_exceeded | Demasiadas solicitudes por minuto para esta clave o cuenta. |
| 429 | capacity_exhausted | Todos los upstream de la ruta seleccionada están ocupados. |
| 502 | model_unavailable | La ruta seleccionada no tiene ningún upstream disponible para este modelo. |
| 502 | generation_failed | El proveedor upstream no pudo generar un resultado. |
| 503 | generation_unavailable | El proveedor upstream no está disponible temporalmente. |
| 503 | route_mode_disabled | El modo de enrutamiento seleccionado está desactivado para este modelo. Envía otro route_mode. |
| 504 | generation_timeout | Se agotó el tiempo de espera del proveedor upstream. |
Las respuestas 429 incluyen un encabezado Retry-After. Espere esa cantidad de segundos antes de reintentar, y reintente los errores 5xx con retroceso exponencial.