Если нужен api нейросети бесплатно для первого прототипа, практичнее сразу проверить его на сквозном сценарии, а не на отдельном запросе. В этом примере бот принимает фотографию, передаёт файл в API, запускает операцию «Оживить фото» и возвращает пользователю готовое видео. Для нового ключа предусмотрено 50 ₽ на пробу, поэтому одного пополнения достаточно для двух запусков photo-video по 25 ₽.
Я разберу проект от входящего сообщения до результата: загрузку файла, постановку задачи в очередь, проверку статуса, webhook, ограничения на пользователя и расчёт себестоимости. Ключ для API создаётся после входа в раздел API; он показывается один раз, поэтому в коде ключ хранится только в переменной окружения.
Что делает бот и во сколько обходится один пользователь
Сценарий состоит из четырёх запросов к API. Сначала бот получает фотографию от пользователя и скачивает её, затем отправляет файл через POST /uploads. В ответ получает ссылку на загруженный файл, после чего передаёт её в POST /generate с операцией photo-video.
POST /generate возвращает идентификатор задачи. Дальше бот не держит HTTP-запрос открытым: задача обрабатывается отдельно, а приложение проверяет её состояние через GET /tasks/{id} либо получает уведомление на указанный callback_url.
| Операция | Цена за запуск |
|---|---|
| Оживить фото (photo-video) | 25 ₽ |
| Изменить фото по описанию (image-edit) | 35 ₽ |
| Картинка по описанию (image) | 9 ₽ |
| Увеличить качество фото (upscale) | 50 ₽ |
| Видео по описанию (video) | 119 ₽ |
| Создать музыку (music) | 59 ₽ |
| Расшифровка записи (stt) | 10 ₽ |
| Говорящий аватар (avatar) | 120 ₽ |
| Убрать вокал (vocal) | 45 ₽ |
| Убрать шум (denoise) | 36 ₽ |
| Звук по описанию (sfx) | 9 ₽ |
| Озвучка текста (tts) | 18 ₽ за 1000 знаков |
Для нашего сценария себестоимость одной успешно запущенной обработки составляет 25 ₽. Если один пользователь отправил одну фотографию, это 25 ₽. Если он отправил четыре фотографии и для каждой запустил оживление, расчёт составляет 4 × 25 = 100 ₽.
При первом выпуске ключа на баланс начисляется 50 ₽. Это не делает каждую последующую обработку бесплатной: бонус просто позволяет провести первые два запуска photo-video без дополнительного пополнения. Оплата производится за запуск, без абонентской платы и минимального платежа.
Для отдельного чат-сценария есть совместимый с OpenAI интерфейс: POST /chat/completions и GET /models. Тариф чата составляет 40 ₽ за миллион токенов запроса и 400 ₽ за миллион токенов ответа, но в этом проекте чат не используется: бот работает именно с операцией photo-video.

Скелет бота: приём файла и загрузка в наше хранилище
Первое правило — не отправлять бинарный файл пользователя непосредственно в /generate. Сначала фотографию нужно загрузить через POST /uploads, получить ссылку и уже её использовать при запуске операции.
Для каждого запроса к API добавляется заголовок Authorization: Bearer <ключ>. Базовый адрес API — https://genius-bot.ru/wp-json/genius/v1, поэтому полный URL загрузки выглядит как https://genius-bot.ru/wp-json/genius/v1/uploads.
Минимальный запрос через curl выглядит так:
curl -X POST \
https://genius-bot.ru/wp-json/genius/v1/uploads \
-H "Authorization: Bearer $GENIUS_API_KEY" \
-F "file=@photo.jpg"
Здесь GENIUS_API_KEY — ключ, полученный в разделе API. Сам ключ не стоит записывать в исходный код, особенно если репозиторий доступен другим разработчикам.
В Python загрузку можно вынести в отдельную функцию:
import os
import requests
API_BASE = "https://genius-bot.ru/wp-json/genius/v1"
API_KEY = os.environ["GENIUS_API_KEY"]
def upload_photo(path):
with open(path, "rb") as photo:
response = requests.post(
f"{API_BASE}/uploads",
headers={
"Authorization": f"Bearer {API_KEY}"
},
files={
"file": photo
},
timeout=60,
)
response.raise_for_status()
return response.json()
Конкретную ссылку из ответа сохраняем в переменную. Важный момент для продакшена — не передавать пользователю весь JSON ответа API без проверки: приложению нужна только информация, которую оно ожидает получить от операции загрузки.
После этого начинается второй этап — запуск генерации. Для него понадобится ссылка на файл и выбранная операция photo-video.
Запуск задачи и ожидание результата без блокировки бота
Нельзя строить обработчик так, чтобы после /generate он несколько минут находился внутри цикла и ждал завершения. Пока такой обработчик занят, растёт число одновременно выполняющихся операций, а сетевые соединения остаются открытыми без необходимости.
Правильнее разделить процесс на две независимые части: короткий HTTP-запрос запускает задачу, а отдельный воркер занимается ожиданием результата. Пример запуска:
def generate_photo_video(file_url):
response = requests.post(
f"{API_BASE}/generate",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json={
"service": "photo-video",
"input": {
"image": file_url
}
},
timeout=60,
)
response.raise_for_status()
return response.json()
В этом фрагменте структура полей внутри JSON должна соответствовать формату конкретного запроса /generate. Из справки известны сам маршрут и название операции photo-video; приложение не должно придумывать дополнительные параметры, которых нет в документации операции.
После запуска приложение получает id задачи. Его удобно связать с идентификатором пользователя Telegram в собственной таблице или хранилище: task_id → user_id. Тогда при завершении можно точно определить, кому отправлять результат.
Для варианта без webhook подходит простой фоновый worker:
import time
def wait_for_task(task_id):
while True:
response = requests.get(
f"{API_BASE}/tasks/{task_id}",
headers={
"Authorization": f"Bearer {API_KEY}"
},
timeout=30,
)
response.raise_for_status()
data = response.json()
if data.get("status") in ("completed", "failed"):
return data
time.sleep(5)
Ключевая идея здесь не в самом sleep(5), а в том, что функция должна выполняться вне обработчика входящего сообщения. В простом прототипе для этого достаточно отдельного потока или очереди задач. Для небольшого бота можно начать с ThreadPoolExecutor, а состояние задач хранить отдельно от процесса приложения.
Пример общей схемы без привязки к конкретной библиотеке Telegram выглядит так: обработчик получает фото → скачивает файл → вызывает /uploads → вызывает /generate → сохраняет task_id → возвращает пользователю сообщение «Задача принята» → worker следит за /tasks/{id} → после завершения отправляет видео.

Вебхук вместо опроса: когда он окупается
Если задач мало, периодический запрос к GET /tasks/{id} проще всего реализовать и отлаживать. Но при большом количестве одновременно ожидающих задач polling начинает создавать лишний трафик: одна задача при проверке каждые 5 секунд создаёт до 12 запросов в минуту только на чтение статуса.
У API есть необязательный параметр callback_url. Когда задача готова, на этот адрес приходит POST, поэтому приложению не требуется самостоятельно спрашивать API о состоянии каждые несколько секунд.
При запуске задача получает адрес обработчика:
payload = {
"service": "photo-video",
"input": {
"image": file_url
},
"callback_url": "https://example.com/api/genius-callback"
}
response = requests.post(
f"{API_BASE}/generate",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json=payload,
timeout=60,
)</response.raise_for_status()
На стороне приложения нужен обычный POST-обработчик. Он принимает уведомление, извлекает идентификатор задачи и передаёт событие в очередь доставки результата. Сам callback не должен заниматься отправкой видео пользователю в длинном синхронном процессе: лучше быстро принять запрос, сохранить событие и вернуть HTTP-ответ.
Условно это можно представить так:
POST /api/genius-callback
|
v
проверка данных
|
v
сохранение task_id
|
v
очередь доставки
|
v
GET /tasks/{id}
|
v
отправка видео пользователю
Преимущество webhook проявляется не в цене самой операции, а в количестве служебных запросов. Если одновременно ожидается 100 задач, polling с интервалом 5 секунд потенциально создаёт до 1200 запросов статуса в минуту, тогда как callback сообщает о завершении только по событию.
При этом webhook не отменяет необходимость контролировать состояние задачи. В реальном приложении стоит предусмотреть обработку повторного callback, временной недоступности собственного сервера и ситуацию, когда задача завершилась с ошибкой.
Что показать пользователю, пока задача в работе
После запуска не стоит оставлять пользователя без ответа. Бот может сразу сообщить, что фотография принята и задача запущена, а затем отдельно прислать результат.
Это также удобное место для отображения ограничения: например, «В обработке. Цена запуска — 25 ₽». Пользователь заранее понимает, что произойдёт один платный запуск, а приложение не создаёт впечатление бесконечного ожидания.
Если пользователь отправил несколько фотографий подряд, лучше не запускать их автоматически без собственного лимита. Для каждого пользователя можно хранить количество задач за минуту, число одновременно выполняющихся задач и общий расход за выбранный период.
В простейшем варианте структура записи может выглядеть так:
{
"telegram_user_id": 123456789,
"active_tasks": 1,
"requests_last_minute": 1,
"spent_rub": 25
}
После успешного запуска увеличивается счётчик расходов и активных задач. После получения результата активная задача удаляется из счётчика, а сумма расходов остаётся в истории.
Отдельно учитывайте лимит самого API: не больше 60 запросов в минуту на один ключ. Это общий технический предел ключа, поэтому лимиты приложения должны учитывать не только команды пользователей, но и собственные запросы к /uploads, /generate и /tasks/{id}.

Как не разориться: лимиты на пользователя и защита от перебора
Стоимость одной обработки известна заранее: photo-video стоит 25 ₽ за запуск. Поэтому основной способ контролировать расходы — не пытаться вычислять их после обработки, а ограничивать число запусков до передачи запроса в /generate.
Например, для демонстрационного бота можно установить максимум 3 запуска photo-video в час на пользователя. Тогда потенциальный расход по одному пользователю составляет не более 3 × 25 = 75 ₽ в час, если приложение разрешает все три запуска.
Если нужен дневной бюджет, расчёт такой же. Лимит в 10 запусков в сутки означает максимум 250 ₽ расхода на одного пользователя за сутки именно на photo-video. При этом фактический расход может быть ниже, если пользователь не использует весь лимит или запуск не был выполнен.
Полезно разделить два ограничения. Первое — пользовательское: сколько операций может инициировать конкретный человек. Второе — системное: сколько задач одновременно может находиться в очереди всего приложения.
Пример простой проверки:
PHOTO_VIDEO_PRICE = 25
MAX_PER_HOUR = 3
MAX_ACTIVE = 20
def can_start(user, active_tasks):
if active_tasks >= MAX_ACTIVE:
return False, "Очередь заполнена"
if user.requests_last_hour >= MAX_PER_HOUR:
return False, "Лимит запусков на час исчерпан"
return True, ""
Такой лимит не заменяет контроль баланса. Перед запуском стоит проверить собственный учёт расходов и не отправлять запрос, если установленный для приложения бюджет уже исчерпан. Остаток баланса API можно получать через GET /balance, а список доступных операций и цен — через GET /services.
Есть ещё одна причина не делать бесконечный polling. Каждый вызов проверки состояния является запросом к API, а ограничение в 60 запросов в минуту действует на ключ целиком. При большом количестве пользователей слишком частые проверки могут приблизить приложение к этому пределу даже без большого количества новых генераций.
Для защиты от повторной отправки одной и той же команды можно использовать идентификатор входящего сообщения Telegram. Сначала приложение записывает его как обработанный, и только затем запускает операцию. Если тот же апдейт придёт повторно, второй запуск не создаётся.
В результате получается небольшой, но законченный контур: пользователь отправляет фото, приложение скачивает его, загружает через /uploads, запускает photo-video, сохраняет идентификатор задачи и получает результат через polling или callback. Все платные действия проходят через одну точку — /generate, поэтому себестоимость легко посчитать и ограничить.
Частые вопросы
Это действительно бесплатный API нейросети?
Для нового ключа на баланс начисляется 50 ₽ на пробу, поэтому первые запуски можно выполнить без отдельного пополнения. Дальше операции оплачиваются за запуск: например, «Оживить фото» стоит 25 ₽.
Сколько стоит один пользователь в нашем примере?
Если пользователь отправляет одну фотографию и бот запускает для неё photo-video один раз, стоимость составляет 25 ₽. Две фотографии — 50 ₽, четыре — 100 ₽.
Можно ли использовать API нейросети для бота с другими операциями?
Да, в API есть отдельные операции для редактирования и генерации изображений, видео, музыки, расшифровки, аватара, удаления вокала и шума, звука и озвучки текста. Цены для них доступны через GET /services; в справке также указана цена каждого запуска.
Нужен ли webhook для небольшого бота?
Нет. API позволяет получать состояние через GET /tasks/{id}, поэтому для первого прототипа можно использовать фоновый polling. Webhook становится удобнее, когда одновременно обрабатывается много задач и не хочется постоянно отправлять запросы для проверки статуса.
Можно ли сделать бесплатный API для телеграм бота без абонентской платы?
У этого API нет абонентской платы и минимального платежа: оплата идёт за запуск. Для первого ключа также предусмотрено начисление 50 ₽ на пробу, но сами операции после расходования баланса не становятся бесплатными.
Подходит ли API для сценария «нейросеть в телеграм боте» без отдельного серверного слоя?
В примере серверный слой нужен для приёма Telegram-сообщений, хранения состояния задач и обработки webhook. Сам доступ к нейросетевым операциям идёт через API с Bearer-ключом, а состояние запущенной задачи можно получать через /tasks/{id}.
Ключ создаётся в личном разделе API. Для такого бота достаточно начать с одной операции, одного лимита на пользователя и фоновой обработки задач, а затем при необходимости добавить webhook и более подробный учёт расходов.
