Flow API — документация API
Этот API генерирует картинки и видео через Google Flow (модели Nano Banana, Veo 3.1, Omni Flash). Генерации идут от имени вашего собственного Google-аккаунта и тратят ваши кредиты Google Flow.
Документ написан так, чтобы по нему мог работать и человек без опыта, и ИИ-агент. Если вы ИИ-агент — обязательно прочитайте раздел «Правила для ИИ-агентов».
Адрес API:
https://flow.178-151-26-131.sslip.ioTelegram-бот: @googleflowapibot — https://t.me/googleflowapibot Этот документ одним файлом:https://flow.178-151-26-131.sslip.io/docs.md
Быстрый старт за 3 минуты
Шаг 1. Подключите Google-аккаунт
- Откройте бота @googleflowapibot в Telegram и нажмите «Подключить Google Flow».
- Бот даст ссылку. На открывшейся странице войдите в свой Google-аккаунт (тот, где у вас подписка Google AI и Google Flow).
- Когда страница напишет «Готово», бот пришлёт сообщение «Google-аккаунт подключён».
Это делается один раз. Куки копировать не нужно.
Шаг 2. Создайте API-ключ
- В боте нажмите «🔑 API-ключи» → «➕ Создать ключ».
- Придумайте название (или нажмите «Пропустить»).
- Бот покажет ключ вида
flow_sk_AbCd.... Скопируйте его сразу — полностью ключ показывается только один раз.
Шаг 3. Сделайте первый запрос
Проверьте, что ключ работает (замените ВАШ_КЛЮЧ на свой ключ):
curl https://flow.178-151-26-131.sslip.io/v1/me -H "Authorization: Bearer ВАШ_КЛЮЧ"
Если в ответе есть "status": "linked" и "balance" — всё готово. Сгенерируйте картинку и дождитесь результата
одним запросом:
curl -X POST https://flow.178-151-26-131.sslip.io/v1/images \
-H "Authorization: Bearer ВАШ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{"prompt": "рыжий кот в очках читает газету, фотореализм", "wait": true}'
В ответе будет "status": "completed" и ссылка "file_url" на готовую картинку. Всё!
Главное, что нужно понимать
- Одна генерация = один файл. Один запрос создаёт ровно одну картинку или одно видео.
- Генерация занимает время. Картинка — 10–30 секунд, видео — обычно 1–3 минуты (иногда до 10).
Поэтому генерация работает в два шага: запустить → забрать результат. Или можно передать
"wait": true, и сервер сам дождётся результата (удобно, но соединение будет долго открыто). - Всё стоит кредитов вашего аккаунта Google Flow. Сколько именно — зависит от модели, длительности, качества
и вашей подписки. Узнать цену до запуска:
POST /v1/estimate. Картинки Nano Banana обычно бесплатные (0 кредитов). - Модели и цены у всех разные — они зависят от подписки Google. Единственный правильный источник:
GET /v1/models. - Одновременно у одного Google-аккаунта идёт одна генерация. Если отправить несколько, они встанут в очередь
(статус
queued) и выполнятся по очереди. - Ссылки на файлы живут около 6 часов. Скачивайте результат сразу.
Авторизация: как передавать ключ
Каждый запрос к /v1/... должен содержать API-ключ в заголовке. Подходит любой из двух вариантов:
Authorization: Bearer flow_sk_ВАШ_КЛЮЧ
X-API-Key: flow_sk_ВАШ_КЛЮЧ
Правила безопасности:
- Ключ — это пароль. Не публикуйте его, не вставляйте в код сайта, который видят посетители, не коммитьте в Git.
- Храните ключ в переменной окружения, например
FLOW_API_KEY. - Если ключ утёк — в боте: «API-ключи» → ключ → «Перевыпустить» (старый сразу перестанет работать) или «Отозвать».
Как устроена генерация (схема)
1. POST /v1/estimate → узнать цену и хватит ли кредитов (необязательно, но рекомендуется)
2. POST /v1/images → запустить картинку ─┐
POST /v1/videos → запустить видео ─┴→ в ответе "id": "gen_..."
3. GET /v1/generations/{id} → проверять статус раз в 5 секунд, пока не станет completed или failed
4. GET file_url → скачать файл (или GET /v1/generations/{id}/file с ключом)
Статусы генерации:
| Статус | Что значит | Что делать |
|---|---|---|
queued |
Ждёт очереди (у аккаунта уже идёт другая генерация) | Подождать и проверить снова |
running |
Google генерирует | Подождать и проверить снова |
completed |
Готово, есть file_url |
Скачать файл |
failed |
Не получилось, причина в error |
Прочитать error, исправить (например, промпт) и запустить заново |
Эндпоинты
Общие правила для всех запросов:
- Тело запросов — JSON, заголовок
Content-Type: application/json. - Все ответы — JSON (кроме скачивания файла).
- Время (
created_at,finished_at,expires_at) — Unix-время в секундах. - При ошибке HTTP-код не 2xx, а в теле
{"error": {...}}— см. «Ошибки».
GET /v1/me — проверить ключ и аккаунт
Показывает, какой ключ используется, подключён ли Google-аккаунт и какой баланс.
curl https://flow.178-151-26-131.sslip.io/v1/me -H "Authorization: Bearer ВАШ_КЛЮЧ"
Ответ:
{
"key": {
"name": "Мой сайт",
"hint": "flow_sk_AbCd…9xYz",
"expires_at": null,
"allowed_models": null,
"quota": {"unit": "credits", "period": "month", "limit": null, "used": 27, "remaining": null}
},
"google_account": {"status": "linked", "email": "you@gmail.com"},
"balance": 1024
}
| Поле | Что значит |
|---|---|
key.expires_at |
Когда ключ перестанет работать. null — бессрочно |
key.allowed_models |
Какие модели разрешены ключу. null — все |
key.quota.limit |
Лимит квоты. null — без ограничений |
key.quota.used |
Сколько уже потрачено за текущий период |
key.quota.remaining |
Сколько осталось. null — без ограничений |
google_account.status |
linked — всё хорошо; expired — нужно переподключиться в боте; none — не подключён |
balance |
Кредиты Google Flow на аккаунте прямо сейчас (есть только при linked) |
GET /v1/balance — баланс кредитов
curl https://flow.178-151-26-131.sslip.io/v1/balance -H "Authorization: Bearer ВАШ_КЛЮЧ"
{"balance": 1024, "quota": {"unit": "credits", "period": "month", "limit": 500, "used": 27, "remaining": 473}}
GET /v1/models — модели, параметры и цены
Возвращает только те модели, которые доступны вашему аккаунту и разрешены этому ключу, с точными ценами. Всегда смотрите сюда, а не в примеры из документации — у разных подписок разные варианты.
curl https://flow.178-151-26-131.sslip.io/v1/models -H "Authorization: Bearer ВАШ_КЛЮЧ"
{
"balance": 1024,
"models": [
{
"id": "nano-banana-2", "type": "image", "name": "Nano Banana 2",
"description": "Быстрая и качественная генерация картинок. Лучший выбор по умолчанию.",
"aspect_ratios": ["16:9", "4:3", "1:1", "3:4", "9:16"], "cost": 0
},
{
"id": "omni-1.1-flash", "type": "video", "name": "Omni 1.1 Flash",
"description": "Дешёвая и быстрая модель видео со звуком. Есть 360p и длительность до 10 секунд.",
"aspect_ratios": ["16:9", "9:16"], "cost": 4,
"durations": [4, 6, 8, 10], "resolutions": ["720p", "360p"],
"prices": [
{"aspect_ratio": "16:9", "duration": 4, "resolution": "360p", "cost": 4},
{"aspect_ratio": "16:9", "duration": 4, "resolution": "720p", "cost": 7}
]
}
]
}
| Поле | Что значит |
|---|---|
id |
То, что нужно передавать в поле model |
type |
image — картинки (запускать через /v1/images), video — видео (через /v1/videos) |
aspect_ratios |
Допустимые форматы кадра |
cost |
Минимальная цена одной генерации в кредитах |
durations |
Только видео: допустимые длительности в секундах |
resolutions |
Только видео: допустимое качество |
prices |
Только видео: точная цена каждой комбинации формат + длительность + качество. Используйте только комбинации из этого списка |
Какие модели бывают (точный список для вас — только в /v1/models):
id |
Тип | Кратко |
|---|---|---|
nano-banana-2 |
картинка | Лучший выбор по умолчанию |
nano-banana-pro |
картинка | Максимальное качество |
nano-banana-2-lite |
картинка | Самая быстрая |
omni-1.1-flash |
видео | Дёшево, со звуком, 4–10 сек, 360p/720p |
veo-3.1-lite |
видео | Veo подешевле |
veo-3.1-fast |
видео | Хорошее качество за разумную цену |
veo-3.1-quality |
видео | Лучшее качество, дорого |
POST /v1/estimate — цена до запуска
Ничего не генерирует и ничего не тратит. Показывает цену, текущий баланс, остаток после генерации и хватит ли квоты ключа.
Поля тела:
| Поле | Обязательно | Тип | По умолчанию | Описание |
|---|---|---|---|---|
type |
да | строка | — | image или video |
model |
да | строка | — | id модели из /v1/models |
aspect_ratio |
нет | строка | 16:9 |
Формат кадра |
duration |
нет | число | самая короткая доступная | Только видео, секунды |
resolution |
нет | строка | 720p |
Только видео: 720p или 360p |
curl -X POST https://flow.178-151-26-131.sslip.io/v1/estimate \
-H "Authorization: Bearer ВАШ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{"type": "video", "model": "omni-1.1-flash", "aspect_ratio": "9:16", "duration": 4, "resolution": "720p"}'
{
"type": "video", "model": "omni-1.1-flash", "model_name": "Omni 1.1 Flash",
"aspect_ratio": "9:16", "duration": 4, "resolution": "720p", "count": 1,
"cost": 7, "balance": 1024, "balance_after": 1017, "enough_credits": true,
"quota": {"unit": "credits", "period": "month", "limit": null, "used": 27, "remaining": null, "enough": true}
}
Запускайте генерацию, только если enough_credits = true и quota.enough = true.
POST /v1/images — сгенерировать картинку
Поля тела:
| Поле | Обязательно | Тип | По умолчанию | Описание |
|---|---|---|---|---|
prompt |
да | строка, 1–4000 символов | — | Что должно быть на картинке. Можно на русском |
model |
нет | строка | nano-banana-2 |
Модель картинок из /v1/models |
aspect_ratio |
нет | строка | 16:9 |
16:9, 4:3, 1:1, 3:4 или 9:16 |
wait |
нет | true/false | false |
true — ответить только когда картинка готова |
Пример без ожидания (рекомендуется для программ):
curl -X POST https://flow.178-151-26-131.sslip.io/v1/images \
-H "Authorization: Bearer ВАШ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{"prompt": "маяк на скале в шторм, закат, кинематографично", "model": "nano-banana-pro", "aspect_ratio": "1:1"}'
Ответ — HTTP 202 (принято, генерация идёт):
{
"id": "gen_3f9a1c2b7d4e5f6a7b8c",
"status": "queued",
"type": "image",
"model": "nano-banana-pro",
"prompt": "маяк на скале в шторм, закат, кинематографично",
"aspect_ratio": "1:1",
"cost_estimated": 0,
"credits_spent": null,
"balance_before": null,
"balance_after": null,
"created_at": 1789420000,
"finished_at": null,
"error": null
}
Запомните id и проверяйте статус через GET /v1/generations/{id}.
С "wait": true сразу придёт ответ HTTP 200 со status = completed или failed.
POST /v1/videos — сгенерировать видео
Поля тела:
| Поле | Обязательно | Тип | По умолчанию | Описание |
|---|---|---|---|---|
prompt |
да | строка, 1–4000 символов | — | Что происходит в видео: сцена, действие, движение камеры, звук |
model |
нет | строка | omni-1.1-flash |
Модель видео из /v1/models |
aspect_ratio |
нет | строка | 16:9 |
16:9 (горизонтально) или 9:16 (вертикально) |
duration |
нет | число | самая короткая доступная | Секунды. Только значения из durations модели |
resolution |
нет | строка | 720p |
720p или 360p (360p есть не у всех моделей) |
wait |
нет | true/false | false |
true — ответить только когда видео готово (может занять до 15 минут) |
curl -X POST https://flow.178-151-26-131.sslip.io/v1/videos \
-H "Authorization: Bearer ВАШ_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{"prompt": "дрон пролетает над заснеженными горами на закате, мягкий свет", "model": "omni-1.1-flash", "aspect_ratio": "16:9", "duration": 6, "resolution": "720p"}'
Ответ — такой же, как у картинок (HTTP 202, status = queued), плюс поля duration и resolution.
GET /v1/generations/{id} — статус и результат
curl https://flow.178-151-26-131.sslip.io/v1/generations/gen_3f9a1c2b7d4e5f6a7b8c -H "Authorization: Bearer ВАШ_КЛЮЧ"
Необязательный параметр ?wait=СЕКУНДЫ (0–600): сервер подождёт до указанного времени и ответит раньше, если генерация закончится.
Например ?wait=60 — удобный способ «ждать» без частых запросов.
Ответ, когда готово:
{
"id": "gen_3f9a1c2b7d4e5f6a7b8c",
"status": "completed",
"type": "video",
"model": "omni-1.1-flash",
"prompt": "дрон пролетает над заснеженными горами на закате, мягкий свет",
"aspect_ratio": "16:9",
"duration": 6,
"resolution": "720p",
"cost_estimated": 10,
"credits_spent": 10,
"balance_before": 1024,
"balance_after": 1014,
"created_at": 1789420000,
"finished_at": 1789420095,
"error": null,
"file_url": "https://flow-content.google/video/...",
"download_url": "https://flow.178-151-26-131.sslip.io/v1/generations/gen_3f9a1c2b7d4e5f6a7b8c/file"
}
| Поле | Что значит |
|---|---|
status |
queued, running, completed или failed |
cost_estimated |
Цена, посчитанная перед запуском |
credits_spent |
Сколько кредитов реально списалось (баланс до минус баланс после) |
balance_before / balance_after |
Баланс до и после генерации |
error |
Причина, если status = failed. Текст на русском, его можно показать человеку |
file_url |
Прямая ссылка на файл (картинка или mp4). Работает без ключа, живёт около 6 часов |
download_url |
Скачивание через этот сервис (нужен ключ в заголовке) |
Ответ при неудаче:
{"id": "gen_...", "status": "failed", "error": "Google отказался генерировать: промпт не прошёл модерацию. Измените описание.", "credits_spent": null}
GET /v1/generations/{id}/file — скачать файл
Отдаёт сам файл (image/jpeg или video/mp4). Нужен ключ.
curl -L https://flow.178-151-26-131.sslip.io/v1/generations/gen_3f9a1c2b7d4e5f6a7b8c/file \
-H "Authorization: Bearer ВАШ_КЛЮЧ" -o result.mp4
GET /v1/generations — последние генерации ключа
curl "https://flow.178-151-26-131.sslip.io/v1/generations?limit=10" -H "Authorization: Bearer ВАШ_КЛЮЧ"
Ответ: {"generations": [ ...объекты как в GET /v1/generations/{id}... ]}, новые первыми. limit — от 1 до 100 (по умолчанию 20).
Ошибки
При ошибке HTTP-код не 2xx, а тело всегда такое:
{
"error": {
"code": "insufficient_credits",
"message": "Не хватает кредитов: нужно 100, на балансе 40.",
"hint": "Необязательная подсказка, что сделать",
"cost": 100,
"balance": 40
}
}
code— постоянный код, по нему удобно проверять ошибку в программе.message— понятное описание на русском.hint— что сделать (есть не всегда).- Иногда есть дополнительные поля (
cost,balance,quota).
| HTTP | code |
Что случилось | Что делать |
|---|---|---|---|
| 401 | missing_api_key |
Нет заголовка с ключом | Добавьте Authorization: Bearer ВАШ_КЛЮЧ |
| 401 | invalid_api_key |
Ключ не найден | Проверьте, что скопировали ключ целиком; перевыпустите в боте |
| 401 | key_revoked |
Ключ отозван | Создайте новый ключ в боте |
| 401 | key_expired |
Закончился срок ключа | Продлите срок в боте |
| 402 | insufficient_credits |
Не хватает кредитов Google Flow | Выберите модель дешевле или пополните кредиты. Не повторяйте запрос |
| 403 | model_not_allowed |
Эта модель запрещена ключу | Используйте разрешённую модель или разрешите её в боте |
| 404 | generation_not_found |
Нет генерации с таким id |
Проверьте id |
| 409 | flow_not_connected |
Google-аккаунт не подключён | Подключите в боте |
| 409 | flow_session_expired |
Google разлогинил сессию | В боте: «Google-аккаунт» → «Переподключить» |
| 409 | not_ready |
Файл ещё не готов | Дождитесь status = completed |
| 400 | wrong_model_type |
Модель картинок в /v1/videos или наоборот |
Возьмите модель нужного type из /v1/models |
| 410 | file_expired |
Ссылка на файл устарела | Скачивайте результат сразу после готовности |
| 422 | invalid_request |
Неверное тело запроса (нет prompt, неправильный тип поля) |
Исправьте запрос по таблицам полей |
| 422 | invalid_options |
Недопустимая комбинация формата / длительности / качества | Возьмите комбинацию из prices в /v1/models |
| 422 | empty_prompt / prompt_too_long |
Пустой или слишком длинный промпт | Промпт от 1 до 4000 символов |
| 429 | quota_exceeded |
Исчерпана квота ключа | Дождитесь нового периода или увеличьте квоту в боте. Не повторяйте запрос |
| 502 | flow_error / flow_unavailable |
Google Flow вернул ошибку или недоступен | Прочитайте message; повторите через 1–2 минуты |
| 503 | browser_error |
Сервис не смог открыть сессию Google | Повторите через минуту |
Важно: если генерация запустилась, а потом не получилась (например, промпт не прошёл модерацию Google),
это не HTTP-ошибка — генерация получит status = failed и причину в поле error.
Квота, срок и разрешённые модели ключа
Всё настраивается в боте: «🔑 API-ключи» → ключ.
- Квота — сколько ключ может потратить за период.
- Единица: кредиты (сумма потраченных кредитов) или генерации (количество запусков).
- Период: день, неделя, месяц (последние 30 дней) или всё время. Считается «скользящим окном» от текущего момента.
- Лимит: число или «без лимита».
- Картинки часто стоят 0 кредитов — чтобы ограничить картинки, выбирайте единицу «генерации».
- Срок действия — дата, после которой ключ перестанет работать (
key_expired). - Модели — список разрешённых моделей. Остальные будут отклоняться с
model_not_allowed, а в/v1/modelsих не будет видно. - Перевыпустить — новый секрет с теми же настройками; старый сразу перестаёт работать.
- Отозвать — ключ навсегда перестаёт работать.
Текущее состояние квоты видно в GET /v1/me и GET /v1/balance.
Готовые примеры
Во всех примерах ключ берётся из переменной окружения FLOW_API_KEY.
Как её задать:
- Linux / macOS:
export FLOW_API_KEY="flow_sk_ВАШ_КЛЮЧ" - Windows PowerShell:
$env:FLOW_API_KEY = "flow_sk_ВАШ_КЛЮЧ"
Bash + curl: видео от запуска до файла
Нужны curl и jq.
#!/usr/bin/env bash
set -euo pipefail
API="https://flow.178-151-26-131.sslip.io"
AUTH="Authorization: Bearer $FLOW_API_KEY"
# 1. Цена
curl -s -X POST "$API/v1/estimate" -H "$AUTH" -H "Content-Type: application/json" \
-d '{"type":"video","model":"omni-1.1-flash","aspect_ratio":"16:9","duration":4}' | jq
# 2. Запуск
ID=$(curl -s -X POST "$API/v1/videos" -H "$AUTH" -H "Content-Type: application/json" \
-d '{"prompt":"волны разбиваются о скалы, замедленная съёмка","model":"omni-1.1-flash","duration":4}' | jq -r .id)
echo "Генерация: $ID"
# 3. Ожидание
while true; do
RESP=$(curl -s "$API/v1/generations/$ID?wait=30" -H "$AUTH")
STATUS=$(echo "$RESP" | jq -r .status)
echo "Статус: $STATUS"
[ "$STATUS" = "completed" ] && break
[ "$STATUS" = "failed" ] && { echo "Ошибка: $(echo "$RESP" | jq -r .error)"; exit 1; }
done
# 4. Скачивание
curl -s -L "$(echo "$RESP" | jq -r .file_url)" -o video.mp4
echo "Готово: video.mp4, списано $(echo "$RESP" | jq -r .credits_spent) кр."
PowerShell (Windows)
$Api = "https://flow.178-151-26-131.sslip.io"
$Headers = @{ Authorization = "Bearer $env:FLOW_API_KEY" }
$body = @{ prompt = "уютная кофейня в дождь, вид из окна"; model = "nano-banana-2"; aspect_ratio = "16:9" } | ConvertTo-Json
$gen = Invoke-RestMethod -Method Post -Uri "$Api/v1/images" -Headers $Headers -ContentType "application/json; charset=utf-8" -Body ([Text.Encoding]::UTF8.GetBytes($body))
do {
$gen = Invoke-RestMethod -Uri "$Api/v1/generations/$($gen.id)?wait=30" -Headers $Headers
Write-Host "Статус: $($gen.status)"
} while ($gen.status -in @("queued", "running"))
if ($gen.status -eq "failed") { throw $gen.error }
Invoke-WebRequest -Uri $gen.file_url -OutFile "image.jpg"
Write-Host "Готово: image.jpg"
Python
Нужна библиотека requests (pip install requests).
import os
import time
import requests
API = "https://flow.178-151-26-131.sslip.io"
HEADERS = {"Authorization": f"Bearer {os.environ['FLOW_API_KEY']}"}
def call(method, path, **kwargs):
r = requests.request(method, API + path, headers=HEADERS, timeout=660, **kwargs)
if r.status_code >= 400:
err = r.json()["error"]
raise RuntimeError(f"{err['code']}: {err['message']} {err.get('hint', '')}")
return r.json()
def generate(kind, prompt, save_as, **options):
"""kind: 'image' или 'video'. options: model, aspect_ratio, duration, resolution."""
est = call("POST", "/v1/estimate", json={"type": kind, **options})
print(f"Цена: {est['cost']} кр., баланс: {est['balance']}, останется: {est['balance_after']}")
if not est["enough_credits"] or not est["quota"]["enough"]:
raise RuntimeError("Не хватает кредитов или квоты ключа")
gen = call("POST", "/v1/images" if kind == "image" else "/v1/videos", json={"prompt": prompt, **options})
while gen["status"] in ("queued", "running"):
gen = call("GET", f"/v1/generations/{gen['id']}", params={"wait": 30})
print("Статус:", gen["status"])
if gen["status"] == "failed":
raise RuntimeError(gen["error"])
with open(save_as, "wb") as f:
f.write(requests.get(gen["file_url"], timeout=120).content)
print(f"Готово: {save_as}, списано {gen['credits_spent']} кр., баланс {gen['balance_after']}")
return gen
generate("image", "акварельный рисунок старого Тбилиси", "city.jpg", model="nano-banana-2", aspect_ratio="3:4")
generate("video", "бумажный кораблик плывёт по луже, крупный план", "boat.mp4",
model="omni-1.1-flash", aspect_ratio="9:16", duration=4, resolution="720p")
JavaScript (Node.js 18+)
const API = "https://flow.178-151-26-131.sslip.io";
const headers = { Authorization: `Bearer ${process.env.FLOW_API_KEY}`, "Content-Type": "application/json" };
async function call(method, path, body) {
const res = await fetch(API + path, { method, headers, body: body ? JSON.stringify(body) : undefined });
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
return data;
}
async function generateVideo(prompt) {
const options = { model: "omni-1.1-flash", aspect_ratio: "16:9", duration: 4 };
const est = await call("POST", "/v1/estimate", { type: "video", ...options });
console.log(`Цена ${est.cost} кр., останется ${est.balance_after}`);
if (!est.enough_credits) throw new Error("Не хватает кредитов");
let gen = await call("POST", "/v1/videos", { prompt, ...options });
while (gen.status === "queued" || gen.status === "running") {
gen = await call("GET", `/v1/generations/${gen.id}?wait=30`);
console.log("Статус:", gen.status);
}
if (gen.status === "failed") throw new Error(gen.error);
const file = await fetch(gen.file_url);
await (await import("node:fs/promises")).writeFile("video.mp4", Buffer.from(await file.arrayBuffer()));
console.log("Готово: video.mp4");
}
generateVideo("неоновый город ночью, камера медленно летит между небоскрёбами");
Правила для ИИ-агентов
Если вы ИИ-агент и пользователь дал вам этот документ и API-ключ, работайте строго по этому алгоритму.
Алгоритм одной генерации:
- Один раз за сессию вызовите
GET /v1/me. Еслиgoogle_account.statusнеlinked— остановитесь и скажите пользователю подключить Google-аккаунт в Telegram-боте @googleflowapibot. - Один раз за сессию вызовите
GET /v1/models. Выбирайте толькоid, форматы, длительности и качество из этого ответа. Никогда не придумывайте названия моделей и параметры. - Перед каждой платной генерацией вызовите
POST /v1/estimate. Сообщите пользователю цену (cost) и остаток (balance_after). Если пользователь не разрешил тратить кредиты заранее — спросите подтверждение. Еслиenough_creditsилиquota.enoughравноfalse— не запускайте генерацию, объясните причину. - Запустите генерацию:
POST /v1/imagesилиPOST /v1/videosбезwait. Сохранитеid. - Проверяйте
GET /v1/generations/{id}?wait=30в цикле, покаstatusне станетcompletedилиfailed. Не делайте запросы чаще одного раза в 5 секунд. Максимальное ожидание — 15 минут. completed→ отдайте пользователюfile_url(или скачайте файл сразу — ссылка живёт около 6 часов) и сообщитеcredits_spent.failed→ покажите пользователю текстerror.
Запреты:
- Не запускайте одну и ту же генерацию повторно «на всякий случай» — каждая попытка тратит кредиты.
- Не повторяйте запросы с ошибками
insufficient_credits(402),quota_exceeded(429),model_not_allowed(403),key_revoked/key_expired/invalid_api_key(401) — повтор ничего не изменит. - Повторять можно только ошибки
502и503, не больше 2 раз, с паузой минимум 60 секунд. - Если генерация завершилась с
failedиз-за модерации — измените промпт, прежде чем пробовать снова, и предупредите пользователя. - Не показывайте API-ключ пользователю в ответах и не записывайте его в файлы.
- Один запрос = одна картинка или одно видео. Если нужно несколько — запускайте по одному и дожидайтесь результата.
Как писать хорошие промпты:
- Картинка: объект + окружение + стиль + свет + ракурс. Пример: «старый маяк на скале, шторм, закат, фотореализм, широкий угол».
- Видео: что происходит + движение камеры + атмосфера + звук. Пример: «дрон медленно облетает маяк во время шторма, волны бьются о скалы, слышен ветер».
- Можно писать на русском или английском.
Частые вопросы
Нужно ли копировать куки Google? Нет. Вы один раз входите в Google через страницу, которую даёт бот. Сессия хранится на сервере сервиса в отдельном профиле вашего аккаунта и обновляется сама.
Google «разлогинил» — что делать?
API начнёт отвечать flow_session_expired, а бот пришлёт уведомление. В боте: «Google-аккаунт» → «Переподключить».
Почему у меня нет модели X или длительности Y?
Набор моделей и цены зависят от вашей подписки Google. Смотрите GET /v1/models.
Можно ли сгенерировать сразу 4 картинки одним запросом? Нет, один запрос = один файл. В Telegram-боте можно выбрать количество ×1–×4.
Сколько запросов можно делать одновременно?
Сколько угодно, но генерации одного Google-аккаунта выполняются по очереди (queued → running).
Списываются ли кредиты за неудачную генерацию?
Решает Google. Обычно за генерацию, отклонённую модерацией, кредиты не списываются. Точное значение всегда в credits_spent.
Где посмотреть интерактивную схему API?
Swagger: https://flow.178-151-26-131.sslip.io/swagger.