С чего начать
Через API доступно то же, что и в студии: генерация картинок, видео и запросы к языковым моделям. Тарифы одинаковые, деньги списываются с того же баланса, что и при работе через сайт. Отдельного счёта для API нет.
API устроен по правилам REST: вы отправляете HTTP-запрос с ключом в заголовке и получаете JSON в ответ. Никаких SDK ставить не обязательно — хватит curl, requests, axios или узла HTTP в n8n.
Шаг 1. Получить ключ
Зайдите в Настройки → API и нажмите «Создать ключ». Секрет показывается один раз — мы храним только его отпечаток и восстановить исходную строку не можем. Потеряли — отзывайте ключ и создавайте новый.
Ключ — это доступ к вашим деньгам
Любой, у кого есть ключ, тратит ваш баланс. Не кладите его в публичный репозиторий, во фронтенд и в переписку. Для подрядчика заводите отдельный ключ — его можно отозвать, не трогая остальные.
Шаг 2. Проверить, что ключ работает
Самый безопасный первый запрос — узнать баланс. Он ничего не стоит и сразу показывает, принят ли ключ.
export ARK_KEY="ark_live_..."
curl -sS -H "Authorization: Bearer $ARK_KEY" \
https://arckep.ru/api/v1/balanceВ ответе — остаток в рублях. Если пришла ошибка с кодом UNAUTHORIZED, значит ключ скопирован не полностью или уже отозван.
Шаг 3. Первая генерация
Картинки и видео делаются асинхронно: запрос возвращается сразу, а результат появляется позже. В ответ приходит номер задачи, по которому можно спрашивать статус.
curl -sS -X POST https://arckep.ru/api/v1/images/generations \
-H "Authorization: Bearer $ARK_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"model": "gemini-3.1-flash-image",
"prompt": "красное яблоко на мраморном столе"
}'curl -sS -H "Authorization: Bearer $ARK_KEY" \
https://arckep.ru/api/v1/images/generations/123| Что | Значение |
|---|---|
| Адрес API | https://arckep.ru/api/v1 |
| Авторизация | Authorization: Bearer ark_live_… |
| Формат | JSON; загрузка файлов — multipart |
| Валюта | рубли, суммы приходят строкой |
| Версия для LLM-агентов | llms.txt |
Ключи и права доступа
Ключ передаётся в заголовке Authorization с префиксом Bearer. Все ключи начинаются с ark_live_.
Authorization: Bearer ark_live_<ваш секрет>Права (scopes)
У каждого ключа есть набор прав. Это защита от чужой ошибки: ключ, выданный для картинок, не сможет потратить деньги на видео или на языковые модели.
| Право | Что разрешает |
|---|---|
images:write | Создавать картинки, смотреть их статус и список |
videos:write | То же для видео |
chat:write | Запросы к языковым моделям. По умолчанию НЕ выдаётся — включайте осознанно |
balance:read | Смотреть баланс |
uploads:write | Загружать файлы. Также работает, если есть право на картинки или видео |
Если права не указать при создании, ключ получит набор для картинок, видео и чтения баланса. Доступ к языковым моделям нужно запрашивать явно — чтобы случайный ключ не мог жечь деньги на длинных диалогах.
Не хватило права
Придёт ошибка FORBIDDEN, и в поле details.required будет указано, какого именно права не хватает. Добавить право существующему ключу нельзя — создайте новый с нужным набором.
Управление ключами из кода
Обычно ключи создают в интерфейсе, но это можно делать и программно — из сессии студии (обычная авторизация на сайте, не API-ключ).
| Метод | Адрес | Что делает |
|---|---|---|
POST | /api/developer/keys | Создать. В ответе один раз приходят и сам ключ, и секрет для проверки вебхуков |
GET | /api/developer/keys | Список ключей без секретов |
PATCH | /api/developer/keys/{id} | Переименовать или сменить адрес вебхука |
POST | /api/developer/keys/{id}/rotate-webhook-secret | Выдать новый секрет вебхука; старый перестаёт действовать |
DELETE | /api/developer/keys/{id} | Отозвать ключ немедленно и навсегда |
Каталог моделей
Список моделей задаётся на сервере и меняется. Не зашивайте названия из этой страницы в код — спрашивайте каталог у API. Это единственный достоверный источник: там же приходят поддерживаемые пропорции, разрешения, длительности и цены.
curl -sS -H "Authorization: Bearer $ARK_KEY" \
https://arckep.ru/api/v1/modelsКаждая запись имеет поле type: image, video или chat. Оно говорит, в какой раздел API её отправлять.
{
"object": "list",
"data": [
{
"id": "gemini-3.1-flash-image",
"type": "image",
"modes": ["generate", "edit_with_reference"],
"aspect_ratios": ["1:1", "16:9", "9:16"],
"resolutions": ["1K", "2K", "4K"],
"max_images": 1,
"supports_thinking": true
},
{
"id": "wan2.7-t2v",
"type": "video",
"name": "Wan 2.7 T2V",
"modes": ["t2v"],
"max_duration": 10,
"pricing_hint": "… ₽/с"
},
{
"id": "openai/gpt-5.4-mini",
"type": "chat",
"context_window": 400000,
"capabilities": ["vision", "function_calling", "streaming"],
"pricing_rub_per_1m": { "input": 82.5, "output": 495.0 }
}
]
}Почему модели нет в списке
В студии моделей больше, чем в API. Наружу открыты только те, для которых проверен расчёт стоимости. Новые появляются после проверки. Если нужной модели нет — напишите нам, это не техническое ограничение.
Баланс
Показывает тот же остаток, что и в личном кабинете. Если вы состоите в организации и она активна, вернётся баланс организации — с него же и списывается.
{
"balance_rub": "150.00",
"is_corporate": false,
"corporate_name": null
}Суммы всюду приходят строками, а не числами. Это сделано намеренно: дробные рубли в формате JSON-числа теряют точность при округлении. Разбирайте их как десятичные, а не как float.
Загрузка файлов
Чтобы использовать своё изображение как основу для генерации, загрузите его к нам и передайте полученную ссылку. Можно передавать и свою публичную HTTPS-ссылку, но загруженные к нам файлы надёжнее: провайдеры иногда не могут скачать файл со стороннего хостинга.
curl -sS -X POST https://arckep.ru/api/v1/uploads \
-H "Authorization: Bearer $ARK_KEY" \
-F "file=@./reference.png"{
"key": "images/42/9f3c….png",
"url": "https://…подписанная-ссылка…"
}| Параметр | Значение |
|---|---|
| Имя поля формы | file |
| Максимальный размер | 10 МБ |
| Типы | изображения (JPEG, PNG, WebP и другие), а также MP4 и WebM |
| Стоимость | бесплатно |
Ссылка временная
Поле url живёт около суток. Для долгих сценариев сохраняйте key — по нему всегда можно получить свежую ссылку. Не записывайте подписанные ссылки в свою базу как постоянные.
Картинки
Генерация асинхронная. Запрос возвращает 202 и номер задачи сразу — картинки ещё нет. Готовый результат забирают опросом статуса или через вебхук.
Создание
curl -sS -X POST https://arckep.ru/api/v1/images/generations \
-H "Authorization: Bearer $ARK_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"model": "gpt-image-2",
"prompt": "предметная съёмка керамической кружки, мягкий студийный свет",
"n": 2,
"size": "1024x1024",
"quality": "low"
}'| Поле | Тип | Описание |
|---|---|---|
model | строка | Обязательно. Id из каталога с типом image |
prompt | строка | Обязательно. От 1 до 10 000 символов |
n | число | Сколько картинок, 1–8. Синоним — num_images; если заданы оба, побеждает num_images |
aspect_ratio | строка | Пропорции: 1:1, 16:9, 9:16, 3:2, 2:3 и другие. Что поддерживает модель — в каталоге |
size | строка | Для совместимости с OpenAI: 1024x1024 и подобные превращаются в пропорции, если aspect_ratio не задан |
resolution | строка | Например 1K, 2K, 4K — если модель это умеет |
quality | строка | Уровень качества у моделей, где он есть |
thinking | да/нет | Режим «подумать подольше». Дороже, доступен не у всех моделей |
reference_image_urls | список ссылок | Исходники для редактирования или переноса стиля |
webhook_url | строка | Куда прислать уведомление именно об этой задаче (перекрывает адрес ключа) |
С опорным изображением
Некоторые модели умеют редактировать присланную картинку или держать один и тот же объект на разных кадрах. Для них передайте ссылки в reference_image_urls.
curl -sS -X POST https://arckep.ru/api/v1/images/generations \
-H "Authorization: Bearer $ARK_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3-pro-image",
"prompt": "тот же объект, снаружи, закатный свет",
"reference_image_urls": ["https://…ссылка-из-uploads…"],
"webhook_url": "https://hooks.example.com/arckep"
}'Модели-редакторы требуют исходник
Модели редактирования и апскейла без reference_image_urls вернут ошибку сразу, не списав денег. В каталоге у них стоит признак requires_reference_image.
Статус и результат
curl -sS -H "Authorization: Bearer $ARK_KEY" \
https://arckep.ru/api/v1/images/generations/123{
"id": 123,
"object": "image.generation",
"status": "completed",
"model": "gemini-3.1-flash-image",
"created_at": "2026-07-27T12:00:00+00:00",
"completed_at": "2026-07-27T12:00:24+00:00",
"cost_rub": "4.24",
"charged_from": "personal",
"error": null,
"output": {
"images": [
{ "url": "https://arckep.ru/…", "expires_in": null },
{ "url": "https://…подписанная…", "expires_in": 86400 }
]
}
}| Статус | Что значит |
|---|---|
queued | Принято, ждёт очереди |
processing | Модель работает |
completed | Готово, ссылки в output |
failed | Не получилось, причина в error, деньги возвращены |
Поле output заполняется только у завершённых задач. У части ссылок есть expires_in — срок жизни в секундах, примерно сутки. Если ссылка протухла, запросите статус задачи ещё раз и получите свежую.
Сколько будет стоить
Цену можно узнать заранее, ничего не запуская и не списывая. Считается тем же механизмом, что и реальное списание.
curl -sS -X POST https://arckep.ru/api/v1/images/estimate \
-H "Authorization: Bearer $ARK_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gemini-3.1-flash-image", "num_images": 1, "resolution": "1K"}'Список своих задач
Возвращает только задачи, созданные через API. История из веб-студии сюда не попадает никогда — даже если ключ принадлежит тому же аккаунту.
curl -sS -H "Authorization: Bearer $ARK_KEY" \
"https://arckep.ru/api/v1/images/generations?limit=20"Для листания передавайте before_id — номер самой старой задачи из предыдущей страницы. Признак has_more подскажет, есть ли ещё.
Видео
Устроено так же, как картинки: запрос возвращается сразу с номером задачи, готовый ролик появляется позже. Разница в сроках — видео считается от десятков секунд до десятков минут, а у тяжёлых моделей дольше.
Режимы
| Режим | Что делает | Что нужно передать |
|---|---|---|
t2v | Видео по текстовому описанию | только prompt |
i2v | Оживить картинку | обязательно image_url |
r2v | По опорным материалам: персонаж, движение, голос | reference_image_urls / reference_video_urls / reference_audio_urls |
edit | Переделать готовое видео | video_url с исходным роликом |
auto | Режим определяется по тому, что вы прислали | значение по умолчанию |
Не каждая модель умеет всё. Доступные режимы конкретной модели перечислены в каталоге в поле modes. Если модель называется с окончанием -i2v, она работает только от картинки, и текстовый режим для неё вернёт ошибку.
Создание
curl -sS -X POST https://arckep.ru/api/v1/videos/generations \
-H "Authorization: Bearer $ARK_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"model": "wan2.7-t2v",
"prompt": "кинематографичный облёт дроном над туманными горами",
"mode": "t2v",
"duration_seconds": 5,
"aspect_ratio": "16:9",
"with_audio": true
}'curl -sS -X POST https://arckep.ru/api/v1/videos/generations \
-H "Authorization: Bearer $ARK_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "wan2.7-i2v",
"prompt": "медленный наезд камеры, естественное движение",
"mode": "i2v",
"image_url": "https://…ссылка-из-uploads…",
"duration_seconds": 5
}'| Поле | По умолчанию | Описание |
|---|---|---|
model | — | Обязательно, из каталога с типом video |
prompt | — | Описание сцены, до 10 000 символов |
mode | auto | t2v, i2v, r2v, edit или auto |
duration_seconds | 5 | От 1 до 30. Предел конкретной модели смотрите в каталоге |
aspect_ratio | 16:9 | Пропорции кадра |
resolution | — | Например 720p или 1080p, если модель различает |
with_audio | да | Звук у моделей, которые его умеют |
image_url | — | Стартовый кадр. Обязателен для i2v |
last_frame_image_url | — | Финальный кадр — у моделей с интерполяцией |
reference_image_urls | — | Опорные изображения: персонаж, стиль, предметы |
reference_video_urls | — | Опорное видео: движение, монтаж |
reference_audio_urls | — | Опорный звук: озвучка, синхрон губ |
video_url | — | Исходник для режима редактирования |
negative_prompt | — | Чего не должно быть в кадре |
seed | — | Для повторяемости результата |
webhook_url | — | Адрес уведомления для этой задачи |
Видео оплачивается вперёд
В отличие от картинок, деньги за видео списываются сразу при постановке задачи. Если провайдер не смог её принять или ролик в итоге не получился, сумма возвращается на баланс автоматически.
Автоматическая длительность
У части моделей длительность выбирает сама модель. Для таких запросов передайте auto_duration. Резервируется максимальная длительность, а после готовности лишнее возвращается — вы платите за фактический хронометраж.
Статус и результат
{
"id": 456,
"object": "video.generation",
"status": "completed",
"model": "wan2.7-t2v",
"cost_rub": "25.00",
"charged_from": "personal",
"error": null,
"output": {
"video_url": "https://…подписанная…",
"thumbnail_url": "https://…подписанная…",
"duration_seconds": 5
}
}Статус берётся из нашей базы: мы сами опрашиваем провайдера в фоне, вам не нужно держать соединение или повторять запрос к нему. Ссылки на видео и превью — временные, примерно на сутки; за свежими просто запросите задачу снова.
Предварительный расчёт цены — POST /api/v1/videos/estimate с моделью, длительностью, разрешением и признаком звука. Список своих задач и листание работают так же, как у картинок.
Языковые модели (чат)
Единственная синхронная часть API: ответ приходит в том же запросе. Формат совместим с OpenAI, поэтому подходят готовые библиотеки — достаточно подменить адрес и ключ.
Нужно право chat:write
По умолчанию новый ключ его не получает. Создавая ключ, укажите это право явно — иначе запрос вернёт FORBIDDEN.
Обычный запрос
curl -sS -X POST https://arckep.ru/api/v1/chat/completions \
-H "Authorization: Bearer $ARK_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.4-mini",
"messages": [
{"role": "system", "content": "Отвечай кратко."},
{"role": "user", "content": "Сколько будет 2+2?"}
],
"stream": false,
"temperature": 0.2,
"max_tokens": 256
}'{
"id": "chatcmpl-…",
"object": "chat.completion",
"model": "openai/gpt-5.4-mini",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "4" },
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 24,
"completion_tokens": 1,
"total_tokens": 25,
"cost_rub": "0.0123"
}
}Поле usage.cost_rub — наше дополнение к формату OpenAI: сколько списано за этот запрос в рублях. Приходит после фактического списания.
Потоковый ответ
С stream: true ответ отдаётся кусками в формате server-sent events, как у OpenAI. Поток заканчивается строкой data: [DONE], а в предпоследнем куске приходит usage с итоговой стоимостью.
curl -sSN -X POST https://arckep.ru/api/v1/chat/completions \
-H "Authorization: Bearer $ARK_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"xai/grok-4.3","messages":[{"role":"user","content":"Привет"}],"stream":true}'Через библиотеку OpenAI
from openai import OpenAI
client = OpenAI(
api_key="ark_live_…", # ключ должен иметь право chat:write
base_url="https://arckep.ru/api/v1",
)
r = client.chat.completions.create(
model="openai/gpt-5.4-mini",
messages=[{"role": "user", "content": "Привет"}],
)
print(r.choices[0].message.content)Вызов функций
Модель может попросить вызвать вашу функцию. Опишите функции в поле tools в формате OpenAI. Выполняете их вы у себя — мы ничего не запускаем, только передаём запрос и ответ.
{
"model": "openai/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"
}Если модель решила вызвать функцию, в ответе будет finish_reason: tool_calls и список вызовов. Выполните их и продолжите диалог, добавив сообщения с ролью tool и полем tool_call_id. Несколько вызовов за один ход поддерживаются.
Только обычные функции
Встроенные инструменты провайдеров — интерпретатор кода, поиск по файлам и прочие — отклоняются. Они тарифицируются отдельно и по чужим правилам. Разрешены только описания с type: function.
Поиск в интернете
Флаг web_search: true включает встроенный поиск провайдера — модель сама ищет свежие данные. Работает у Anthropic, Google и xAI. У обычных моделей OpenAI такого режима в этом формате нет: запрос вернёт ошибку 400 с пояснением, а не молча выполнится без поиска.
curl -sS -X POST https://arckep.ru/api/v1/chat/completions \
-H "Authorization: Bearer $ARK_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google-ai-studio/gemini-3.5-flash",
"messages": [{"role": "user", "content": "Что сегодня в новостях технологий?"}],
"web_search": true,
"max_tokens": 1024
}'Поиск оплачивается отдельно
Помимо токенов провайдер берёт плату за каждый поисковый запрос, и она включается в стоимость. Какие модели поддерживают поиск — видно в каталоге, в поле capabilities.
Ограничения запроса
| Ограничение | Значение |
|---|---|
| Длина одного сообщения | 100 000 символов |
| Количество сообщений | 64 |
| Суммарный объём | 200 000 символов, включая описания функций |
max_tokens | не больше 16 384 |
| Количество функций | до 32 |
| Одновременных потоков на ключ | 5 |
Картинки в сообщениях не принимаются — для генерации изображений есть отдельный раздел API. Диалоги через API не сохраняются в истории веб-студии: остаются только записи о списаниях.
Деньги
Цены такие же, как в студии. Списывается с вашего личного баланса, а если вы состоите в активной организации — с её счёта; в ответе это видно в поле charged_from.
Картинки: сначала резерв, потом сверка
При постановке задачи с баланса резервируется расчётная стоимость. Когда картинка готова, сумма сверяется с фактической: разница либо доплачивается, либо возвращается. Если генерация не удалась или сработал фильтр безопасности — резерв возвращается целиком.
Резерв берётся до обращения к провайдеру. Поэтому несколько параллельных задач не могут суммарно потратить больше, чем есть на балансе.
Видео: оплата вперёд
Здесь сумма списывается сразу при постановке задачи. Если провайдер не принял задачу или ролик в итоге не получился, деньги возвращаются автоматически — отдельно просить возврат не нужно.
Чат: оплата по факту
Заранее списать нельзя — стоимость зависит от длины ответа, которую заранее никто не знает. Поэтому перед запросом проверяется, что баланса хватает на предполагаемую стоимость, а списание происходит после ответа, по фактическому расходу токенов.
Баланс может уйти в небольшой минус
Если ответ уже получен, он будет оплачен, даже когда денег на балансе не хватило — иначе мы бы отдавали чужую работу бесплатно. Уйти в глубокий минус не получится: следующий запрос не пройдёт проверку баланса.
Узнать цену заранее
Для картинок и видео есть расчёт без запуска: POST /images/estimate и POST /videos/estimate. Считают тем же кодом, что и настоящее списание, поэтому расхождений быть не должно.
Для чата предварительной оценки нет — ориентируйтесь на цены за миллион токенов из каталога моделей (поле pricing_rub_per_1m).
Не хватает денег
Придёт код INSUFFICIENT_BALANCE и HTTP 402. В details будет, сколько нужно и сколько есть. Пополнить — в личном кабинете.
Лимиты и повторные запросы
Ограничения частоты
| Ограничение | По умолчанию |
|---|---|
| Запросов в минуту | 60 на ключ |
| Запросов в сутки | 500 на ключ |
| Одновременных задач (картинки и видео) | 5 на ключ |
| Одновременных потоков чата | 5 на ключ |
При превышении приходит HTTP 429 с кодом RATE_LIMIT_EXCEEDED. В details указано, какой именно предел сработал — по этому полю удобно решать, ждать секунду или минуту. Лимиты считаются на ключ, поэтому не раздавайте один ключ десяти воркерам.
Защита от двойного списания
При создании картинки или видео передавайте заголовок Idempotency-Key с уникальным значением, например UUID. Если запрос оборвётся по таймауту и вы повторите его с тем же ключом, задача не создастся заново — вы получите тот же ответ и тот же номер задачи.
Idempotency-Key: 6f1c0a4e-6c1a-4c94-a0f2-6f0b6f0f5f1a| Ситуация | Что произойдёт |
|---|---|
| Тот же ключ, запрос уже выполнен (в пределах ~2 минут) | Вернётся тот же ответ, повторного списания нет |
| Тот же ключ, первый запрос ещё выполняется | HTTP 409 — подождите и повторите |
| Ключ не передан | Запрос выполнится обычным образом |
Для чата заголовок не нужен: ответ приходит сразу, повторять нечего.
Как узнать, что готово
Есть два способа: спрашивать статус самому или получить уведомление на свой адрес. Для промышленных сценариев лучше уведомления — они не тратят лимит запросов и приходят сразу.
| Способ | Когда подходит | Как часто спрашивать |
|---|---|---|
| Опрос статуса | Скрипты, разовые задачи, отладка | Картинки — раз в 2–5 секунд, видео — раз в 5–15 секунд |
| Вебхуки | Постоянные интеграции, n8n, серверные сценарии | не нужно — придёт само |
Ставьте у себя разумный таймаут: картинки обычно готовы меньше чем за две минуты, видео — от минуты до часа в зависимости от модели и длительности. Если провайдер завис, наша фоновая проверка сама закроет задачу и вернёт деньги.
Вебхуки
Мы отправляем POST-запрос на ваш адрес, когда задача завершилась — успешно или нет. Адрес задаётся один раз для ключа или отдельно для каждой задачи полем webhook_url.
Какие события приходят
| Событие | Когда |
|---|---|
image.generation.completed | Картинка готова |
image.generation.failed | Картинка не получилась, деньги возвращены |
video.generation.completed | Видео готово |
video.generation.failed | Видео не получилось, деньги возвращены |
{
"id": 123,
"object": "image.generation",
"status": "completed",
"model": "gemini-3.1-flash-image",
"cost_rub": "4.24",
"error": null,
"output": {
"images": [{ "url": "https://arckep.ru/…" }]
}
}Проверка подлинности
Вместе с телом мы присылаем подпись. Она доказывает, что запрос отправили мы, а не кто-то, кто узнал ваш адрес. Секрет для проверки выдаётся один раз при создании ключа — там же, где сам ключ.
| Заголовок | Значение |
|---|---|
X-Arckep-Signature | HMAC-SHA256 от сырого тела запроса, в hex |
X-Arckep-Event | Название события |
X-Arckep-Delivery-Id | Номер доставки — одинаковый у повторов |
User-Agent | Arckep-Webhooks/1.0 |
import hmac, hashlib
def verify(secret: str, raw_body: bytes, signature_hex: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_hex or "")Считайте подпись от сырых байтов
Подпись берётся от тела ровно в том виде, в каком оно пришло. Если сначала разобрать JSON, а потом собрать обратно, порядок полей и пробелы изменятся, и подпись не сойдётся.
Секрет можно сменить, не трогая сам ключ: POST /api/developer/keys/{id}/rotate-webhook-secret. Новый секрет тоже показывается один раз, старый сразу перестаёт работать.
Повторы и надёжность
- Отвечайте кодом 2xx как можно быстрее, тяжёлую работу делайте потом у себя.
- Если ваш сервер не ответил или вернул ошибку, доставка повторяется с нарастающими паузами, до 5 попыток.
- Очередь доставок хранится в базе, поэтому перезапуск нашего сервиса ничего не теряет.
- Один и тот же номер доставки может прийти несколько раз — учитывайте это и не выполняйте действие дважды.
Требования к адресу
Адрес должен быть на HTTPS и вести на публичный хост. Локальные и внутренние адреса отклоняются при сохранении — это защита от использования нашего сервера как посредника для доступа к чужим внутренним сетям.
- Только HTTPS.
- Нельзя
localhost, внутренние диапазоны IP, служебные адреса и домены вроде.localили.internal. - Проверка идёт после разрешения имени, так что подменить домен на внутренний IP не выйдет.
Если нужно принимать вебхуки на машине без публичного адреса, используйте туннель (ngrok, Cloudflare Tunnel) — он даёт настоящий HTTPS-адрес.
Ошибки
Все ошибки приходят в одном формате. Ориентируйтесь в коде на поле error_code, а не на текст сообщения: формулировки мы улучшаем, коды не меняем.
{
"error_code": "INSUFFICIENT_BALANCE",
"message": "Insufficient personal balance: need 15.00 ₽, available 5.00 ₽…",
"details": {
"required": 15.0,
"available": 5.0,
"is_corporate": false,
"currency": "RUB"
}
}Сообщения приходят на английском — так их проще показывать в логах и передавать в поддержку. Ниже перевод и что делать в каждом случае.
| Код | HTTP | Что случилось | Что делать |
|---|---|---|---|
UNAUTHORIZED | 401 | Ключ не передан, неверен или отозван | Проверьте заголовок Authorization и сам ключ. Секрет виден только при создании — если потерян, заведите новый |
FORBIDDEN | 403 | У ключа нет нужного права либо аккаунт заблокирован | Посмотрите details.required и создайте ключ с этим правом |
INSUFFICIENT_BALANCE | 402 | Не хватает денег на операцию | Пополните баланс. В details — сколько нужно и сколько есть |
INVALID_MODEL | 400 | Модель недоступна через API или в id опечатка | Возьмите id из каталога моделей |
INVALID_PARAMETER | 400 | Одно из полей имеет недопустимое значение | Смотрите details.field и details.reason |
VALIDATION_ERROR | 400 / 422 | Тело запроса не подходит под схему: превышены лимиты, неверная комбинация полей | Прочитайте message — там указано конкретное нарушение |
SAFETY_BLOCKED | 400 | Контент отклонён фильтрами провайдера | Смягчите формулировку или замените исходные материалы |
RESOURCE_NOT_FOUND | 404 | Задача не найдена: чужой номер или это генерация из веб-студии | Используйте номер из ответа на создание |
REQUEST_IN_PROGRESS | 409 | Запрос с таким Idempotency-Key ещё выполняется | Подождите и повторите — или возьмите новый ключ идемпотентности для новой задачи |
FILE_TOO_LARGE | 413 | Файл больше допустимого | Сожмите файл, предел — 10 МБ |
RATE_LIMIT_EXCEEDED | 429 | Превышена частота или число одновременных задач | Сделайте паузу; в details указано, какой предел сработал |
GENERATION_FAILED | 500 | Ошибка на стороне провайдера или у нас | Повторите с задержкой. Деньги за неудавшуюся задачу возвращаются |
SERVICE_UNAVAILABLE | 503 | API временно отключён | Повторите позже |
Как обрабатывать правильно
| Группа | Повторять? |
|---|---|
| 400, 402, 403, 404, 413 | Нет. Запрос надо исправить или пополнить баланс |
| 429 | Да, но с паузой и увеличением интервала |
| 500, 503 | Да, с нарастающей задержкой |
| 409 | Да, через несколько секунд — исходный запрос ещё выполняется |
Не считайте деньги списанными по факту ошибки
Если запрос завершился ошибкой, деньги либо не списывались, либо уже возвращены. Настоящую сумму всегда показывает сама задача в поле cost_rub и история операций в личном кабинете.
Готовые рецепты
Картинка от начала до конца
Скрипт загружает исходник, ставит задачу с защитой от двойного списания и ждёт результат.
export ARK_KEY="ark_live_..."
export BASE="https://arckep.ru/api/v1"
# 1. Загрузить исходник (если нужен)
UP=$(curl -sS -X POST "$BASE/uploads" \
-H "Authorization: Bearer $ARK_KEY" \
-F "file=@./input.png")
REF_URL=$(echo "$UP" | jq -r .url)
# 2. Поставить задачу
JOB=$(curl -sS -X POST "$BASE/images/generations" \
-H "Authorization: Bearer $ARK_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d "{
\"model\": \"gemini-3.1-flash-image\",
\"prompt\": \"кот-космонавт, студийный свет\",
\"reference_image_urls\": [\"$REF_URL\"]
}")
ID=$(echo "$JOB" | jq -r .id)
# 3. Ждать результат
while true; do
S=$(curl -sS -H "Authorization: Bearer $ARK_KEY" "$BASE/images/generations/$ID")
ST=$(echo "$S" | jq -r .status)
echo "$S" | jq -c '{status, cost_rub, error}'
[ "$ST" = "completed" ] && echo "$S" | jq -r '.output.images[].url' && break
[ "$ST" = "failed" ] && echo "Ошибка: $(echo "$S" | jq -r .error)" && break
sleep 3
doneВидео по тексту
curl -sS -X POST "$BASE/videos/generations" \
-H "Authorization: Bearer $ARK_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"model": "veo-3.1-fast-generate-preview",
"prompt": "волны на пляже, золотой час",
"mode": "t2v",
"duration_seconds": 5
}'Приём вебхука на Python
import hmac, hashlib
from fastapi import FastAPI, Request, HTTPException
app = FastAPI()
SECRET = "…секрет вебхука, показан один раз при создании ключа…"
@app.post("/hooks/arckep")
async def arckep_hook(request: Request):
raw = await request.body() # именно сырые байты
signature = request.headers.get("X-Arckep-Signature", "")
expected = hmac.new(SECRET.encode(), raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, signature):
raise HTTPException(status_code=401, detail="bad signature")
event = request.headers.get("X-Arckep-Event")
payload = await request.json()
# Отвечаем быстро, обработку ставим в очередь
enqueue(event, payload)
return {"ok": True}Подключение в n8n
- Узел HTTP Request, метод POST, адрес
https://arckep.ru/api/v1/images/generations. - Авторизация: заголовок
Authorizationсо значениемBearer ark_live_…. Храните ключ в Credentials, а не в теле узла. - Дальше либо узел ожидания и повторный запрос статуса, либо узел Webhook как приёмник уведомления — второй вариант надёжнее и не тратит лимит.
Языковая модель через библиотеку OpenAI
from openai import OpenAI
client = OpenAI(api_key="ark_live_…", base_url="https://arckep.ru/api/v1")
stream = client.chat.completions.create(
model="anthropic/claude-sonnet-4-6",
messages=[{"role": "user", "content": "Объясни рекурсию за три предложения"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)Если что-то не работает
Начните с GET /api/v1/balance — он проверяет ключ, не тратя денег. Затем GET /api/v1/models — убедитесь, что модель есть в списке и её id написан точно. Большинство проблем на старте — это опечатка в id модели или недостающее право у ключа.
Остались вопросы
Пишите на почту googlmen1057@gmail.com — приложите номер задачи и код ошибки, так разберёмся быстрее. Машинная версия этого руководства для AI-агентов доступна по адресу arckep.ru/llms.txt.