{"openapi":"3.1.0","info":{"title":"API epicai","version":"2026-10-27","summary":"Все нейросети сайта: текст, картинки, видео, музыка, озвучка, расшифровка, документы","description":"API epicai даёт доступ ко всем нейросетям сайта. Текстовые модели работают по протоколу **OpenAI Chat Completions**: подходят официальные библиотеки OpenAI для Python и JavaScript, Cursor, Continue, LangChain, n8n и любые клиенты, которые умеют указывать свой `base_url`. Картинки, видео, музыка, озвучка, расшифровка речи и документы запускаются задачами.\n\n## Вход\n\nКлюч создаётся в кабинете разработчика (`/developers`) и передаётся в заголовке `Authorization: Bearer sk-epic-…`. Для клиентов, привыкших к Anthropic, принимается и заголовок `x-api-key`. Ключ показывается один раз, в базе хранится только его хеш.\n\n## Деньги\n\nВызовы оплачиваются теми же токенами (ТОК), что и работа на сайте, по тем же ценам, с теми же ценовыми акциями. Перед запросом резервируется «вход + максимум ответа», после ответа списывается фактическое по данным вендора, остаток резерва возвращается. Если ответ не получен, токены не списываются. Стоимость каждого вызова приходит в поле `epic.cost_tok` и в заголовке `x-epic-cost-tok`.\n\nЦена задач с картинками, видео, музыкой, озвучкой и документами известна заранее, её отдаёт `POST /quote`. Она фиксируется при создании задачи и резервируется целиком, а после успеха списывается. Если задача не удалась, резерв снимается. Ключи организаций Business платят из кошелька организации.\n\n## Лимиты\n\nПо умолчанию 60 запросов в минуту и 10 одновременных на ключ. У ключа могут быть свои лимит в минуту, дневной и месячный потолок расхода (день считается по Москве), список разрешённых моделей и IP-адресов, срок действия. Ответ 429 содержит `Retry-After`.\n\n## Ошибки\n\nФормат ошибок как у OpenAI: `{\"error\": {\"message\", \"type\", \"param\", \"code\"}}`. По `code` программа различает причины, `message` написан для человека. В каждом ответе есть заголовок `x-request-id`; его стоит приложить к обращению в поддержку.\n\n## Задачи\n\nКартинки, видео, музыка, озвучка, расшифровка и документы создаются так: `POST /tasks` принимает модель, текст, параметры и входные файлы и сразу возвращает задачу. Дальше результат можно ждать опросом `GET /tasks/{id}` либо получить вебхуком на `webhook_url`. Готовые файлы хранятся 7 суток. Все параметры и допустимые значения каждой модели описаны в `GET /models/{id}`. Для картинок, озвучки и расшифровки есть и адреса в форме OpenAI, они ждут результата в одном запросе.\n\n## Что не поддерживается\n\nВ чате не поддерживаются `n` больше 1, `logprobs`, `audio`, `modalities`, `web_search_options`, `prediction` и устаревшие `functions`. В картинках `n` тоже только 1. Эмбеддингов в API нет. У видеомоделей Kling пока не работают режимы с раскадровкой и элементами, у Suno и Midjourney нет операций над уже готовым результатом (продление, апскейл, вариации), у Gamma нет шаблонов и тем оформления из библиотеки сайта.","contact":{"name":"Поддержка epicai","url":"https://epicai.ru/help"}},"servers":[{"url":"https://epicai.ru/v1","description":"epicai"}],"tags":[{"name":"Чат","description":"Генерация ответов текстовых моделей."},{"name":"Задачи","description":"Картинки, видео, музыка, озвучка, расшифровка и документы: создание задачи, цена, состояние и результат, вебхук."},{"name":"Картинки","description":"Создание картинок в форме OpenAI Images."},{"name":"Звук","description":"Озвучка текста и расшифровка речи в форме OpenAI Audio."},{"name":"Модели","description":"Каталог моделей всех типов, доступных ключу, их параметры и цены."},{"name":"Аккаунт","description":"Баланс, состояние ключа и статистика расхода."},{"name":"Сервис","description":"Описание сервиса и спецификация."}],"security":[{"bearerAuth":[]}],"paths":{"/":{"get":{"tags":["Сервис"],"operationId":"getRoot","summary":"Описание сервиса","description":"Возвращает версию API и адреса документации. Ключ не нужен.","security":[],"responses":{"200":{"description":"Описание сервиса.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","examples":["epicai.api"]},"version":{"type":"string","examples":["2026-10-27"]},"documentation":{"type":"string","format":"uri"},"reference":{"type":"string","format":"uri"},"openapi":{"type":"string","format":"uri"}}}}}}}}},"/openapi.json":{"get":{"tags":["Сервис"],"operationId":"getOpenApi","summary":"Спецификация OpenAPI","description":"Эта спецификация в формате OpenAPI 3.1. Ключ не нужен.","security":[],"responses":{"200":{"description":"Документ OpenAPI.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/models":{"get":{"tags":["Модели"],"operationId":"listModels","summary":"Список моделей","description":"Модели всех типов, доступные этому ключу. Имя модели из поля `id` передаётся в запрос как `model`. У текстовых моделей в `pricing` цены в токенах сайта (ТОК) за 1 млн токенов, у остальных цена за задачу, её даёт `POST /quote`. Полное описание параметров и входных файлов медиа-модели отдаёт `GET /models/{id}`.","parameters":[{"name":"type","in":"query","description":"Только модели этого типа.","schema":{"type":"string","enum":["chat","image","video","music","speech","transcription","document"]}}],"responses":{"200":{"description":"Список моделей.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"}},"content":{"application/json":{"schema":{"type":"object","required":["object","data"],"properties":{"object":{"type":"string","const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Model"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/models/{model}":{"get":{"tags":["Модели"],"operationId":"getModel","summary":"Описание модели","description":"Для текстовой модели окно контекста, возможности и цены за 1 млн токенов. Для остальных моделей ещё и `parameters` (JSON Schema допустимых параметров с подсказками `x-enum-titles`, `x-show-if`, `x-options-by`, `x-affects-price`), число входных файлов (`inputs`, `inputs_by`), длину текста (`prompt_max`, `prompt_required`) и примеры цен (`pricing.examples`).","parameters":[{"name":"model","in":"path","required":true,"description":"Имя модели из списка. Если в имени есть `/`, передавайте его как есть или с кодированием `%2F`.","schema":{"type":"string"},"examples":{"openrouter":{"value":"deepseek/deepseek-v4.1-flash"}}}],"responses":{"200":{"description":"Описание модели.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Model"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/chat/completions":{"post":{"tags":["Чат"],"operationId":"createChatCompletion","summary":"Создать ответ модели","description":"Принимает диалог и возвращает ответ модели целиком или потоком Server-Sent Events (`stream: true`).\n\n**Размер.** Тело запроса не больше 12 МБ. Картинки передаются ссылками `http(s)` или как `data:image/…;base64,…`.\n\n**Максимум ответа.** Если `max_tokens` не указан, берётся значение по умолчанию (8192, для моделей с рассуждениями 16384). Для резерва токенов считается именно этот максимум, поэтому на балансе должно хватать на «вход + максимум ответа». Уменьшите `max_tokens`, если хотите резервировать меньше.\n\n**Последнее сообщение.** Диалог должен заканчиваться сообщением `user` или `tool`.\n\n**Стриминг.** Ответ идёт кадрами `data: {…}` и завершается `data: [DONE]`. Чтобы получить расход, добавьте `stream_options: {\"include_usage\": true}`: перед `[DONE]` придёт кадр с `usage` и `epic.cost_tok`. Для длинных пауз сервер посылает комментарии `: keep-alive`. Если соединение оборвать, оплачивается то, что уже отдано.\n\n**Различия между вендорами.** Часть параметров (например, `seed`, штрафы за повторы, `temperature` у моделей с рассуждениями) вендор может проигнорировать.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"},"examples":{"simple":{"summary":"Простой запрос","value":{"model":"deepseek/deepseek-v4.1-flash","messages":[{"role":"system","content":"Отвечай кратко."},{"role":"user","content":"Назови три основных цвета."}],"max_tokens":200}},"stream":{"summary":"Поток с расходом","value":{"model":"claude-haiku-5-5","stream":true,"stream_options":{"include_usage":true},"messages":[{"role":"user","content":"Расскажи короткую историю о роботе."}],"max_tokens":400}},"tools":{"summary":"Вызов функции","value":{"model":"gpt-5.4-mini","messages":[{"role":"user","content":"Какая погода в Париже?"}],"tools":[{"type":"function","function":{"name":"get_weather","description":"Погода в городе","parameters":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}}],"tool_choice":"auto"}},"vision":{"summary":"Картинка на входе","value":{"model":"claude-haiku-5-5","max_tokens":200,"messages":[{"role":"user","content":[{"type":"text","text":"Что на картинке?"},{"type":"image_url","image_url":{"url":"https://example.com/photo.jpg"}}]}]}}}}}},"responses":{"200":{"description":"Ответ модели. Без `stream` приходит JSON, с `stream: true` приходит поток `text/event-stream`.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-limit-requests":{"$ref":"#/components/headers/RateLimit"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"},"x-ratelimit-reset-requests":{"$ref":"#/components/headers/RateReset"},"x-epic-cost-tok":{"description":"Списано ТОК за этот вызов. Только у ответа без стриминга; у потока стоимость приходит в последнем кадре как `epic.cost_tok`.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletion"}},"text/event-stream":{"schema":{"$ref":"#/components/schemas/ChatCompletionChunk"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/ServerError"},"503":{"$ref":"#/components/responses/ServerError"},"504":{"$ref":"#/components/responses/ServerError"}}}},"/quote":{"post":{"tags":["Задачи"],"operationId":"quoteTask","summary":"Узнать цену задачи","description":"Считает цену так же, как это сделает `POST /tasks`, но ничего не запускает и не списывает. Цена зависит от модели, параметров и действующих ценовых акций. У озвучки она зависит от длины текста в `prompt`, у расшифровки и части видеомоделей от длины входных файлов, поэтому в `videos` и `audios` можно передать секунды числом, не загружая файл. В `images` можно передать число картинок. Если у сочетания параметров нет цены, ответ 400 `unsupported_parameters`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"},"examples":{"video":{"summary":"Видео","value":{"model":"kling","parameters":{"scenario":"t2v","engine":"v3","quality":"std","duration":5}}},"speech":{"summary":"Озвучка, цена по тексту","value":{"model":"elevenlabs/eleven-v4","prompt":"Добро пожаловать в epicai."}},"transcription":{"summary":"Расшифровка, запись 90 секунд","value":{"model":"gpt-transcribe","audios":[90]}}}}}},"responses":{"200":{"description":"Цена задачи.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"503":{"$ref":"#/components/responses/ServerError"}}}},"/tasks":{"post":{"tags":["Задачи"],"operationId":"createTask","summary":"Создать задачу","description":"Запускает генерацию любой нейросети, кроме текстовых: картинки, видео, музыки, озвучки, расшифровки речи, документов. Ответ приходит сразу, со статусом `queued` или `in_progress`. Готовый результат забирают через `GET /tasks/{id}` или получают на `webhook_url`.\n\n**Цена.** Цена считается при создании по правилам сайта, фиксируется в задаче (`price.tokens`) и резервируется на балансе. Если задача не удалась, резерв снимается, токены не списываются. Заранее цену можно узнать через `POST /quote`.\n\n**Параметры.** Список допустимых значений у каждой модели свой, его отдаёт `GET /models/{id}` в поле `parameters` (JSON Schema). Параметр, которого нет в схеме, или значение вне списка дают ответ 400 `invalid_parameter`. Параметры, которые не заданы, берутся по умолчанию, как на сайте.\n\n**Входные файлы.** Картинки передаются ссылкой `http(s)` или строкой `data:image/png|jpeg|webp;base64,…` до 10 МБ. Видео и аудио передаются ссылкой или как `data:video/…;base64,…` и `data:audio/…;base64,…`, предельные размеры зависят от модели. Сколько файлов принимает модель, написано в её полях `inputs` и `inputs_by`.\n\n**Повтор запроса.** Заголовок `Idempotency-Key` защищает от двойного запуска при обрыве связи. Повтор с тем же ключом и теми же параметрами вернёт ту же задачу с кодом 200, с другими параметрами даст 409 `idempotency_conflict`.\n\n**Ограничения.** По умолчанию у одного ключа может быть не больше 20 задач в работе (`too_many_active_tasks`). Задача, которая не завершилась за 100 минут, считается неудавшейся (`task_timeout`).\n\n**Операции над результатом.** Увеличение, вариации, пересоздание и видео из картинки Midjourney, продолжение трека, WAV, текст по времени, замена участка и клип к треку Suno запускаются как обычные задачи с параметром `task` и полем `source`: номер завершённой задачи-источника и выбор картинки (`image`) или трека (`track`). Цена операции берётся по прайсу сайта. Источник должна создать та же модель и тот же владелец; если он не подходит, ответ 400 `invalid_source`.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Строка до 64 знаков (латиница, цифры, `.`, `_`, `:`, `-`), уникальная для каждой новой задачи.","schema":{"type":"string","maxLength":64,"pattern":"^[A-Za-z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskRequest"},"examples":{"image":{"summary":"Картинка","value":{"model":"nano-banana-2","prompt":"Маяк на скале в шторм, масло","parameters":{"aspect_ratio":"16:9"}}},"video":{"summary":"Видео по описанию","value":{"model":"kling","prompt":"Кошка идёт по подоконнику, дождь за окном","parameters":{"scenario":"t2v","engine":"v3","quality":"std","duration":5,"aspect_ratio":"16:9"}}},"video_i2v":{"summary":"Оживить картинку","value":{"model":"kling","prompt":"Камера медленно приближается","parameters":{"scenario":"i2v","engine":"v3","quality":"std","duration":5},"images":["https://example.com/photo.jpg"]}},"music":{"summary":"Песня","value":{"model":"suno","prompt":"Тёплая песня о дороге домой","parameters":{"task":"generate","instrumental":false}}},"document":{"summary":"Презентация","value":{"model":"gamma","prompt":"Презентация о солнечной энергетике для школьников","parameters":{"format":"presentation","num_cards":8}}},"webhook":{"summary":"С уведомлением по готовности","value":{"model":"nano-banana-2","prompt":"Логотип кофейни, минимализм","webhook_url":"https://example.com/hooks/epicai"}},"image_upscale":{"summary":"Увеличить картинку Midjourney","value":{"model":"midjourney","parameters":{"task":"upscale","upscale_type":"subtle"},"source":{"task":"task_595ef35bd62fd815d180b829","image":2}}},"music_wav":{"summary":"Сохранить трек Suno в WAV","value":{"model":"suno","parameters":{"task":"wav"},"source":{"task":"task_8eea7e79b44773a9675c6db7","track":2}}}}}}},"responses":{"200":{"description":"Повтор запроса с тем же `Idempotency-Key`: возвращена уже созданная задача.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"},"Idempotent-Replayed":{"description":"Всегда `true`: ответ повторяет первый запрос.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"202":{"description":"Задача принята и продолжается после ответа. Так отвечают модели, у которых вендор работает синхронно, если сервер умеет отвечать раньше окончания работы. Тело то же, что при 201.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"},"Location":{"description":"Адрес задачи, `/v1/tasks/{id}`.","schema":{"type":"string","format":"uri"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"201":{"description":"Задача создана.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"},"Location":{"description":"Адрес задачи, `/v1/tasks/{id}`.","schema":{"type":"string","format":"uri"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"409":{"$ref":"#/components/responses/Conflict"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/ServerError"},"503":{"$ref":"#/components/responses/ServerError"},"504":{"$ref":"#/components/responses/ServerError"}}},"get":{"tags":["Задачи"],"operationId":"listTasks","summary":"Список задач","description":"Задачи всех ключей владельца в том же пространстве (личном или организации), свежие первыми. Следующая страница запрашивается параметром `after` со значением `next_after` из прошлого ответа.","parameters":[{"name":"limit","in":"query","description":"Сколько задач вернуть.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"after","in":"query","description":"Номер задачи, после которой начинать список.","schema":{"type":"string","pattern":"^task_[0-9a-f]{24}$"}},{"name":"status","in":"query","description":"Только задачи в этом состоянии.","schema":{"type":"string","enum":["queued","in_progress","succeeded","failed"]}},{"name":"model","in":"query","description":"Только задачи этой модели.","schema":{"type":"string"}}],"responses":{"200":{"description":"Страница задач.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/tasks/{id}":{"get":{"tags":["Задачи"],"operationId":"getTask","summary":"Состояние и результат задачи","description":"Возвращает задачу. Запрос сам проверяет, как дела у вендора, поэтому ждать фонового обхода не нужно. Пока задача в работе (`queued` или `in_progress`), в ответе заголовок `Retry-After: 3`, опрашивайте не чаще раза в 3 секунды. Когда задача завершена, в `output` лежат ссылки на файлы, они действуют 7 суток (`expires_at`), после чего файлы стираются, а в задаче остаётся `expired: true`.","parameters":[{"name":"id","in":"path","required":true,"description":"Номер задачи вида `task_…`.","schema":{"type":"string","pattern":"^task_[0-9a-f]{24}$"}}],"responses":{"200":{"description":"Задача.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"},"Retry-After":{"description":"Есть, пока задача в работе: через сколько секунд спросить снова.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/images/generations":{"post":{"tags":["Картинки"],"operationId":"createImage","summary":"Создать картинку","description":"Запрос в форме OpenAI Images. Работают клиенты OpenAI, где можно указать свой `base_url`. Только картинки: для остальных моделей служит `POST /tasks`.\n\n**Ожидание.** Запрос держится открытым, пока картинка не готова (обычно до пары минут, предельное ожидание около 100 секунд). Если за это время результата нет, ответ 202 с задачей, и дальше её нужно забирать через `GET /tasks/{id}`. Заголовок `Prefer: respond-async` или поле `async: true` сразу вернут задачу.\n\n**Параметры модели** (`size`, `quality`, `aspect_ratio`, `resolution` и другие, их список в `GET /models/{id}`) можно писать прямо в теле запроса, как у OpenAI, или внутри `parameters`. Поле `n` может быть только 1. `response_format` принимает `url` (по умолчанию) и `b64_json`. Остальное, как у `POST /tasks`: цена, входные файлы в `images`, вебхук, `Idempotency-Key`.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Защита от двойного запуска при повторе запроса.","schema":{"type":"string","maxLength":64,"pattern":"^[A-Za-z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageRequest"},"examples":{"simple":{"summary":"Простой запрос","value":{"model":"nano-banana-2","prompt":"Маяк на скале в шторм, масло","aspect_ratio":"16:9"}},"edit":{"summary":"С картинкой-референсом","value":{"model":"gpt-image-2","prompt":"Сделай фон закатным","images":["https://example.com/photo.jpg"],"size":"1536x1024"}}}}}},"responses":{"200":{"description":"Картинка готова.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"},"x-epic-cost-tok":{"description":"Списано ТОК.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageResult"}}}},"202":{"description":"Картинка ещё не готова, продолжайте через `GET /tasks/{id}`. Ответ содержит задачу.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"},"Location":{"description":"Адрес задачи.","schema":{"type":"string","format":"uri"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"409":{"$ref":"#/components/responses/Conflict"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/ServerError"},"503":{"$ref":"#/components/responses/ServerError"},"504":{"$ref":"#/components/responses/ServerError"}}}},"/audio/speech":{"post":{"tags":["Звук"],"operationId":"createSpeech","summary":"Озвучить текст","description":"Запрос в форме OpenAI Text-to-Speech. В ответ приходит сам звук `audio/mpeg`, без обёртки JSON; номер задачи в заголовке `x-epic-task`. Если озвучка не успела (предельное ожидание около 100 секунд), ответ 202 с задачей.\n\nТекст можно передать в `input` (как у OpenAI) или в `prompt`. Голос, скорость и другие настройки зависят от модели, их список в `GET /models/{id}`; `voice` и `speed` пишутся прямо в теле или внутри `parameters`. Формат ответа только mp3. Поля `instructions` и `stream_format` не поддерживаются.\n\nЦена зависит от длины текста, её можно узнать через `POST /quote`.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Защита от двойного запуска при повторе запроса.","schema":{"type":"string","maxLength":64,"pattern":"^[A-Za-z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpeechRequest"},"examples":{"simple":{"summary":"Простой запрос","value":{"model":"elevenlabs/eleven-v4","input":"Добро пожаловать в epicai.","voice":"sarah"}}}}}},"responses":{"200":{"description":"Звук mp3.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"},"x-epic-cost-tok":{"description":"Списано ТОК.","schema":{"type":"integer"}},"x-epic-task":{"description":"Номер задачи `task_…`.","schema":{"type":"string"}}},"content":{"audio/mpeg":{"schema":{"type":"string","format":"binary"}}}},"202":{"description":"Озвучка не успела, продолжайте через `GET /tasks/{id}`.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"},"Location":{"description":"Адрес задачи.","schema":{"type":"string","format":"uri"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"409":{"$ref":"#/components/responses/Conflict"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/ServerError"},"503":{"$ref":"#/components/responses/ServerError"},"504":{"$ref":"#/components/responses/ServerError"}}}},"/audio/transcriptions":{"post":{"tags":["Звук"],"operationId":"createTranscription","summary":"Расшифровать речь","description":"Запрос в форме OpenAI Speech-to-Text. Запись передаётся файлом (`multipart/form-data`, поле `file`) или в JSON ссылкой либо строкой `data:audio/…;base64,…`. Запрос держится открытым, пока расшифровка не готова (до 280 секунд), потом отвечает 202 с задачей.\n\n`response_format`. `json` (по умолчанию) возвращает `{text}`; `text` возвращает чистый текст; `verbose_json` добавляет язык, длительность, сегменты и слова, если модель их отдаёт; `srt` и `vtt` возвращают субтитры и доступны только у моделей с таймкодами.\n\nЯзык задаётся полем `language` (код ISO-639-1). Поля `prompt`, `temperature`, `timestamp_granularities` и `chunking_strategy` принимаются для совместимости с клиентами OpenAI и не действуют. Цена зависит от длины записи.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Защита от двойного запуска при повторе запроса.","schema":{"type":"string","maxLength":64,"pattern":"^[A-Za-z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/TranscriptionForm"}},"application/json":{"schema":{"$ref":"#/components/schemas/TranscriptionRequest"},"examples":{"link":{"summary":"Запись по ссылке","value":{"model":"gpt-transcribe","file":"https://example.com/record.mp3","language":"ru"}}}}}},"responses":{"200":{"description":"Расшифровка. Форма зависит от `response_format`.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"},"x-epic-cost-tok":{"description":"Списано ТОК.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transcription"}},"text/plain":{"schema":{"type":"string"}},"application/x-subrip":{"schema":{"type":"string"}},"text/vtt":{"schema":{"type":"string"}}}},"202":{"description":"Расшифровка не успела, продолжайте через `GET /tasks/{id}`.","headers":{"x-request-id":{"$ref":"#/components/headers/RequestId"},"x-ratelimit-remaining-requests":{"$ref":"#/components/headers/RateRemaining"},"Location":{"description":"Адрес задачи.","schema":{"type":"string","format":"uri"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"409":{"$ref":"#/components/responses/Conflict"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/ServerError"},"503":{"$ref":"#/components/responses/ServerError"},"504":{"$ref":"#/components/responses/ServerError"}}}},"/account":{"get":{"tags":["Аккаунт"],"operationId":"getAccount","summary":"Баланс и состояние ключа","description":"Показывает баланс источника, из которого платит ключ (личный баланс или кошелёк организации), и расход ключа за сегодня и за месяц.","responses":{"200":{"description":"Состояние ключа и баланса.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/usage":{"get":{"tags":["Аккаунт"],"operationId":"getUsage","summary":"Статистика расхода","description":"Расход всех ключей владельца ключа в том же пространстве (личном или организации) за период. Даты включительно, по Москве. Период не длиннее 92 дней; по умолчанию последние 30 суток.","parameters":[{"name":"from","in":"query","description":"Начало периода, ГГГГ-ММ-ДД.","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","description":"Конец периода, ГГГГ-ММ-ДД. По умолчанию сегодня.","schema":{"type":"string","format":"date"}},{"name":"group_by","in":"query","description":"Группировка строк.","schema":{"type":"string","enum":["day","model","key"],"default":"day"}}],"responses":{"200":{"description":"Отчёт о расходе.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageReport"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}}},"webhooks":{"taskFinished":{"post":{"tags":["Задачи"],"operationId":"taskFinishedWebhook","summary":"Задача завершилась","description":"epicai присылает POST на `webhook_url`, указанный в задаче, когда она завершилась успешно (`task.succeeded`) или неудачно (`task.failed`). Адрес должен быть `https://` на публичном сервере, порт 443, без логина и пароля.\n\n**Подпись.** Заголовок `X-Epic-Signature: t=<unix-время>,v1=<подпись>`. Подпись это HMAC-SHA256 от строки `<t>.<тело запроса как есть>` с секретом вашего ключа (`key.webhook_secret` из `GET /account`), в шестнадцатеричной записи. Сверяйте подпись и отбрасывайте события, у которых `t` старше пяти минут.\n\n**Доставка.** Ответ с кодом 2xx в течение 10 секунд считается принятым. Иначе доставка повторяется, всего до 6 попыток с паузами 1 минута, 5 минут, 30 минут, 2 часа и 6 часов. Событие может прийти повторно, различайте их по `data.id`. Вебхук ускоряет получение результата, но не заменяет `GET /tasks/{id}`: если событие потерялось, задача всё равно доступна по номеру.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Событие принято (любой код 2xx)."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"sk-epic-…","description":"Ключ API из кабинета разработчика. Заголовок `Authorization: Bearer sk-epic-…`."}},"headers":{"RequestId":{"description":"Номер запроса `req_…`. Его же сервер пишет в журнал вызовов; назовите его в поддержке.","schema":{"type":"string"}},"RateLimit":{"description":"Лимит запросов в минуту для ключа.","schema":{"type":"integer"}},"RateRemaining":{"description":"Сколько запросов осталось в текущей минуте.","schema":{"type":"integer"}},"RateReset":{"description":"Через сколько секунд начнётся новая минута, например `37s`.","schema":{"type":"string"}}},"responses":{"BadRequest":{"description":"Запрос составлен неверно (коды `invalid_json`, `missing_required_parameter`, `invalid_parameter`, `unknown_parameter`, `unsupported_parameter`, `unsupported_parameters`, `unsupported_model`, `unsupported_content`, `invalid_image`, `invalid_input`, `prompt_too_long`, `result_too_large`, `context_length_exceeded`, `content_filter`, `invalid_request`). В `param` указано, какое поле не подошло; ошибки внутри параметров модели имеют вид `parameters.имя`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Ключ не передан, неверный, отозван или просрочен (`invalid_api_key`, `api_key_revoked`, `api_key_expired`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PaymentRequired":{"description":"Недостаточно токенов или достигнут лимит организации (`insufficient_funds`, `organization_limit_reached`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Доступ запрещён (`api_key_blocked`, `api_access_closed`, `ip_not_allowed`, `account_suspended`, `email_not_confirmed`, `organization_inactive`, `model_not_allowed`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Модель, задача или адрес не найдены (`model_not_found`, `task_not_found`, `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"TooLarge":{"description":"Тело запроса или входной файл больше допустимого (`request_too_large`, `input_too_large`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Ключ `Idempotency-Key` уже использован с другими параметрами (`idempotency_conflict`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Превышен лимит (`rate_limit_exceeded`, `too_many_concurrent_requests`, `too_many_active_tasks`, `key_day_cap_reached`, `key_month_cap_reached`, `balance_busy`, `too_many_failed_attempts`). Повторите запрос через время из `Retry-After`.","headers":{"Retry-After":{"description":"Через сколько секунд можно повторить.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Сбой на стороне сервиса или вендора модели (`internal_error`, `upstream_error`, `upstream_unavailable`, `upstream_timeout`, `upstream_unreachable`, `model_unavailable`, `empty_response`, `empty_result`, `billing_unavailable`, `api_disabled`, `media_disabled`, `task_unavailable`, `storage_unavailable`). У задач то же самое приходит в `error` готовой задачи со статусом `failed`. Токены за такой вызов не списываются, кроме случая, когда часть потока уже отдана клиенту.","headers":{"Retry-After":{"description":"Через сколько секунд повторить, если сервис знает.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["message","type","code"],"properties":{"message":{"type":"string","description":"Описание для человека."},"type":{"type":"string","enum":["invalid_request_error","authentication_error","permission_error","rate_limit_error","insufficient_quota","server_error"]},"param":{"type":["string","null"],"description":"Имя параметра запроса, если ошибка в нём."},"code":{"type":"string","description":"Стабильный код ошибки."}}}},"examples":[{"error":{"message":"Недостаточно токенов: для запроса нужно зарезервировать до 30045 ТОК (вход плюс максимум ответа), доступно 100. Пополните баланс или уменьшите max_tokens","type":"insufficient_quota","param":null,"code":"insufficient_funds"}}]},"Model":{"type":"object","required":["id","object"],"properties":{"id":{"type":"string","description":"Имя модели для поля `model` в запросе.","examples":["claude-haiku-5-5"]},"object":{"type":"string","const":"model"},"type":{"type":"string","enum":["chat","image","video","music","speech","transcription","document"],"description":"Вид модели. `chat` работает через `/chat/completions`, остальные через `/tasks`, а картинки, озвучка и расшифровка ещё и через свои адреса."},"endpoints":{"type":"array","items":{"type":"string"},"description":"Адреса, через которые модель запускается. Есть у нетекстовых моделей.","examples":[["POST /v1/images/generations","POST /v1/tasks"]]},"parameters":{"type":"object","additionalProperties":true,"description":"JSON Schema параметров модели. Только в `GET /models/{id}` у нетекстовых моделей."},"inputs":{"type":"object","description":"Сколько входных файлов принимает модель: максимум картинок, видео, аудио и минимум картинок. Только в `GET /models/{id}`.","properties":{"image":{"type":"integer"},"video":{"type":"integer"},"audio":{"type":"integer"},"image_min":{"type":"integer"}}},"inputs_by":{"type":"object","additionalProperties":true,"description":"То же по значениям параметра, если число файлов от него зависит, например по `scenario`."},"input_files":{"type":"object","description":"Форматы и предельный размер входных файлов по видам. Только в `GET /models/{id}` у моделей, которые принимают входные файлы.","properties":{"image":{"$ref":"#/components/schemas/InputFileLimit"},"video":{"$ref":"#/components/schemas/InputFileLimit"},"audio":{"$ref":"#/components/schemas/InputFileLimit"}}},"prompt_max":{"type":"integer","description":"Предельная длина текста запроса, знаков."},"prompt_required":{"type":"boolean","description":"Текст запроса обязателен."},"created":{"type":"integer","description":"Всегда 0: совместимость с клиентами OpenAI."},"owned_by":{"type":"string","description":"Разработчик модели."},"name":{"type":"string","description":"Название модели на сайте."},"context_window":{"type":"integer","description":"Окно контекста, токенов."},"capabilities":{"type":"object","properties":{"vision":{"type":"boolean","description":"Принимает изображения."},"tools":{"type":"boolean","description":"Поддерживает вызов функций."},"reasoning":{"type":"boolean","description":"Модель с рассуждениями (работает `reasoning_effort`)."},"streaming":{"type":"boolean"}}},"pricing":{"type":"object","description":"Цены в токенах сайта (ТОК) за 1 млн токенов.","properties":{"currency":{"type":"string","const":"TOK"},"unit":{"type":"string","enum":["1M tokens","task"],"description":"`1M tokens` у текстовых моделей, `task` у остальных."},"free":{"type":"boolean"},"quote":{"type":"string","description":"Как узнать цену задачи. Есть у нетекстовых моделей.","examples":["POST /v1/quote"]},"examples":{"type":"array","description":"Цены типичных сочетаний параметров. Только в `GET /models/{id}`.","items":{"type":"object","properties":{"parameters":{"type":"object","additionalProperties":true},"tokens":{"type":"integer"}}}},"examples_for":{"type":"string","description":"К какой задаче относятся цены из `examples`, например «задача с 5 карточками».","examples":["задача с 5 карточками (цена растёт с их числом)"]},"depends_on_inputs":{"type":"boolean","description":"Только у видеомоделей. Цена зависит ещё от числа или длины входных файлов, точное значение даёт `POST /quote`. У озвучки и расшифровки цена зависит от длины текста и записи, но флага нет."},"input":{"type":"number","description":"Обычный вход."},"output":{"type":"number","description":"Выход, включая рассуждения."},"cached_input":{"type":"number","description":"Вход, прочитанный из кэша вендора."}}},"source_by":{"type":"object","description":"Есть у моделей с операциями над готовым результатом (Midjourney, Suno). `values` — какие значения параметра `parameter` (всегда `task`) требуют поле `source`, откуда берётся результат и что в `source` выбирают: `image`, `track` или ничего (`null`).","properties":{"parameter":{"type":"string"},"values":{"type":"object","additionalProperties":{"type":"object","properties":{"source":{"type":"string","description":"Какой должна быть задача-источник."},"select":{"type":["string","null"],"enum":["image","track",null]}}}}}}}},"ChatCompletionRequest":{"type":"object","required":["model","messages"],"properties":{"model":{"type":"string","description":"Имя модели из `GET /v1/models`."},"messages":{"type":"array","minItems":1,"maxItems":2000,"description":"Диалог. Последним должно идти сообщение `user` или `tool`. Роль `developer` приравнивается к `system`.","items":{"$ref":"#/components/schemas/Message"}},"stream":{"type":"boolean","default":false,"description":"Вернуть ответ потоком Server-Sent Events."},"stream_options":{"type":"object","properties":{"include_usage":{"type":"boolean","description":"Прислать перед `[DONE]` кадр с `usage` и `epic.cost_tok`."}}},"max_tokens":{"type":"integer","minimum":1,"description":"Максимум токенов ответа. Если не задан, берётся значение по умолчанию (8192, для моделей с рассуждениями 16384). Верхний предел 65536."},"max_completion_tokens":{"type":"integer","minimum":1,"description":"То же, что `max_tokens`; если заданы оба, действует `max_completion_tokens`."},"temperature":{"type":"number","minimum":0,"maximum":2},"top_p":{"type":"number","minimum":0,"maximum":1},"presence_penalty":{"type":"number","minimum":-2,"maximum":2},"frequency_penalty":{"type":"number","minimum":-2,"maximum":2},"seed":{"type":"integer"},"stop":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"},"maxItems":4}],"description":"До четырёх стоп-последовательностей по 64 символа."},"reasoning_effort":{"type":"string","enum":["none","minimal","low","medium","high","xhigh"],"description":"Глубина рассуждений для моделей, которые это умеют. `none` отключает рассуждения там, где это возможно."},"tools":{"type":"array","maxItems":128,"items":{"$ref":"#/components/schemas/Tool"},"description":"Функции, которые может вызвать модель. Суммарное описание до 256 КБ."},"tool_choice":{"description":"Как модель выбирает функции.","oneOf":[{"type":"string","enum":["auto","none","required"]},{"type":"object","required":["type","function"],"properties":{"type":{"const":"function"},"function":{"type":"object","required":["name"],"properties":{"name":{"type":"string"}}}}}]},"parallel_tool_calls":{"type":"boolean","description":"Разрешить вызывать несколько функций за раз."},"response_format":{"description":"Формат ответа. Для json_object в сообщениях должно встречаться слово JSON, иначе ответ 400 invalid_parameter.","oneOf":[{"type":"object","required":["type"],"properties":{"type":{"const":"text"}}},{"type":"object","required":["type"],"properties":{"type":{"const":"json_object"}}},{"type":"object","required":["type","json_schema"],"properties":{"type":{"const":"json_schema"},"json_schema":{"type":"object","required":["name","schema"],"properties":{"name":{"type":"string"},"strict":{"type":"boolean"},"schema":{"type":"object","description":"JSON Schema ответа."}}}}}]},"user":{"type":"string","description":"Принимается для совместимости, вендору не передаётся."}}},"Message":{"oneOf":[{"type":"object","title":"system / developer","required":["role","content"],"properties":{"role":{"type":"string","enum":["system","developer"]},"content":{"$ref":"#/components/schemas/TextContent"}}},{"type":"object","title":"user","required":["role","content"],"properties":{"role":{"const":"user"},"content":{"oneOf":[{"type":"string"},{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/TextPart"},{"$ref":"#/components/schemas/ImagePart"}]}}]}}},{"type":"object","title":"assistant","required":["role"],"properties":{"role":{"const":"assistant"},"content":{"oneOf":[{"$ref":"#/components/schemas/TextContent"},{"type":"null"}]},"tool_calls":{"type":"array","items":{"$ref":"#/components/schemas/ToolCall"}}}},{"type":"object","title":"tool","required":["role","tool_call_id","content"],"properties":{"role":{"const":"tool"},"tool_call_id":{"type":"string"},"content":{"$ref":"#/components/schemas/TextContent"}}}]},"TextContent":{"oneOf":[{"type":"string"},{"type":"array","items":{"$ref":"#/components/schemas/TextPart"}}]},"TextPart":{"type":"object","required":["type","text"],"properties":{"type":{"const":"text"},"text":{"type":"string"}}},"ImagePart":{"type":"object","required":["type","image_url"],"properties":{"type":{"const":"image_url"},"image_url":{"type":"object","required":["url"],"properties":{"url":{"type":"string","description":"Ссылка `http(s)` или `data:image/png|jpeg|gif|webp;base64,…`."},"detail":{"type":"string","enum":["low","high","auto"]}}}}},"Tool":{"type":"object","required":["type","function"],"properties":{"type":{"const":"function"},"function":{"type":"object","required":["name"],"properties":{"name":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$"},"description":{"type":"string"},"parameters":{"type":"object","description":"JSON Schema аргументов."},"strict":{"type":"boolean"}}}}},"ToolCall":{"type":"object","required":["id","type","function"],"properties":{"id":{"type":"string"},"type":{"const":"function"},"function":{"type":"object","required":["name","arguments"],"properties":{"name":{"type":"string"},"arguments":{"type":"string","description":"Аргументы строкой JSON."}}}}},"Usage":{"type":"object","properties":{"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer","description":"Включает токены рассуждений."},"total_tokens":{"type":"integer"},"prompt_tokens_details":{"type":"object","properties":{"cached_tokens":{"type":"integer"}}},"completion_tokens_details":{"type":"object","properties":{"reasoning_tokens":{"type":"integer"}}}}},"EpicInfo":{"type":"object","description":"Расширение epicai.","properties":{"cost_tok":{"type":"integer","description":"Списано ТОК за этот вызов."},"request_id":{"type":"string","description":"Номер запроса, он же в заголовке `x-request-id`."}}},"ChatCompletion":{"type":"object","required":["id","object","created","model","choices"],"properties":{"id":{"type":"string","examples":["chatcmpl-4d90e80d34e073e9fa11e17a"]},"object":{"const":"chat.completion"},"created":{"type":"integer"},"model":{"type":"string"},"choices":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"message":{"type":"object","properties":{"role":{"const":"assistant"},"content":{"type":["string","null"]},"reasoning_content":{"type":"string","description":"Рассуждения модели, если вендор их отдаёт."},"tool_calls":{"type":"array","items":{"$ref":"#/components/schemas/ToolCall"}}}},"finish_reason":{"type":"string","enum":["stop","length","tool_calls","content_filter"]}}}},"usage":{"$ref":"#/components/schemas/Usage"},"epic":{"$ref":"#/components/schemas/EpicInfo"}}},"ChatCompletionChunk":{"type":"object","description":"Кадр потока. Первый кадр несёт роль, дальше идут дельты, затем кадр с `finish_reason`, при `include_usage` кадр с `usage` и `epic`, затем `[DONE]`.","properties":{"id":{"type":"string"},"object":{"const":"chat.completion.chunk"},"created":{"type":"integer"},"model":{"type":"string"},"choices":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"delta":{"type":"object","properties":{"role":{"type":"string"},"content":{"type":"string"},"reasoning_content":{"type":"string"},"tool_calls":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"id":{"type":"string"},"type":{"const":"function"},"function":{"type":"object","properties":{"name":{"type":"string"},"arguments":{"type":"string"}}}}}}}},"finish_reason":{"type":["string","null"]}}}},"usage":{"$ref":"#/components/schemas/Usage"},"epic":{"$ref":"#/components/schemas/EpicInfo"}}},"TaskRequest":{"type":"object","required":["model"],"additionalProperties":false,"properties":{"model":{"type":"string","description":"Имя модели из `GET /models` (любого типа, кроме `chat`)."},"prompt":{"type":"string","description":"Описание или текст задачи. Предельная длина и обязательность зависят от модели: поля `prompt_max` и `prompt_required` в `GET /models/{id}`. Для озвучки это текст, который нужно озвучить."},"parameters":{"type":"object","description":"Параметры модели по её схеме из `GET /models/{id}`, например `quality`, `duration`, `aspect_ratio`. Не указанные берутся по умолчанию.","additionalProperties":true},"images":{"type":"array","description":"Входные картинки: референсы, первый и последний кадр, исходник для правок. Сколько их принимает модель при выбранных параметрах, написано в `inputs` и `inputs_by`.","items":{"oneOf":[{"type":"string","description":"Ссылка `http(s)` или `data:image/png|jpeg|webp;base64,…`, до 10 МБ."},{"type":"object","required":["url"],"properties":{"url":{"type":"string"}}}]}},"videos":{"type":"array","description":"Входные видео (перерисовка, перенос движения, лицо и голос). Ссылка `http(s)` или `data:video/…;base64,…`.","items":{"type":"string"}},"audios":{"type":"array","description":"Входные записи (песня для обработки, голос, речь для оживления лица). Ссылка `http(s)` или `data:audio/…;base64,…`.","items":{"type":"string"}},"webhook_url":{"type":"string","format":"uri","description":"Адрес `https://` для уведомления о завершении. Порт 443, публичный сервер."},"source":{"$ref":"#/components/schemas/TaskSource","description":"Для операций над готовым результатом: увеличение, вариации и видео из картинки Midjourney, продолжение, WAV, текст по времени и клип к треку Suno. Какие значения параметра `task` требуют `source`, написано в поле `source_by` модели."}}},"QuoteRequest":{"type":"object","required":["model"],"additionalProperties":false,"properties":{"model":{"type":"string"},"prompt":{"type":"string","description":"Нужен там, где цена зависит от длины текста (озвучка)."},"parameters":{"type":"object","additionalProperties":true},"images":{"description":"Число картинок или сами картинки (как в `POST /tasks`).","oneOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"array","items":{"type":"string"}}]},"videos":{"type":"array","description":"Для каждого видео длительность в секундах числом или ссылка на файл.","items":{"oneOf":[{"type":"number"},{"type":"string"}]}},"audios":{"type":"array","description":"Для каждой записи длительность в секундах числом или ссылка на файл.","items":{"oneOf":[{"type":"number"},{"type":"string"}]}},"source":{"$ref":"#/components/schemas/TaskSource","description":"Принимается, чтобы тело задачи подходило и для котировки. Цена от источника не зависит."}}},"Quote":{"type":"object","required":["object","model","price"],"properties":{"object":{"const":"quote"},"model":{"type":"string"},"price":{"type":"object","properties":{"currency":{"const":"TOK"},"tokens":{"type":"integer","description":"Цена задачи, ТОК. У бесплатных моделей 0."},"base":{"type":"integer","description":"Цена без ценовой акции."},"discount":{"type":["object","null"],"description":"Действующая акция, если есть.","properties":{"percent":{"type":"integer"}}}}},"parameters":{"type":"object","additionalProperties":true,"description":"Параметры, как они будут применены, с подстановкой значений по умолчанию."}}},"InputFileLimit":{"type":"object","properties":{"formats":{"type":"array","items":{"type":"string"},"description":"Допустимые типы файла (MIME)."},"max_bytes":{"type":"integer","description":"Предельный размер одного файла, байт."}}},"TaskFile":{"type":"object","required":["type","url","mime","bytes"],"properties":{"type":{"type":"string","enum":["image","video","audio","text","document"]},"url":{"type":"string","format":"uri","description":"Ссылка на файл. Открывается без ключа, действует до `expires_at`."},"mime":{"type":"string"},"bytes":{"type":"integer"},"width":{"type":"integer","description":"Только у картинок."},"height":{"type":"integer","description":"Только у картинок."}}},"Task":{"type":"object","required":["id","object","type","model","status","created_at","price","parameters"],"properties":{"id":{"type":"string","pattern":"^task_[0-9a-f]{24}$","examples":["task_7fa4be5e14351e3dff994aa3"]},"object":{"const":"task"},"type":{"type":"string","enum":["image","video","music","speech","transcription","document"],"description":"Вид модели."},"model":{"type":"string"},"status":{"type":"string","enum":["queued","in_progress","succeeded","failed"],"description":"`queued` и `in_progress` значат, что задача в работе; `succeeded` и `failed` окончательные."},"created_at":{"type":"integer","description":"Unix-время создания."},"started_at":{"type":["integer","null"]},"finished_at":{"type":["integer","null"]},"price":{"type":"object","properties":{"tokens":{"type":"integer","description":"Цена задачи, ТОК. Зафиксирована при создании."},"charged":{"type":"integer","description":"Списано: цена после успеха, 0 пока задача идёт и после неудачи."}}},"parameters":{"type":"object","additionalProperties":true,"description":"Параметры, с которыми работает задача, включая подставленные по умолчанию."},"output":{"type":"array","description":"Файлы результата, есть у `succeeded`. Картинки и видео приходят одним-несколькими файлами. У музыки и документов, кроме звука и PDF, может быть файл `.json` с описанием (названия, теги, текст песни, разбор дорожек), у расшифровки текст `.txt`, у описания картинки Midjourney текст `.txt` и `.json`.","items":{"$ref":"#/components/schemas/TaskFile"}},"expires_at":{"type":["integer","null"],"description":"До какого времени действуют ссылки в `output`."},"expired":{"type":"boolean","description":"Файлы стёрты по сроку хранения."},"error":{"type":"object","description":"Причина неудачи, есть у `failed`. Токены за такую задачу не списаны.","properties":{"code":{"type":"string","description":"Стабильный код, например `content_filter`, `prompt_too_long`, `input_unavailable`, `upstream_timeout`, `task_timeout`, `generation_failed`, `empty_result`."},"message":{"type":"string"}}},"source":{"type":"object","description":"Источник операции над результатом: номер задачи и выбранный номер картинки или трека. Есть только у операций.","properties":{"task":{"type":"string"},"image":{"type":"integer"},"track":{"type":"integer"}}}}},"TaskList":{"type":"object","required":["object","data","has_more"],"properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"has_more":{"type":"boolean"},"next_after":{"type":"string","description":"Значение для параметра `after` следующего запроса. Есть, если `has_more` истина."}}},"ImageRequest":{"type":"object","required":["model","prompt"],"additionalProperties":true,"description":"Служебные поля ниже; все остальные поля верхнего уровня считаются параметрами модели.","properties":{"model":{"type":"string","description":"Модель-картинка из `GET /models?type=image`."},"prompt":{"type":"string"},"n":{"type":"integer","const":1,"default":1},"response_format":{"type":"string","enum":["url","b64_json"],"default":"url"},"images":{"type":"array","description":"Входные картинки, как в `POST /tasks`.","items":{"type":"string"}},"parameters":{"type":"object","additionalProperties":true},"webhook_url":{"type":"string","format":"uri"},"async":{"type":"boolean","default":false,"description":"Не ждать результата, сразу вернуть задачу (202)."},"user":{"type":"string","description":"Принимается для совместимости, не используется."}}},"ImageResult":{"type":"object","required":["created","data"],"properties":{"created":{"type":"integer"},"data":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"b64_json":{"type":"string","description":"Картинка в base64, если запрошен `response_format=b64_json` и она не больше 48 МБ."}}}},"epicai":{"type":"object","properties":{"task":{"type":"string"},"price":{"type":"object","properties":{"tokens":{"type":"integer"},"charged":{"type":"integer"}}},"expires_at":{"type":["integer","null"]}}}}},"SpeechRequest":{"type":"object","required":["model"],"additionalProperties":true,"description":"Служебные поля ниже; `voice`, `speed` и другие поля верхнего уровня считаются параметрами модели.","properties":{"model":{"type":"string","description":"Модель из `GET /models?type=speech`."},"input":{"type":"string","description":"Текст для озвучки. Вместо него можно передать `prompt`, но не оба поля сразу."},"prompt":{"type":"string"},"voice":{"type":"string","description":"Голос, список зависит от модели."},"speed":{"type":"number","description":"Скорость речи, если модель её регулирует."},"response_format":{"type":"string","enum":["mp3"],"default":"mp3"},"parameters":{"type":"object","additionalProperties":true},"webhook_url":{"type":"string","format":"uri"}}},"TranscriptionForm":{"type":"object","required":["model","file"],"properties":{"file":{"type":"string","format":"binary","description":"Запись, mp3, wav, m4a, ogg, flac, aac, webm или mp4. Предельный размер задаёт модель и сервер."},"model":{"type":"string","description":"Модель из `GET /models?type=transcription`."},"language":{"type":"string","description":"Язык записи, код ISO-639-1."},"response_format":{"type":"string","enum":["json","text","verbose_json","srt","vtt"],"default":"json"}}},"TranscriptionRequest":{"type":"object","required":["model","file"],"properties":{"model":{"type":"string"},"file":{"type":"string","description":"Ссылка `http(s)` или `data:audio/…;base64,…`."},"language":{"type":"string"},"response_format":{"type":"string","enum":["json","text","verbose_json","srt","vtt"],"default":"json"},"parameters":{"type":"object","additionalProperties":true},"webhook_url":{"type":"string","format":"uri"}}},"Transcription":{"type":"object","required":["text"],"properties":{"text":{"type":"string"},"task":{"type":"string","description":"Только у `verbose_json`."},"language":{"type":"string","description":"Только у `verbose_json`, если модель определяет язык."},"duration":{"type":"number","description":"Только у `verbose_json`, секунды."},"segments":{"type":"array","description":"Только у `verbose_json`, если модель отдаёт таймкоды.","items":{"type":"object","properties":{"start":{"type":"number"},"end":{"type":"number"},"text":{"type":"string"}}}},"words":{"type":"array","description":"Только у `verbose_json`, если модель отдаёт слова.","items":{"type":"object"}},"epicai":{"type":"object","properties":{"task":{"type":"string"},"price":{"type":"object","properties":{"tokens":{"type":"integer"},"charged":{"type":"integer"}}},"expires_at":{"type":["integer","null"]}}}}},"WebhookEvent":{"type":"object","required":["id","object","type","created","data"],"properties":{"id":{"type":"string","examples":["evt_7fa4be5e14351e3dff994aa3_1"]},"object":{"const":"event"},"type":{"type":"string","enum":["task.succeeded","task.failed"]},"created":{"type":"integer"},"data":{"$ref":"#/components/schemas/Task"}}},"Account":{"type":"object","properties":{"object":{"const":"account"},"balance":{"type":"object","properties":{"tokens":{"type":"integer","description":"Баланс, ТОК."},"reserved":{"type":"integer","description":"Зарезервировано под выполняющиеся запросы."},"available":{"type":"integer","description":"Доступно для новых запросов."},"source":{"type":"string","enum":["personal","organization"]},"organization_id":{"type":"integer","description":"Есть у ключа организации."}}},"key":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"prefix":{"type":"string","description":"Начало ключа для опознания."},"created":{"type":"integer","description":"Unix-время создания."},"expires_at":{"type":["integer","null"]},"rate_limit_rpm":{"type":"integer"},"cap_day":{"type":"integer","description":"Дневной потолок, ТОК; 0 без потолка."},"cap_month":{"type":"integer","description":"Месячный потолок, ТОК; 0 без потолка."},"spent_today":{"type":"integer"},"spent_month":{"type":"integer"},"webhook_secret":{"type":["string","null"],"description":"Секрет, которым подписаны вебхуки этого ключа (`whsec_…`). Хранить так же бережно, как сам ключ."}}}}},"UsageRow":{"type":"object","properties":{"day":{"type":"string","format":"date","description":"При `group_by=day`."},"model":{"type":"string","description":"При `group_by=model`."},"model_id":{"type":"integer"},"key_id":{"type":"integer","description":"При `group_by=key`."},"name":{"type":"string","description":"Название ключа при `group_by=key`."},"calls":{"type":"integer"},"errors":{"type":"integer"},"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"cached_tokens":{"type":"integer"},"cost_tok":{"type":"integer"}}},"UsageReport":{"type":"object","properties":{"object":{"const":"usage"},"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"},"group_by":{"type":"string","enum":["day","model","key"]},"total":{"type":"object","properties":{"calls":{"type":"integer"},"errors":{"type":"integer"},"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"cached_tokens":{"type":"integer"},"cost_tok":{"type":"integer"}}},"data":{"type":"array","items":{"$ref":"#/components/schemas/UsageRow"}}}},"TaskSource":{"type":"object","description":"Источник операции над готовым результатом: своя завершённая задача той же модели. Операции перечислены в поле `source_by` описания модели. Midjourney выбирает картинку или ролик полем `image`, Suno выбирает трек полем `track` (номер файла из `output` задачи-источника).","required":["task"],"additionalProperties":false,"properties":{"task":{"type":"string","pattern":"^task_[0-9a-f]{24}$","description":"Номер задачи-источника, она должна быть завершена успешно."},"image":{"type":"integer","minimum":1,"maximum":100,"description":"Midjourney: номер картинки сетки (или ролика, если источник — видео). У одиночной картинки не указывают. У `reroll` не нужен."},"track":{"type":"integer","minimum":1,"maximum":100,"description":"Suno: номер трека, он же номер файла в `output` источника. Можно не указывать, если трек один."}}}}}}