Стабильный контракт
Авторизация, тарифы, диалоги, вложения, очередь и потоковые ответы доступны через единый API. Старые пути запросов сохраняют совместимость.
Базовый адрес публичного API:
https://rc.walvey.online.
Walvey AI Gateway · API v3
Практическое руководство для пользователей, интеграторов и администраторов. Список методов ниже строится прямо из действующей OpenAPI-схемы backend.
Model API
Walvey предоставляет стабильные публичные маршруты независимо от используемого провайдера моделей. Интеграциям достаточно работать с API Walvey и не требуется знать схему размещения его компонентов.
Авторизация, тарифы, диалоги, вложения, очередь и потоковые ответы доступны через единый API. Старые пути запросов сохраняют совместимость.
Базовый адрес публичного API:
https://rc.walvey.online.
Администратор управляет доступными именами моделей и тарифными ограничениями. Фактическую доступность выбранной модели проверяет провайдер во время запроса.
Клиент получает нормализованный JSON-ответ или SSE-события через маршруты Walvey.
Используйте GET /health и
GET /ready для проверки доступности.
Выполните вход для Bearer JWT или используйте выданный
X-API-Key.
Получите обычный ответ или поток событий через
POST /v1/chat.
Эксплуатация
Эти проверки отвечают на разные вопросы. Используйте
/health для liveness и /ready перед
передачей production-трафика.
Возвращает 200, если приложение готово отвечать на
базовые запросы. Также показывает безопасную сводку очереди.
Проверяет необходимые зависимости и обработчик генерации. Если
сервис временно не готов принимать трафик, возвращает
503.
curl --fail https://rc.walvey.online/health
curl --fail https://rc.walvey.online/ready
Security
API выдаёт stateless JWT. Refresh-token и серверного logout route
нет: клиент удаляет сохранённый токен, а принудительный отзыв
происходит через смену пароля, блокировку или изменение
token_version.
POST /auth/register принимает email и пароль не
короче 8 символов; POST /auth/login возвращает
token.
С токеном вызовите /auth/verify/start, затем
/auth/verify/confirm. Пока email не подтверждён,
REQUIRE_EMAIL_VERIFIED=true закрывает chat,
conversations, memory и admin API, но оставляет доступ к
/me и verification flow.
Передавайте Authorization: Bearer <token>.
Срок действия по умолчанию — 7 дней и задаётся
JWT_TTL_SECONDS.
Permissions
Роль определяет полномочия, а тариф — лимиты генерации. Они связаны, но не взаимозаменяемы.
| Кто | Что разрешено | Что ограничивает |
|---|---|---|
| Гость | Web UI, docs, health, регистрация, вход и reset flow | Нет доступа к пользовательским данным |
| Пользователь | Только свои диалоги, вложения и память; запрос расширенного доступа | Текущий план и, при включении, подтверждение email |
| Moderator | Статистика, пользователи, блокировки, заявки и read-only просмотр plan/model/role | Фиксированные permissions системной роли moderator |
| Admin | Все делегируемые administrative actions | Не может управлять ролями и назначать их пользователям |
| Primary admin | Полный административный API, RBAC и назначение ролей | Только фактическая системная роль primary_admin |
| History service account | Собственные history/chat запросы с отдельными лимитами | Не администратор, не видит чужие данные, memory extraction отключён |
Это учётная запись с email из ADMIN_EMAIL. При первом
чистом запуске она создаётся из
ADMIN_BOOTSTRAP_PASSWORD, а при последующих стартах
backend возвращает ей системную роль primary_admin и
административный тариф. ADMIN_API_KEY также
аутентифицируется именно как эта запись.
В production backend останавливает запуск, если после bootstrap
не осталось ни одного активного
primary_admin.
Тариф и роль независимы: смена плана не выдаёт permissions. Только primary admin может назначать роли другим пользователям. После первого входа удалите bootstrap-пароль из runtime environment и перезапустите backend.
Administration
Registry задаёт стабильную policy приложения, а тариф сужает её для конкретного пользователя. Доступность модели подтверждается при фактическом запросе.
enabledis_defaultis_visionis_memory
Registry управляется через /admin/models и
административный интерфейс. Записи определяют policy доступа, но
не устанавливают и не загружают модели.
rpmconcurrencyprioritymax_num_predictctx_*, mem_max_itemscan_switch_modelallowed_models* разрешает любое имя, кроме явно отключённых администратором.allowed_server_tools
Fixed plan с can_switch_model=false обязан разрешать
текущую default-модель либо *. Несовместимая смена
default-модели отклоняется до обновления таких тарифов.
Operations
Раздел администратора Мониторинг обновляется каждые
5 секунд и использует GET /admin/runtime.
curl -sS "$BASE_URL/admin/runtime?event_limit=100&job_limit=100" \
-H "Authorization: Bearer $TOKEN"
curl -sS "$BASE_URL/admin/model-journal?limit=50" \
-H "Authorization: Bearer $TOKEN"
curl -sS "$BASE_URL/admin/model-journal/ENTRY_ID" \
-H "Authorization: Bearer $TOKEN"
Основной администратор с обязательной причиной включает maintenance, отменяет задачу или очищает ожидающую очередь. Состояние maintenance переживает перезапуск.
После трёх ошибок модель исключается на пять минут. Ручной probe использует фиксированный короткий запрос и не создаёт чат.
GET /metrics требует admin.stats.read. Пример scrape и dashboard находятся в ops/.
Для ключа отдельно задаются запросы, токены и период. Исчерпание возвращает 429 с Retry-After.
Experimental
В старые маршруты /v1/chat и
/v1/chat/files можно передать необязательное поле
mode: chat (по умолчанию) или
codex.
Backend добавляет системные инструкции для анализа, написания и объяснения кода. Ответ генерирует выбранная модель. Эффективный режим отражается в обычном JSON-ответе и status-событии SSE.
{
"conversation_id": 42,
"input": "Объясни ошибку и предложи patch",
"mode": "codex",
"stream": true
}
Desktop coding-agent
Отдельный WalveyOrbit.exe скачивается со страницы
/download, входит в существующий аккаунт и
выполняет действия только внутри выбранной пользователем папки.
Это самостоятельный agent loop, а не prompt-профиль
mode=codex.
Сервис проверяет модель и тариф, ставит каждый model turn в общую очередь и сохраняет состояние задачи.
Windows-приложение повторно валидирует tool и путь, затем пакетно читает, ищет, проверяет Git diff, применяет один patch либо запускает фиксированную проверку.
Изменение файла и запуск project code требуют подтверждения. Задачу можно остановить, продолжить после обрыва, дополнить новой инструкцией после завершения или удалить.
Передаётся только display label. Для работы модель всё же получает необходимые фрагменты файлов, результаты поиска, проверок и patch. Перед запуском убедитесь, что эти данные можно использовать для генерации.
Разрешены list_files, read_file,
read_files, search, read-only
git_status/git_diff,
apply_patch и run_check с ID
tests/lint/format_check/typecheck/build.
Сервер и EXE запрещают absolute/traversal paths,
.env*, VCS, credentials и private keys. Клиент
дополнительно проверяет Windows symlink/junction/reparse point.
До 20 шагов и 30 минут по умолчанию, bounded observations, идемпотентный result, отмена гонок и восстановление model turn после перезапуска backend.
Если функция включена в тарифе, Orbit предоставляет Linux desktop
в Docker: OCR-снимок экрана с координатами, мышь, клавиатуру,
clipboard и файлы внутри /home/sandbox. Shell и запись
могут требовать отдельного подтверждения пользователя.
Временные 409/429/502/503/504 повторяются с задержкой, результат инструмента отправляется идемпотентно, а зависший после перезапуска server turn автоматически возвращается в состояние ready.
POST /v1/agent/tasks
POST /v1/agent/tasks/{task_id}/follow-up
POST /v1/agent/tasks/{task_id}/continue
GET /v1/agent/tasks/{task_id}/actions/next
POST /v1/agent/tasks/{task_id}/actions/{action_id}/result
POST /v1/agent/tasks/{task_id}/cancel
DELETE /v1/agent/tasks/{task_id}
GET /v1/agent/tasks/{task_id}/events
GET /v1/agent/tasks/{task_id}/events/stream
Coding clients
Coding-клиенты подключаются к Walvey как к провайдеру OpenAI Chat Completions. Авторизация, модели, тарифы, очередь, квоты и мониторинг остаются на стороне Walvey.
https://rc.walvey.online/v1
GET /modelsPOST /chat/completionshttps://rc.walvey.online/openai/v1
Этот Base URL предоставляет чистый стандартный каталог. Оба варианта используют одну очередь и одинаковые ограничения.
opencode.json{
"$schema": "https://opencode.ai/config.json",
"provider": {
"walvey": {
"npm": "@ai-sdk/openai-compatible",
"name": "Walvey AI",
"options": {
"baseURL": "https://rc.walvey.online/v1",
"apiKey": "{env:WALVEY_API_KEY}"
},
"models": {
"MODEL_ID_FROM_ADMIN": {
"name": "Walvey coding model"
}
}
}
},
"model": "walvey/MODEL_ID_FROM_ADMIN"
}
OpenAI Compatible.https://rc.walvey.online/v1.Server tools
В веб-чате включите «Веб-инструменты». В Chat Completions передайте
"web_search": true для всего разрешённого политиками
набора либо укажите
точный список в server_tools. Модель сама вызывает
необходимые функции в ограниченном серверном цикле.
allowed_server_tools определяет максимальный набор
инструментов пользователя. API-ключ и отдельный запрос не могут
расширить этот список.
server_tools: null включает наследование, явный
список оставляет только выбранный поднабор, а
server_tools: [] запрещает все инструменты ключу.
web_search: true разрешает модели использовать весь
эффективный набор, а server_tools задаёт точный
список. Политика тарифа и ключа всё равно имеет приоритет.
Наличие разрешения не гарантирует доступность SearXNG, Open-Meteo, GitHub, GitLab или запрошенного публичного сайта.
В Администрирование → Тарифы основной администратор
отмечает доступные инструменты. Это верхняя граница для JWT,
веб-чата, Chat Completions и прямых /v1/tools/*.
Ключ по умолчанию наследует тариф владельца. Можно отключить наследование и выбрать поднабор. Ключ никогда не может разрешить инструмент, запрещённый тарифом.
| Имя в политике | Назначение | Источник и ограничения |
|---|---|---|
web_search |
Ищет актуальные страницы и возвращает заголовки, фрагменты и URL. | SearXNG, от 1 до 10 результатов на один вызов. |
web_fetch |
Извлекает читаемый текст конкретной публичной страницы. | Только HTTP(S), текст до 30 000 символов, без JavaScript-рендеринга. |
repository_read |
Показывает каталог или читает текстовый файл репозитория. | Только публичные GitHub/GitLab; код не клонируется и не запускается. |
get_current_time |
Возвращает локальное время для города или IANA timezone. | ISO-время, timezone и UTC offset. |
get_weather |
Возвращает текущие условия и прогноз для города. | Open-Meteo, прогноз от 1 до 7 дней. |
Откройте Администрирование → Тарифы, создайте или
отредактируйте тариф и отметьте «Разрешённые веб-инструменты».
Сохранение сразу меняет верхнюю границу для владельцев тарифа.
Откройте Администрирование → API-ключи. Оставьте
«Наследовать тариф» либо снимите флажок и выберите поднабор.
Перевыпуск секрета для изменения политики не требуется.
| Уровень | Значение | Результат |
|---|---|---|
| Тариф | allowed_server_tools: [...] |
Максимально разрешённый набор; пустой список запрещает всё. |
| API-ключ | server_tools: null |
Наследует актуальную политику тарифа владельца. |
| API-ключ | server_tools: [...] |
Фиксированный поднабор разрешений тарифа. |
| API-ключ | server_tools: [] |
Полностью запрещает серверные инструменты ключу. |
| Chat Completions | web_search: true |
Модель выбирает инструменты из эффективного набора. |
| Chat Completions | server_tools: [...] |
Разрешает в этом запросе только перечисленные инструменты. |
curl -sS "$BASE_URL/v1/chat/completions" \
-H "Authorization: Bearer $SERVICE_KEY" \
-H 'Content-Type: application/json' \
--data '{
"model": "MODEL_ID_FROM_ADMIN",
"messages": [{"role": "user", "content": "Изучи README репозитория и проверь погоду в Москве"}],
"server_tools": ["repository_read", "get_weather"],
"stream": false
}'
curl -sS -X PATCH "$BASE_URL/admin/plans/PLAN_ID" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data '{
"allowed_server_tools": [
"web_search", "web_fetch", "repository_read",
"get_current_time", "get_weather"
]
}'
curl -sS -X PATCH "$BASE_URL/admin/api-keys/KEY_ID" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data '{"server_tools":["web_search","web_fetch"]}'
# Вернуть наследование тарифа:
curl -sS -X PATCH "$BASE_URL/admin/api-keys/KEY_ID" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data '{"server_tools":null}'
GET /v1/tools/capabilities
POST /v1/tools/web-search
POST /v1/tools/web-fetch
POST /v1/tools/repository
GET /v1/tools/time?city=Москва
GET /v1/tools/weather?city=Москва&forecast_days=3
# Те же маршруты доступны с префиксом /openai/v1/tools/*
curl -sS "$BASE_URL/v1/tools/capabilities" \
-H "X-API-Key: $SERVICE_KEY"
curl -sS -X POST "$BASE_URL/v1/tools/web-search" \
-H "X-API-Key: $SERVICE_KEY" \
-H 'Content-Type: application/json' \
--data '{"query":"FastAPI release notes","max_results":5}'
Политика применяется одинаково к веб-чату, /v1/chat,
/v1/chat/completions,
/openai/v1/chat/completions и прямым маршрутам
/v1/tools/*. Старые тарифы и ключи после миграции
сохраняют совместимость и наследуют полный доступ, пока администратор
явно не сузит список.
Streaming
Один и тот же POST поддерживает обычный JSON и поток. Для SSE
передайте "stream": true; для единого JSON-результата —
false.
Пока job ждёт worker, сервер отправляет status event с
state: "queued", conversation ID, mode и metadata
вложений.
Каждый OpenAI-совместимый chunk нормализуется и оборачивается в
data: {json}\n\n. Текст обычно находится в
message.content.
Комментарий : heartbeat поддерживает соединение.
data: [DONE] завершает поток. Полезный conversation ID
также находится в заголовке X-Conversation-Id.
Attachments
Вложения принадлежат конкретному пользователю и диалогу, а на диске
хранятся в зашифрованном виде с Fernet-ключом
CHAT_FILE_ENC_KEY.
Изображения: JPEG, PNG, WebP. Документы: текстовые файлы и распространённые исходники, Markdown, CSV, JSON, XML, YAML, PDF и DOCX. MIME/signature и размеры изображений проверяются.
По умолчанию изображение не больше 16 384 px по стороне и 40 млн пикселей; общий бюджет изображений одного запроса — 60 млн пикселей. Из документа в prompt попадает максимум 40 000 символов с дополнительным ограничением тарифа по контексту.
/v1/chat/files сразу загружает файлы и запускает
ответ. /v1/chat/upload только сохраняет их и
возвращает IDs, которые позже передаются в JSON-поле
attachment_ids.
Ссылаться можно только на вложения того же пользователя и того же conversation. Очистка или удаление диалога удаляет metadata и зашифрованные файлы.
Troubleshooting
JSON-ошибка обычно имеет поле detail. Запишите также
ответный заголовок X-Request-Id — он помогает найти
запрос в логах.
400 / 422401403404 / 409413 / 415429Retry-After, не запускайте немедленные циклические повторы.502503 / 504/ready, учитывайте timeout и повторите запрос с задержкой.Quick recipes
Замените URL, email, пароль, token и IDs. Кнопки копируют только команды внутри блока.
BASE_URL=https://rc.walvey.online
curl -sS -X POST "$BASE_URL/auth/login" \
-H 'Content-Type: application/json' \
--data '{"email":"user@example.com","password":"LONG_PASSWORD"}'
TOKEN='PASTE_TOKEN_FROM_RESPONSE'
curl -sS "$BASE_URL/me" \
-H "Authorization: Bearer $TOKEN"
curl -sS -X POST "$BASE_URL/v1/chat" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data '{
"input": "Кратко объясни транзакции в базе данных",
"mode": "chat",
"stream": false,
"options": {
"temperature": 0.2,
"top_p": 0.9,
"repeat_penalty": 1.05,
"num_predict": 300
}
}'
curl -N -X POST "$BASE_URL/v1/chat" \
-H "Authorization: Bearer $TOKEN" \
-H 'Accept: text/event-stream' \
-H 'Content-Type: application/json' \
--data '{
"input": "Найди ошибку: def add(a, b): return a - b",
"mode": "codex",
"stream": true
}'
curl -sS -X POST "$BASE_URL/v1/chat/upload" \
-H "Authorization: Bearer $TOKEN" \
-F 'conversation_id=42' \
-F 'files=@./notes.pdf'
curl -N -X POST "$BASE_URL/v1/chat" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data '{
"conversation_id": 42,
"input": "Сделай резюме документа",
"attachment_ids": ["PASTE_ATTACHMENT_ID"],
"stream": true
}'
curl -sS "$BASE_URL/admin/plans" \
-H "Authorization: Bearer $TOKEN"
curl -sS -X PATCH "$BASE_URL/admin/plans/approved" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data '{
"rpm": 30,
"concurrency": 1,
"can_switch_model": true,
"allowed_models": ["default"],
"allowed_server_tools": [
"web_search",
"web_fetch",
"get_current_time",
"get_weather"
]
}'
curl -sS "$BASE_URL/admin/models" \
-H "Authorization: Bearer $TOKEN"
curl -sS "$BASE_URL/admin/backend" \
-H "Authorization: Bearer $TOKEN"
curl -sS -X POST "$BASE_URL/admin/backend/models/sync?refresh=false" \
-H "Authorization: Bearer $TOKEN"
curl -sS -X POST "$BASE_URL/admin/models" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data '{
"name": "code",
"display_name": "Qwen Coder 7B",
"description": "Модель для работы с кодом",
"enabled": true,
"is_default": false,
"is_vision": false,
"is_memory": false
}'
Имя должно совпадать со значением model, которое
поддерживает провайдер. Старый путь синхронизации сохранён для
совместимости и не устанавливает модели.
curl -sS -X POST "$BASE_URL/admin/roles" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data '{
"name": "support",
"display_name": "Support",
"description": "Просмотр и блокировка пользователей",
"permissions": ["admin.users.read", "admin.users.ban"]
}'
curl -sS -X POST "$BASE_URL/admin/users/42/role" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data '{"role_name":"support"}'
curl -sS -X POST "$BASE_URL/admin/api-keys" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data '{
"name": "support-bot",
"description": "Интеграция поддержки",
"user_id": 42,
"scopes": ["admin.users.read"],
"enabled": true,
"disable_thinking": true,
"server_tools": ["web_search", "web_fetch"],
"expires_at": "2099-01-01T00:00:00Z"
}'
SERVICE_KEY='PASTE_ONE_TIME_SECRET'
curl -sS "$BASE_URL/me" \
-H "X-API-Key: $SERVICE_KEY"
curl -sS -X PATCH "$BASE_URL/admin/api-keys/KEY_ID" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data '{"enabled":false,"expires_at":null}'
Поле secret возвращается только при создании и
перевыпуске. Сохраните его до закрытия ответа; исходный секрет в
хранилище не сохраняется. При
disable_thinking: true gateway запрашивает ответ без
отображения рассуждений. Поддержка быстрого режима зависит от
выбранной модели. server_tools: null наследует тариф,
список задаёт поднабор, а пустой список запрещает ключу все
серверные веб-инструменты.
Live contract
Контракт загружается напрямую из действующей схемы приложения.
Загружаем OpenAPI-схему…