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

Быстрый старт

  1. Войдите и откройте Студию — API-ключи в разделе аккаунта.
  2. Пополните API-кошелёк (отдельный от кредитов студии; действует минимальное первое пополнение).
  3. Вызывайте 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.

Получить API-ключ

Аутентификация

Ключ передаётся в каждом запросе: заголовком 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МодельТиповые задачи
liteGPT-6 Luna (gpt-6-luna)переводы, правки, извлечение данных, классификация, короткие ответы
standardGPT-5.4 (gpt-5.4)повседневный контент: письма, описания, посты, пересказы
heavyClaude 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Когда
400invalid_request_errorбитый JSON, нет messages/prompt, неизвестная модель или модель не того типа для эндпоинта, неподдерживаемый/приватный источник картинки
401authentication_errorключ отсутствует, испорчен или отозван
402billing_errorкошелёк ни разу не пополнялся (в сообщении минимум) или баланса не хватает на вызов (для текста — на резерв по max_tokens; в сообщении обе суммы)
403permission_errorаккаунт владельца ключа заблокирован
429rate_limit_errorбольше 30 запросов в минуту на ключ
413invalid_request_errorтело запроса больше 48 МБ (/v1/images/edits)
502api_errorпоставщик не ответил — деньги возвращены (кроме сбоя посреди потока)
503api_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 и обсудим обработку данных.

Нужен объёмный прайс или интеграция под ключ?

Бесплатная консультация