Один API-ключ и единый формат запроса для моделей генерации изображений и видео. Изображения возвращаются в ответе, а видео выполняются как задачи, которые можно опрашивать или получать через webhook.
Создайте ключ в разделе Консоль → API-ключи. Полный ключ показывается только один раз, поэтому сохраните его сразу, например, как MLMUX_API_KEY.
Вызовите эндпоинт генерации изображений или видео, передав ID модели и промпт. Списания производятся с аккаунта, которому принадлежит ключ.
Запросы на генерацию изображений возвращают URL прямо в ответе. Запросы на генерацию видео возвращают задачу: опрашивайте её poll_url или подпишитесь на вебхук.
Передавайте ключ в заголовке Authorization: Bearer при каждом запросе к https://api.mlmux.com. Ключи начинаются с sk-. API не принимает ключи в других заголовках или в строке запроса.
Чтобы проверить работоспособность ключа, запросите список доступных моделей:
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" }
]
}Все эндпоинты доступны по адресу https://api.mlmux.com. Тела запросов и ответов передаются в формате JSON, если не указано иное.
| Метод | Путь | Описание |
|---|---|---|
GET | /v1/models | Список ID моделей, доступных для вызова. |
POST | /v1/images/generations | Генерация изображений по промпту. |
POST | /v1/images/edits | Редактирование или объединение исходных изображений. Принимает JSON или multipart. |
GET | /v1/images/generations/{task_id} | Получение асинхронной задачи генерации изображений. Для редактирования используется /v1/images/edits/{task_id}. |
POST | /v1/videos/generations | Создание задачи генерации видео. |
GET | /v1/videos/generations/{task_id} | Получение задачи генерации видео. |
GET | /v1/tasks/{task_id} | Получение любой задачи по ID. |
POST | /v1/tasks/{task_id}/cancel | Отмена незавершённой задачи. |
POST | /v1/uploads | Загрузка референсного файла и получение URL. |
GET | /v1/account/balance | Получение баланса кредитов. |
Укажите route_mode в теле запроса, чтобы выбрать уровень upstream. Запрос остается на своем уровне и никогда незаметно не переключается на другой; если уровень отключен для модели, запрос завершается с ошибкой route_mode_disabled. Если поле не указано, MLMux использует режимы маршрутизации, настроенные для API-ключа, а затем значение модели по умолчанию — official-cheap.
| Значение | Описание |
|---|---|
official | Официальный маршрут провайдера с тарификацией по его прейскуранту. |
official-cheap | Более экономичный официальный маршрут. Используется по умолчанию для новых запросов и API-ключей. |
Использование оплачивается кредитами, где 1 кредит равен 1 доллару США. Видеомодели тарифицируются за выходной токен; модели изображений — за токен провайдера или за изображение в зависимости от модели. Тарифы для каждого маршрута приведены на странице с ценами.
В ответах задач указывается estimated_charge_credits при создании задачи и actual_charge_credits после её успешного завершения (оба значения в кредитах). В полезной нагрузке вебхуков передаётся actual_charge_nano_credits в виде целого числа, где 1,000,000,000 нанокредитов равны 1 кредиту.
Проверить остаток баланса можно с помощью GET /v1/account/balance.
Запросы на генерацию видео, а также запросы на генерацию изображений с параметром "async": true, возвращают HTTP 202 с объектом задачи. Опрашивайте poll_url задачи каждые несколько секунд, пока её статус не станет succeeded, failed, expired или canceled.
| Статус | Описание |
|---|---|
queued | Принята и ожидает запуска. |
submitted | Отправлена провайдеру. |
running | Генерация. Значение progress изменяется от 0 до 100. |
succeeded | Завершена. Ответ содержит итоговые URL. |
failed | Ошибка. Причина указана в message. |
expired | Не завершилась в установленный лимит времени. |
canceled | Отменена через эндпоинт отмены. |
https://api.mlmux.com/v1/tasks/{task_id}/cancelЗадачи в статусе queued, submitted или running можно отменить, при этом заблокированные кредиты будут возвращены. Ответ: {"id": "task_…", "status": "canceled"}. Для задач в любом другом статусе возвращается ошибка 409 task_not_cancelable.
Асинхронные запросы на генерацию видео и изображений принимают заголовок Idempotency-Key длиной до 160 символов. Повторная отправка того же ключа с тем же телом запроса возвращает исходную задачу вместо создания новой. Отправка того же ключа с другим телом возвращает 409 idempotency_key_reused. Синхронные запросы и редактирование изображений этот заголовок не поддерживают.
Чтобы использовать локальный файл в качестве референса, загрузите его в multipart-поле file. Принимаются изображения, видео и аудио размером до 50 МБ; они хранятся в течение 3 дней. Передавайте возвращённый url в любых полях URL запроса на генерацию.
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"
}Создайте эндпоинт в Console → Webhooks и выберите события для получения. Когда запрос или задача завершается, MLMux отправляет POST-запрос с телом в формате JSON на ваш URL.
| Событие | Описание |
|---|---|
request.succeeded | Запрос или задача успешно выполнены. |
request.failed | Запрос или задача завершились с ошибкой. Причина указана в data.error_code и data.error_message. |
webhook.test | Отправляется при тестировании эндпоинта в 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
}
}Каждая доставка подписывается секретным ключом эндпоинта (whsec_…), который отображается один раз при его создании или ротации. Заголовок X-MLMux-Signature содержит Unix-штамп времени t и подпись v1: hex-строку HMAC-SHA256 от штампа времени, точки и необработанного тела запроса. Вычислите то же значение, сравните его и отклоняйте устаревшие штампы времени.
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 ?? ""));
}Возвращайте любой статус 2xx в течение 10 секунд. MLMux выполняет до 6 попыток доставки в течение приблизительно 11 часов. Используйте X-MLMux-Event-ID для игнорирования дубликатов.
Ошибки имеют единый формат JSON. Делайте ветвление по code, а не по message. При обращении в поддержку указывайте request_id, который также возвращается в заголовке X-Request-ID.
{
"error": {
"message": "Invalid API key",
"type": "invalid_request_error",
"code": "invalid_api_key",
"request_id": "req_9f2c..."
}
}| HTTP | Код | Пояснение |
|---|---|---|
| 400 | invalid_request | Тело запроса не является корректным JSON или поле имеет неверный тип, например неизвестный route_mode при генерации изображения. |
| 400 | invalid_value | Значение, такое как resolution, size, aspect_ratio или n, не поддерживается моделью. |
| 400 | model_not_found | Идентификатор модели не существует или недоступен. |
| 400 | invalid_video_request | Недопустимый режим видео, количество референсов, соотношение сторон, разрешение или длительность. |
| 400 | content_policy_violation | Промпт или входные данные заблокированы системой модерации контента. |
| 401 | invalid_api_key | API-ключ отсутствует, недействителен, истёк или отключён. |
| 402 | insufficient_credits | На балансе недостаточно средств для покрытия расчетной стоимости. Пополните баланс и повторите попытку. |
| 402 | spend_limit_exceeded | Запрос превысит лимит расходов, установленный в Console. |
| 402 | api_key_monthly_limit_exceeded | Запрос превысит месячный бюджет этого API-ключа. |
| 403 | email_verification_required | Подтвердите email-адрес аккаунта перед использованием API. |
| 403 | model_not_allowed | Этот API-ключ ограничен другими моделями. |
| 403 | forbidden_asset_reference | Ссылка asset:// не принадлежит этому аккаунту. |
| 404 | task_not_found | Задача не существует или принадлежит другому аккаунту. |
| 409 | idempotency_key_reused | Заголовок Idempotency-Key уже использовался с другим телом запроса. |
| 409 | task_not_cancelable | Задача уже завершена. |
| 429 | rate_limit_exceeded | Слишком много запросов в минуту для этого ключа или аккаунта. |
| 429 | capacity_exhausted | Все upstream-провайдеры на выбранном маршруте заняты. |
| 502 | model_unavailable | На выбранном маршруте нет доступных upstream-провайдеров для этой модели. |
| 502 | generation_failed | Upstream-провайдеру не удалось сгенерировать результат. |
| 503 | generation_unavailable | Upstream-провайдер временно недоступен. |
| 503 | route_mode_disabled | Выбранный режим маршрутизации отключен для этой модели. Передайте другой route_mode. |
| 504 | generation_timeout | Истекло время ожидания ответа от upstream-провайдера. |
Ответы со статусом 429 содержат заголовок Retry-After. Подождите указанное количество секунд перед повтором запроса, а ошибки 5xx повторяйте с экспоненциальной задержкой.