B2B AI API — цены и справочник
Один эндпоинт для Claude, GPT, Gemini, картинок и видео — дешевле официальных тарифов каждого вендора (экономия по каждой модели посчитана на страницах моделей). Без подписки: пополняете кошелёк и платите по факту по ценам ниже — текст за токены (вход и выход — каждый по своей цене за 1M), картинки за штуку, видео за секунду в разрешении запроса. Два текстовых формата: Anthropic Messages и OpenAI Chat Completions — существующие SDK работают после замены базового URL (Anthropic SDK: baseURL …/api; OpenAI SDK: baseURL …/api/v1 — сниппеты ниже).
Живые цены
| Модель | Тип | Цена |
|---|---|---|
claude-opus-5 — Claude Opus 5 | текст | вход 198 ₽ / выход 990 ₽-56%/ 1 млн токенов |
claude-sonnet-5 — Claude Sonnet 5 | текст | вход 114 ₽ / выход 570 ₽-36%/ 1 млн токенов |
gpt-5.4 — GPT-5.4 | текст | вход 99 ₽ / выход 594 ₽-56%/ 1 млн токенов |
gpt-6-luna — GPT-6 Luna | текст | вход 2,2 ₽ / выход 11 ₽-75%/ 1 млн токенов |
nano-banana-2 — Nano Banana 2 | картинки | 2,4 ₽-60%/ запрос |
nano-banana — Nano Banana | картинки | 0,96 ₽-72%/ запрос |
gpt-image-2 — GPT Image 2 | картинки | 2,4 ₽ / запрос |
seedream-5.0-lite — Seedream 5.0 Lite | картинки | 4,8 ₽ / запрос |
seedance-2.0-fast — Seedance 2.0 Fast | видео | от 10,6 ₽ / секунда видео |
seedance-2.0-mini — Seedance 2.0 Mini | видео | от 8,54 ₽ / секунда видео |
kling-v3 — Kling V3 | видео | 7,32 ₽-35%/ секунда видео |
veo-3.1-fast — Veo 3.1 Fast | видео | 42 ₽-22%/ запрос |
veo-3.1-lite — Veo 3.1 Lite | видео | 24 ₽-33%/ запрос |
minimax-3-hailuo — MiniMax 3 Hailuo | видео | 14,9 ₽-58%/ запрос |
wan/2-7-text-to-video — Wan 2.7 text-to-video | видео | 14,4 ₽-68%/ запрос |
Цены обновляются автоматически. Полный машинно-читаемый прайс по всем моделям: GET https://zerocoder.com/api/v1/models
«-NN%» — экономия к официальной цене вендора за ту же единицу (секунда видео, картинка, 1 млн токенов), официальные цены проверены 4 октября 2026. Источники и допущения — на страницах моделей: Claude API · ChatGPT API · Nano Banana API · Kling API · Veo API · MiniMax Hailuo API · Wan API
Быстрый старт
- Войдите и откройте Студию — API-ключи в разделе аккаунта.
- Пополните API-кошелёк (отдельный от кредитов студии; действует минимальное первое пополнение).
- Вызывайте API — формат совместим с Anthropic Messages:
curl https://zerocoder.com/api/v1/messages \
-H "x-api-key: YOUR_KEY" \
-H "content-type: application/json" \
-d '{"model": "claude-sonnet", "max_tokens": 300,
"messages": [{"role": "user", "content": "Hello!"}]}'Алиасы моделей: claude-opus, claude-sonnet, gpt, gpt-luna (→ GPT-6 Luna), smart, nano-banana, gpt-image и другие — см. эндпоинт моделей выше. claude-haiku снят: поставщик убрал Claude Haiku, поэтому запрос с ним возвращает 400 с подсказкой — используйте gpt-luna или claude-sonnet-5.
Аутентификация
Ключ передаётся в каждом запросе: заголовком x-api-key (как у Anthropic) или Authorization: Bearer (как у OpenAI). Ключи начинаются с zc-sk-; мы храним только SHA-256-хеш, поэтому потерянный ключ не восстановить — выпустите новый в разделе аккаунта.
Отсутствующий или отозванный ключ → 401 authentication_error; заблокированный аккаунт → 403 permission_error. Ключи привязаны к аккаунту: все ключи одного аккаунта делят общий кошелёк, а лимит 30 запросов в минуту считается на каждый ключ отдельно (у аккаунта до 10 активных ключей).
x-api-key: zc-sk-…
# или / or
Authorization: Bearer zc-sk-…Лимиты и биллинг
Лимит: 30 запросов в минуту на ключ, одна общая корзина для всех генерирующих эндпоинтов (messages, chat completions, картинки, правка, видео). Сверх лимита — 429 rate_limit_error: подождите несколько секунд и повторите. GET /v1/models в лимит не входит; у GET /v1/balance своё мягкое ведро — 120 запросов в минуту на ключ.
Оплата в рублях с отдельного API-кошелька (не из кредитов студии). Текстовые модели тарифицируются по токенам, вход и выход — отдельно: в GET /v1/models у них input_price_rub (за 1M входных токенов) и output_price_rub (за 1M выходных, обычно в 5–8 раз дороже входа), unit "1M_tokens"; price_rub равен цене входа и оставлен для старых клиентов. Вызов стоит входные токены × цена входа + выходные × цена выхода, минимум 0,5 ₽ за вызов (min_rub). При старте резервируется верхняя оценка — оценка входа по цене входа плюс max_tokens (по умолчанию 8192, не больше 32768 — большее значение прижимается) по цене выхода; как только ответ готов, списывается по факту, а разница возвращается сразу, в том же запросе. Если баланса меньше резерва — 402 billing_error с суммой резерва и вашим балансом в сообщении: уменьшите max_tokens или пополните кошелёк. Резерв считается не меньше чем на 512 выходных токенов (резервный этаж может ответить до этого объёма даже при меньшем max_tokens). У моделей шлюза ответ обрезается по max_tokens (по умолчанию 8192) — для длинных ответов передавайте max_tokens больше; если ответ пришёл через наши подписки Claude/ChatGPT, вывод жёстко не ограничен max_tokens, и токены сверх резерва дописываются после ответа по цене выхода. Картинки — за штуку, видео — цена секунды × seconds в разрешении запроса; их цена списывается до вызова, как раньше. Любое списание автоматически возвращается, если поставщик не ответил (вы получите 502 с пометкой «Charge refunded»).
Где виден счёт: блок billing возвращают /v1/chat/completions, /v1/images/edits, vision-ответы /v1/messages, финальное событие billing потока /v1/messages и последний чанк потока /v1/chat/completions. У текстовых моделей это { charged_rub, reserved_rub, balance_rub, unit: "1M_tokens", rub_per_mtok_in, rub_per_mtok_out, rub_per_mtok } — сколько списано по факту, сколько было зарезервировано на старте, баланс после расчёта и цены входа и выхода за 1M, по которым считали (rub_per_mtok повторяет цену входа для старых клиентов); у картинок по-прежнему { charged_rub, balance_rub }. Обычные (не потоковые) текстовые ответы /v1/messages и /v1/images/generations блока billing не несут (их форма заморожена ради существующих клиентов), а /v1/videos отдаёт price_rub / balance_rub — состояние кошелька всегда можно спросить у GET /v1/balance.
Пример на gpt-luna (GPT-6 Luna): вход 2,2 ₽ / выход 11,02 ₽ за 1M токенов. Вызов с 1 000 токенов на входе и 200 на выходе стоит 0,0044 ₽ → действует минимум 0,5 ₽; 200 000 на входе и 50 000 на выходе → 0,9915 ₽; 1 000 000 на входе и 200 000 на выходе → 4,41 ₽. Длинный ответ дороже длинного вопроса: выход дороже входа в 5 раз. Потоки резервируют так же и рассчитываются после последней дельты, до события billing; если поток оборвался посередине, платите только за реально выданные токены (минимум действует), остаток резерва возвращается.
Перед первым вызовом кошелёк нужно пополнить хотя бы один раз (минимум — ниже); пустой кошелёк отвечает 402 billing_error с суммой минимума в сообщении. Автопополнение с сохранённой карты включается в разделе аккаунта.
Минимальное первое пополнение: 1000 ₽
Модели
GET/api/v1/models
GET /v1/models возвращает все модели, доступные вашему ключу, с текущей ценой. У текстовых моделей endpoint /v1/messages (и /v1/chat/completions), у картиночных — /v1/images/generations и /v1/images/edits, у видео — /v1/videos. Принимаются и алиасы (claude-sonnet, gpt-luna, …), и полные id (claude-sonnet-4.6, gpt-6-luna). Снятые id (claude-haiku, а также убранные у поставщика claude-haiku-4.5, gpt-5.4-mini, gpt-5.4-nano) возвращают 400 с подсказкой, чем заменить.
Единицы: у текстовых моделей unit "1M_tokens" — input_price_rub и output_price_rub это рубли за 1M входных и выходных токенов (price_rub = цена входа, оставлен для совместимости), а min_rub — минимум за вызов; у картиночных unit "request" (цена за штуку), у видео — "second" (цена за секунду), у моделей с ценой по разрешениям ещё price_rub_by_resolution — POST /v1/videos списывает по разрешению, которое уходит поставщику. Остальные поля (id, aliases, type, endpoint, provider) не менялись.
{
"object": "list", "currency": "RUB", "balance_rub": 1840.5,
"data": [
{ "id": "smart", "aliases": ["auto"], "type": "text", "endpoint": "/v1/messages", "unit": "1M_tokens", "price_rub": null, "provider": "router",
"description": "Automatic model selection by task complexity (lite/standard/heavy). Billed at the routed model's price; …" },
{ "id": "claude-sonnet", "aliases": ["claude-sonnet-4.6", "claude-custom-default"], "type": "text", "endpoint": "/api/v1/messages", "unit": "1M_tokens", "price_rub": …, "input_price_rub": …, "output_price_rub": …, "min_rub": 0.5, "provider": "Anthropic" },
{ "id": "gpt-6-luna", "aliases": ["gpt-luna", "gpt-nano"], "type": "text", "endpoint": "/api/v1/messages", "unit": "1M_tokens", "price_rub": …, "input_price_rub": …, "output_price_rub": …, "min_rub": 0.5, "provider": "nexus" },
{ "id": "nano-banana-2", "aliases": ["gemini-3-flash"], "type": "image", "endpoint": "/api/v1/images/generations", "unit": "request", "price_rub": …, "provider": "gemini-image" },
{ "id": "seedance-2.0", "aliases": [], "type": "video", "endpoint": "/api/v1/videos", "unit": "second", "price_rub": …, "price_rub_by_resolution": { "480p": …, "720p": …, "1080p": … }, "provider": "nexus" }
]
}Smart-роутинг — model: "smart"
Не хотите выбирать модель под каждый запрос? Передайте "smart" (синоним "auto") — роутер сам подберёт модель под сложность задачи: простые запросы уходят на быстрые недорогие модели, сложные — на топовые. Так вы не переплачиваете за лёгкие вызовы. Прямые id моделей работают как раньше.
Роутер — детерминированная эвристика с нулевой задержкой: без доп. стоимости, без лишнего сетевого хопа, одинаковый запрос всегда попадает в один тир. Оценивается: объём входа, код и программистские маркеры, признаки анализа и рассуждений, математика, длинные тексты, строгие форматы вывода (JSON/схемы), длина диалога; простые механические задачи (перевод, исправление ошибок, сокращение, классификация, извлечение) снижают балл. Сумма баллов даёт один из трёх тиров:
| Tier | Модель | Типовые задачи |
|---|---|---|
lite | GPT-6 Luna (gpt-6-luna) | переводы, правки, извлечение данных, классификация, короткие ответы |
standard | GPT-5.4 (gpt-5.4) | повседневный контент: письма, описания, посты, пересказы |
heavy | Claude Opus 5 (claude-opus-5) | код, глубокий анализ, длинные тексты, многошаговые рассуждения |
curl https://zerocoder.com/api/v1/messages \
-H "x-api-key: YOUR_KEY" \
-H "content-type: application/json" \
-d '{"model": "smart", "max_tokens": 400,
"messages": [{"role": "user", "content": "Refactor this function and explain the changes: …"}]}'{
"id": "msg_…", "type": "message", "role": "assistant",
"model": "gpt-6-luna",
"smart_routing": { "tier": "lite", "score": 1, "signals": ["short", "translate"] },
"content": [{ "type": "text", "text": "…" }],
"stop_reason": "end_turn", "stop_sequence": null,
"usage": { "input_tokens": 12, "output_tokens": 8 }
}Списание всегда по цене фактически выбранной модели (таблица выше). Ответ полностью прозрачен: в поле model — реальная модель, в smart_routing — { tier, score, signals }, чтобы вы могли логировать и проверять решения роутера. Работает и в /v1/messages, и в /v1/chat/completions.
Баланс
GET/api/v1/balance
GET /v1/balance — состояние кошелька аккаунта, без учёта в лимите запросов. spent_30d_rub — сумма списаний за последние 30 дней (возвраты уже вычтены). key.requests_count и key.last_used_at описывают ключ, которым вы вызвали метод.
curl https://zerocoder.com/api/v1/balance -H "x-api-key: YOUR_KEY"
curl https://zerocoder.com/api/v1/models -H "x-api-key: YOUR_KEY"{
"currency": "RUB",
"balance_rub": 1840.5,
"topped_up_total_rub": 5000,
"spent_30d_rub": 3159.5,
"min_topup_rub": 1000,
"auto_topup": { "enabled": true, "amount_rub": 1000, "threshold_rub": 300 },
"key": { "name": "prod-backend", "requests_count": 4213, "last_used_at": "2026-09-26T10:41:07.000Z" }
}Текст: /v1/messages
POST/api/v1/messages
Совместим с Anthropic Messages. Тело: model, messages[] (роли user / assistant; content — строка или массив блоков), опционально system, max_tokens, stream. Последнее сообщение user становится промптом, предыдущие передаются как история.
{
"model": "claude-sonnet",
"system": "You are a concise assistant.",
"max_tokens": 300,
"messages": [
{ "role": "user", "content": "Hi! What's the capital of Portugal?" },
{ "role": "assistant", "content": "Lisbon." },
{ "role": "user", "content": [{ "type": "text", "text": "And its population?" }] }
]
}Ответ повторяет Anthropic: id msg_…, content[0].text, stop_reason "end_turn", usage с input_tokens / output_tokens. Для моделей шлюза usage — реальный счётчик поставщика; для Claude/ChatGPT через прокси — оценка (~4 символа на токен). smart_routing появляется только при model "smart". max_tokens обрезает ответ моделей шлюза (по умолчанию 8192, не больше 32768 — большее значение прижимается; ответы через наши подписки Claude/ChatGPT жёстко не обрезаются) и задаёт размер токенного резерва (см. Биллинг), так что не завышайте его без нужды. По usage и считается счёт за токены.
{
"id": "msg_1f0c9b1e5a2b4c7d9e8f0a1b2c3d4e5f",
"type": "message",
"role": "assistant",
"model": "claude-sonnet-4.6",
"content": [{ "type": "text", "text": "About 550 thousand in the city, ~2.9 million in the metro area." }],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": { "input_tokens": 42, "output_tokens": 19 }
}Текст: /v1/chat/completions
POST/api/v1/chat/completions
Совместим с OpenAI Chat Completions — направьте baseURL OpenAI SDK на наш /api/v1 (Anthropic SDK сам добавляет /v1/messages, ему нужен /api — сниппеты ниже) и используйте ключ zc-sk-. Тело: model, messages[] с ролями system / user / assistant (content — строка или массив частей {type:"text"} / {type:"image_url"}), опционально stream, max_tokens; temperature принимается и игнорируется. system → системный промпт, последний user → промпт, остальное → история.
// OpenAI SDK (Node) — only baseURL and the key change
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://zerocoder.com/api/v1", apiKey: "zc-sk-…" });
const r = await client.chat.completions.create({ model: "gpt-luna", messages: [{ role: "user", content: "Hello!" }] });# OpenAI SDK (Python)
from openai import OpenAI
client = OpenAI(base_url="https://zerocoder.com/api/v1", api_key="zc-sk-…")
r = client.chat.completions.create(model="gpt-luna", messages=[{"role": "user", "content": "Hello!"}]){
"model": "gpt-luna",
"messages": [
{ "role": "system", "content": "Answer in one sentence." },
{ "role": "user", "content": "Why is the sky blue?" }
],
"max_tokens": 200
}{
"id": "chatcmpl_8c2f1d0e9a7b4c5d",
"object": "chat.completion",
"created": 1790419267,
"model": "gpt-6-luna",
"choices": [
{ "index": 0, "message": { "role": "assistant", "content": "Sunlight scatters off air molecules, and blue scatters most." }, "finish_reason": "stop" }
],
"usage": { "prompt_tokens": 21, "completion_tokens": 14, "total_tokens": 35 },
"billing": { "charged_rub": 0.5, "reserved_rub": 0.5, "balance_rub": 1840.0, "unit": "1M_tokens", "rub_per_mtok_in": …, "rub_per_mtok_out": …, "rub_per_mtok": … }
}Тот же ключ, лимит, биллинг, роутинг (включая "smart") и vision, что у /v1/messages — это один движок в другом конверте. Ошибки — в конверте OpenAI (см. «Ошибки»).
Стриминг
Передайте stream: true в любой текстовый эндпоинт — ответ придёт потоком Server-Sent Events (content-type text/event-stream). /v1/messages отдаёт последовательность событий Anthropic: message_start, content_block_start, N × content_block_delta с text_delta, content_block_stop, message_delta со stop_reason и output_tokens, message_stop — плюс одно дополнительное финальное событие billing с { charged_rub, reserved_rub, balance_rub, unit, rub_per_mtok_in, rub_per_mtok_out, rub_per_mtok } (уже рассчитанное по факту). Официальные SDK Anthropic незнакомое событие пропускают.
event: message_start
data: {"type":"message_start","message":{"id":"msg_…","type":"message","role":"assistant","model":"gpt-5.4","content":[],"stop_reason":null,"usage":{"input_tokens":21,"output_tokens":0}}}
event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Sunlight "}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"scatters…"}}
event: content_block_stop
data: {"type":"content_block_stop","index":0}
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":14}}
event: message_stop
data: {"type":"message_stop"}
event: billing
data: {"charged_rub":0.5,"reserved_rub":0.5,"balance_rub":1840.0,"unit":"1M_tokens","rub_per_mtok_in":…,"rub_per_mtok_out":…,"rub_per_mtok":…}/v1/chat/completions отдаёт чанки OpenAI: первый чанк только с ролью {delta:{role:"assistant", content:""}}, затем data: {object:"chat.completion.chunk", choices:[{delta:{content}}]} …, финальный чанк с finish_reason "stop", usage и billing { charged_rub, reserved_rub, balance_rub, unit, rub_per_mtok_in, rub_per_mtok_out, rub_per_mtok }, затем data: [DONE].
curl -N https://zerocoder.com/api/v1/chat/completions \
-H "authorization: Bearer YOUR_KEY" \
-H "content-type: application/json" \
-d '{"model": "gpt", "stream": true,
"messages": [{"role": "user", "content": "Write a haiku about rain"}]}'data: {"id":"chatcmpl_…","object":"chat.completion.chunk","created":1790419267,"model":"gpt-6-luna","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"chatcmpl_…","object":"chat.completion.chunk","created":1790419267,"model":"gpt-6-luna","choices":[{"index":0,"delta":{"content":"Sunlight "},"finish_reason":null}]}
data: {"id":"chatcmpl_…","object":"chat.completion.chunk","created":1790419267,"model":"gpt-6-luna","choices":[{"index":0,"delta":{"content":"scatters…"},"finish_reason":null}]}
data: {"id":"chatcmpl_…","object":"chat.completion.chunk","created":1790419267,"model":"gpt-6-luna","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":21,"completion_tokens":14,"total_tokens":35},"billing":{"charged_rub":0.5,"reserved_rub":0.5,"balance_rub":1840.0,"unit":"1M_tokens","rub_per_mtok_in":…,"rub_per_mtok_out":…,"rub_per_mtok":…}}
data: [DONE]Честно о стриминге: настоящая потоковая выдача токен за токеном есть только у моделей шлюза (GPT, Gemini и другие модели, идущие через шлюз). Claude и ChatGPT через наши подписки сначала генерируются целиком и приходят одним куском, порезанным на чанки без искусственной задержки — там поток нужен для совместимости, а не для скорости.
Биллинг потока: цена резервируется до вызова так же, как без стриминга. Сбой до первого фрагмента — возврат денег и событие error; сбой посреди потока — без возврата (часть текста доставлена), событие error; обрыв соединения клиентом — запрос к поставщику прерывается, возврата нет. Событие ошибки: в /v1/messages — event: error с конвертом Anthropic, в /v1/chat/completions — чанк data: {"error":{message,type,code}} и следом data: [DONE] (официальный OpenAI SDK бросает на нём APIError).
// /v1/messages
event: error
data: {"type":"error","error":{"type":"api_error","message":"Upstream generation failed: … Charge refunded."}}
// /v1/chat/completions
data: {"error":{"message":"Upstream generation failed: … Charge refunded.","type":"api_error","code":"upstream_error"}}
data: [DONE]Картинки на вход (vision, beta)beta
Оба текстовых эндпоинта принимают до 4 картинок в сообщении user: блоки Anthropic {type:"image", source:{type:"base64", media_type, data}} и {type:"image", source:{type:"url", url}} или части OpenAI {type:"image_url", image_url:{url}} (https-URL или data URI). Правила те же, что у правки: только https-ссылки на публичные хосты (приватные и loopback-адреса отклоняются), редиректы — только на публичные https-хосты, каждая картинка не больше 8 МБ — иначе 400 ещё до списания. Ответ — обычный текстовый с блоком billing (по токенам, как любой текстовый вызов); в usage.input_tokens входит оценка за каждую картинку.
{
"model": "gpt",
"max_tokens": 300,
"messages": [{
"role": "user",
"content": [
{ "type": "text", "text": "What is on this photo? Answer in Russian." },
{ "type": "image", "source": { "type": "url", "url": "https://example.com/photo.jpg" } },
{ "type": "image", "source": { "type": "base64", "media_type": "image/png", "data": "iVBORw0KGgo…" } }
]
}]
}{ "role": "user", "content": [
{ "type": "text", "text": "Describe the image." },
{ "type": "image_url", "image_url": { "url": "https://example.com/photo.jpg" } }
] }{
"id": "msg_7c1e2d3a-4b5c-4d6e-8f90-a1b2c3d4e5f6",
"type": "message", "role": "assistant",
"model": "gemini-flash-latest",
"content": [{ "type": "text", "text": "На фото — рыжий кот на подоконнике…" }],
"stop_reason": "end_turn",
"usage": { "input_tokens": 1112, "output_tokens": 18 },
"billing": { "charged_rub": 0.5, "reserved_rub": 0.5, "balance_rub": 1840.0, "unit": "1M_tokens", "rub_per_mtok_in": …, "rub_per_mtok_out": …, "rub_per_mtok": … }
}Vision в бете: запросы с картинками отвечает vision-модель Gemini (поле model в ответе показывает, что реально сработало), резерв — vision-модель OpenAI, если настроена. Если ни один бэкенд недоступен — 502 «Vision backend unavailable», деньги возвращаются. Списание — по цене запрошенной модели.
Генерация картинок
POST/api/v1/images/generations
POST /v1/images/generations — формат OpenAI Images. Тело: prompt, опционально model (по умолчанию nano-banana), size (1024x1024 / 1792x1024 / 1024x1792) или aspect ("1:1", "16:9", "9:16", "4:3", "3:4"); только n = 1. Ответ: { created, data:[{ url }] }. Ссылка временная — скачайте файл сразу.
{ "model": "nano-banana-2", "prompt": "A watercolor fox in a birch forest", "aspect": "16:9" }{ "created": 1790419267, "data": [{ "url": "https://…/out.png" }] }Правка картинок
POST/api/v1/images/edits
POST /v1/images/edits — правка или объединение референсов по текстовой инструкции (по умолчанию edit-модель NanoBanana). JSON: prompt, опционально model, aspect, image (один https-URL или data URI) или images[] (до 4). Либо multipart/form-data с полями prompt, model, aspect и файловыми полями image / image[] — файлы до 8 МБ каждый, всё тело запроса до 48 МБ (сверх — 413). Загружаются только https-URL; приватные и loopback-адреса отклоняются с 400. model — только картиночная модель из GET /v1/models (type "image"); id видео и текстовых моделей отклоняются с 400.
{
"model": "nano-banana",
"prompt": "Replace the background with a sunset beach, keep the person unchanged",
"images": ["https://example.com/portrait.jpg"],
"aspect": "3:4"
}# JSON
curl https://zerocoder.com/api/v1/images/edits \
-H "x-api-key: YOUR_KEY" -H "content-type: application/json" \
-d '{"prompt": "Make it a night scene", "image": "https://example.com/photo.jpg", "aspect": "16:9"}'
# multipart
curl https://zerocoder.com/api/v1/images/edits \
-H "x-api-key: YOUR_KEY" \
-F prompt="Make it a night scene" -F aspect=16:9 \
-F "image[]=@photo1.jpg" -F "image[]=@photo2.jpg"Ответ: { created, model, data:[{ url }], billing:{ charged_rub, balance_rub } }. Цена модели списывается до вызова и возвращается, если поставщик не справился; если вы оборвали соединение до результата, списание остаётся (задача на шлюзе уже отработала) — то же правило, что у текстовых потоков.
Видео
POST/api/v1/videos
POST /v1/videos запускает генерацию: model (kling-v3, seedance-2.0-fast, … — см. /v1/models), prompt, опционально seconds (4–10, по умолчанию 5), size или aspect (по умолчанию 16:9), image (https-URL опорного кадра для image-to-video). Ответ: { id, object:"video", model, status:"queued", seconds, price_rub, balance_rub, size, resolution, billing:{ charged_rub, balance_rub, unit, unit_price_rub, price_option } }. Списание — цена секунды × seconds, в момент старта; у моделей с ценой по разрешениям (price_rub_by_resolution в /v1/models) — цена того разрешения, которое уходит поставщику: из resolution или size (по умолчанию 1920x1080, то есть 1080p или ближайший тариф модели). Неверный size или resolution — 400 до списания.
{ "model": "kling-v3", "prompt": "A drone shot over a foggy pine forest at dawn", "seconds": 5, "aspect": "16:9",
"image": "https://example.com/first-frame.jpg" }{ "id": "vid_7a1…", "object": "video", "model": "kling-v3", "status": "queued", "seconds": 5, "price_rub": …, "balance_rub": …,
"size": "1920x1080", "resolution": null, "billing": { "charged_rub": …, "balance_rub": …, "unit": "second", "unit_price_rub": … }, "poll": "/api/v1/videos?id=vid_7a1…" }GET/api/v1/videos?id=…
Опрашивайте GET /v1/videos?id=… раз в несколько секунд: { id, status:"queued"|"processing"|"completed"|"failed", progress, url }. При сбое в ответе error и refunded: true — деньги возвращаются автоматически; зависшие задачи возвращает сторож в течение пары часов. Если видео недоступно с нашей стороны, старт отвечает 503.
{ "id": "vid_7a1…", "status": "processing", "progress": 40, "url": null }
{ "id": "vid_7a1…", "status": "completed", "progress": 100, "url": "https://…/video.mp4" }
{ "id": "vid_7a1…", "status": "failed", "error": "generation failed", "refunded": true }curl https://zerocoder.com/api/v1/videos -H "x-api-key: YOUR_KEY" -H "content-type: application/json" \
-d '{"model": "kling-v3", "prompt": "A drone shot over a foggy pine forest", "seconds": 5}'
# → {"id":"vid_…","status":"queued",…}
curl "https://zerocoder.com/api/v1/videos?id=vid_…" -H "x-api-key: YOUR_KEY"Ошибки
/v1/messages, /v1/models, /v1/balance, /v1/images/* и /v1/videos используют конверт Anthropic; /v1/chat/completions — конверт OpenAI. Поле message всегда человекочитаемое, его безопасно логировать.
| Статус | type | Когда |
|---|---|---|
400 | invalid_request_error | битый JSON, нет messages/prompt, неизвестная модель или модель не того типа для эндпоинта, неподдерживаемый/приватный источник картинки |
401 | authentication_error | ключ отсутствует, испорчен или отозван |
402 | billing_error | кошелёк ни разу не пополнялся (в сообщении минимум) или баланса не хватает на вызов (для текста — на резерв по max_tokens; в сообщении обе суммы) |
403 | permission_error | аккаунт владельца ключа заблокирован |
429 | rate_limit_error | больше 30 запросов в минуту на ключ |
413 | invalid_request_error | тело запроса больше 48 МБ (/v1/images/edits) |
502 | api_error | поставщик не ответил — деньги возвращены (кроме сбоя посреди потока) |
503 | api_error | видео или правка картинок временно недоступны с нашей стороны |
// Anthropic envelope — /v1/messages, /v1/models, /v1/balance, /v1/images/*, /v1/videos
{ "type": "error", "error": { "type": "billing_error", "message": "Not enough API balance: this call reserves up to 4.7522 ₽ (≈2 input tokens at 118.8 ₽ and up to 8000 output tokens at 594 ₽ per 1M tokens; the unused part is refunded after the reply), you have 0.2 ₽." } }
// OpenAI envelope — /v1/chat/completions
{ "error": { "message": "Rate limit exceeded (30 requests/minute).", "type": "rate_limit_error", "code": "rate_limit_exceeded" } }Конверт OpenAI: error.code повторяет статус, чтобы код на SDK мог на него переключаться — 400 invalid_request, 401 invalid_api_key, 402 insufficient_balance, 403 account_suspended, 429 rate_limit_exceeded, 502 upstream_error; error.type — та же строка, что и в конверте Anthropic.
Примеры кода
Официальные SDK
OpenAI SDK сам добавляет к baseURL /chat/completions, Anthropic SDK — /v1/messages, поэтому базовые адреса у них разные:
// Anthropic SDK (Node) — baseURL WITHOUT /v1: the SDK appends /v1/messages itself
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({ baseURL: "https://zerocoder.com/api", apiKey: "zc-sk-…" });
const msg = await client.messages.create({ model: "claude-sonnet", max_tokens: 300, messages: [{ role: "user", content: "Hello!" }] });# Anthropic SDK (Python)
from anthropic import Anthropic
client = Anthropic(base_url="https://zerocoder.com/api", api_key="zc-sk-…")
msg = client.messages.create(model="claude-sonnet", max_tokens=300, messages=[{"role": "user", "content": "Hello!"}])// OpenAI SDK (Node) — only baseURL and the key change
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://zerocoder.com/api/v1", apiKey: "zc-sk-…" });
const r = await client.chat.completions.create({ model: "gpt-luna", messages: [{ role: "user", content: "Hello!" }] });# OpenAI SDK (Python)
from openai import OpenAI
client = OpenAI(base_url="https://zerocoder.com/api/v1", api_key="zc-sk-…")
r = client.chat.completions.create(model="gpt-luna", messages=[{"role": "user", "content": "Hello!"}])curl
curl https://zerocoder.com/api/v1/messages \
-H "x-api-key: YOUR_KEY" \
-H "content-type: application/json" \
-d '{"model": "claude-sonnet", "max_tokens": 300,
"messages": [{"role": "user", "content": "Hello!"}]}'curl -N https://zerocoder.com/api/v1/chat/completions \
-H "authorization: Bearer YOUR_KEY" \
-H "content-type: application/json" \
-d '{"model": "gpt", "stream": true,
"messages": [{"role": "user", "content": "Write a haiku about rain"}]}'Python (requests)
import json, requests
API = "https://zerocoder.com/api/v1"
H = {"x-api-key": "YOUR_KEY", "content-type": "application/json"}
# 1. Chat Completions (non-streaming)
r = requests.post(f"{API}/chat/completions", headers=H, json={
"model": "gpt-luna",
"messages": [{"role": "system", "content": "Answer briefly."},
{"role": "user", "content": "Why is the sky blue?"}],
})
r.raise_for_status()
data = r.json()
print(data["choices"][0]["message"]["content"], data["billing"])
# 2. Messages with streaming (Anthropic SSE)
with requests.post(f"{API}/messages", headers=H, stream=True, json={
"model": "gpt", "stream": True, "max_tokens": 400,
"messages": [{"role": "user", "content": "Tell a short story about a lighthouse"}],
}) as s:
s.raise_for_status()
event = None
for line in s.iter_lines(decode_unicode=True):
if line.startswith("event: "):
event = line[7:]
elif line.startswith("data: "):
payload = json.loads(line[6:])
if event == "content_block_delta":
print(payload["delta"]["text"], end="", flush=True)
elif event == "billing":
print("\n", payload) # {'charged_rub': …, 'reserved_rub': …, 'balance_rub': …, 'unit': '1M_tokens', 'rub_per_mtok_in': …, 'rub_per_mtok_out': …, 'rub_per_mtok': …}
elif event == "error":
raise RuntimeError(payload["error"]["message"])
# 3. Image edit (multipart)
with open("photo.jpg", "rb") as f:
r = requests.post(f"{API}/images/edits", headers={"x-api-key": "YOUR_KEY"},
data={"prompt": "Make it a night scene", "aspect": "16:9"},
files={"image": f})
print(r.json()["data"][0]["url"])Node (fetch)
const API = "https://zerocoder.com/api/v1";
const H = { "x-api-key": process.env.ZC_API_KEY, "content-type": "application/json" };
// 1. Messages (non-streaming)
const r = await fetch(`${API}/messages`, {
method: "POST", headers: H,
body: JSON.stringify({ model: "claude-sonnet", max_tokens: 300,
messages: [{ role: "user", content: "Hello!" }] }),
});
if (!r.ok) throw new Error((await r.json()).error.message);
const msg = await r.json();
console.log(msg.content[0].text); // non-streaming /v1/messages carries no billing block — see GET /v1/balance
// 2. Chat Completions with streaming (OpenAI SSE)
const s = await fetch(`${API}/chat/completions`, {
method: "POST", headers: H,
body: JSON.stringify({ model: "gpt", stream: true,
messages: [{ role: "user", content: "Write a haiku about rain" }] }),
});
if (!s.ok) throw new Error((await s.json()).error.message);
const reader = s.body.getReader();
const dec = new TextDecoder();
let buf = "";
for (;;) {
const { value, done } = await reader.read();
if (done) break;
buf += dec.decode(value, { stream: true });
const lines = buf.split("\n"); buf = lines.pop() ?? "";
for (const line of lines) {
if (!line.startsWith("data: ")) continue;
const data = line.slice(6);
if (data === "[DONE]") break;
const chunk = JSON.parse(data);
if (chunk.error) throw new Error(chunk.error.message);
process.stdout.write(chunk.choices[0].delta.content ?? "");
}
}
// 3. Video: start, then poll
const v = await (await fetch(`${API}/videos`, { method: "POST", headers: H,
body: JSON.stringify({ model: "kling-v3", prompt: "A drone shot over a foggy forest", seconds: 5 }) })).json();
let st;
do {
await new Promise((res) => setTimeout(res, 5000));
st = await (await fetch(`${API}/videos?id=${v.id}`, { headers: H })).json();
} while (st.status !== "completed" && st.status !== "failed");
console.log(st.url ?? st.error);Что нового (06.10.2026)
- 06.10.2026: выходные токены списываются по своей цене — в /v1/models появились input_price_rub и output_price_rub (price_rub по-прежнему = цена входа), в блоке billing — rub_per_mtok_in и rub_per_mtok_out, резерв берёт max_tokens по цене выхода. Раньше вход и выход считались вместе по цене входа. Ответ моделей шлюза теперь обрезается по max_tokens, под который взят резерв (по умолчанию 8192, не больше 32768).
- 06.10.2026: claude-haiku снят (поставщик убрал Claude Haiku) и возвращает 400 с подсказкой; новый алиас gpt-luna ведёт на GPT-6 Luna, gpt-nano → GPT-6 Luna, gpt-mini → GPT-5.6 Luna.
- 06.10.2026: POST /v1/videos списывает по разрешению, которое уходит поставщику (price_rub_by_resolution в /v1/models), и возвращает size, resolution и billing.
- 26.09.2026: потокенный биллинг текста, минимум 0,5 ₽ за вызов; на старте резервируется верхняя оценка (по max_tokens), сразу после ответа списывается по факту. В блоке billing появились reserved_rub, unit и rub_per_mtok; в /v1/models у текстовых моделей — unit "1M_tokens" и min_rub.
- Стриминг (stream: true) в /v1/messages — Anthropic SSE с дополнительным событием billing.
- Новый эндпоинт POST /v1/chat/completions — формат OpenAI Chat Completions, включая стриминг; OpenAI SDK работает с baseURL …/api/v1.
- Новый эндпоинт GET /v1/balance — кошелёк, расход за 30 дней, настройки автопополнения и статистика ключа.
- Новый эндпоинт POST /v1/images/edits — правка по референсам (JSON или multipart), до 4 картинок.
- Vision (beta) теперь идёт сначала через Gemini с резервом OpenAI; если бэкенд недоступен — деньги возвращаются.
- Оба текстовых эндпоинта работают на одном движке: одинаковые ключи, лимит, биллинг, роутинг и коды ошибок.
Частые вопросы
Почему дешевле, чем напрямую?
Мы объединяем объём многих клиентов в одном контракте, поэтому цены ниже официальных прайсов вендоров. Экономия по каждой модели — на её странице.
Есть минимальный контракт?
Нет. Пополнение кошелька, оплата по факту (текст — за токены, картинки — за штуку, видео — за секунду). Кошелёк отделён от кредитов студии, чтобы счёт сходился в одной валюте.
Что с лимитами и аптаймом?
Запросы переключаются между провайдерами, где модель это позволяет; расход и статистика ключа видны в разделе аккаунта.
Храните ли вы мои промпты?
Запросы проксируются для биллинга и антиабьюза; для корпоративных объёмов подпишем NDA и обсудим обработку данных.