Для AI-агентов: markdown этой страницы — /docs-content/search.md индекс документации — /llms.txt
Web Search для AI
REST-эндпоинты для веб-поиска от имени AI-агентов и приложений. Один запрос возвращает синтезированный ответ со ссылками на источники, потоковый режим — по мере готовности. Для глубокого исследования с многошаговым агентным циклом — отдельный эндпоинт POST /v1/research.
Скоуп: vibe:search | Базовый URL: https://vibecode.bitrix24.tech/v1 | Авторизация: X-Api-Key
Быстрый старт | Справочник эндпоинтов | Тарификация | Коды ошибок | Рецепт RAG с LLM
Разделы документации
- Поиск — синхронный запрос и потоковая передача (SSE) через
POST /v1/search - Глубокий поиск — многошаговое агентное исследование
POST /v1/research - Провайдеры — список поисковых движков и их возможностей
- Свои ключи (BYOK) — добавление личных ключей для бесплатного поиска
Какой ключ выбрать
Web Search работает с двумя типами ключей. Выбор определяется тем, от чьего имени отправляется запрос.
| Сценарий | Ключ | Заголовки запроса |
|---|---|---|
| СценарийСвой портал, личный скрипт или сервер | КлючЛичный API-ключ vibe_api_… |
Заголовки запросаX-Api-Key: vibe_api_… |
| СценарийЗапрос от имени конечного пользователя в OAuth-приложении | КлючКлюч авторизации vibe_app_… |
Заголовки запросаX-Api-Key: vibe_app_… + Authorization: Bearer <session_token> |
Подробнее о форматах ключей и получении session_token — Ключи и авторизация.
Провайдеры
Платформа предоставляет платформенные движки с тарификацией в Вайбах и BYOK-провайдеры с оплатой напрямую у поставщика. Какие именно движки доступны на конкретном инстансе, какой из них платформенный и какова его цена — зависит от настроек инстанса. Актуальный список возвращает GET /v1/search/providers.
| Провайдер | Назначение | Тарификация |
|---|---|---|
Провайдерbitrix-search |
НазначениеПлатформенный веб-поиск. Конкретный движок и его возможности зависят от инстанса — см. GET /v1/search/providers |
Тарификацияплатформенный, тариф в Вайбах — см. GET /v1/search/providers |
Провайдерtavily |
НазначениеTavily — англоязычный поиск с фильтрами по доменам и времени, оценкой релевантности | Тарификация0 Ꝟ (BYOK) |
Провайдерbrave |
НазначениеBrave Search — приватный веб-поиск, опциональный суммаризатор в advanced |
Тарификация0 Ꝟ (BYOK) |
Провайдерexa |
НазначениеExa — нейросетевой/семантический поиск с извлечением полного контента | Тарификация0 Ꝟ (BYOK) |
Провайдерyou-com |
НазначениеYou.com — поиск с цитатами и уточняющими вопросами | Тарификация0 Ꝟ (BYOK) |
Провайдерlinkup |
НазначениеLinkup — обход веба в реальном времени с режимом deep research | Тарификация0 Ꝟ (BYOK) |
Провайдерperplexity |
НазначениеPerplexity Sonar — модели Sonar для поиска и глубокого исследования | Тарификация0 Ꝟ (BYOK) |
Провайдерjina |
НазначениеJina DeepSearch — итеративный цикл «искать → читать → думать», только research | Тарификация0 Ꝟ (BYOK) |
Провайдерz-ai |
НазначениеZ.AI Web Search — поиск без синтезированного ответа с датами публикации | Тарификация0 Ꝟ (BYOK) |
Актуальный список с матрицей возможностей и ценами — GET /v1/search/providers. Какой провайдер платформенный, его цена и движок по умолчанию различаются от инстанса к инстансу. Для всех BYOK-провайдеров нужен ваш собственный ключ — добавляется через Свои ключи (BYOK). BYOK-провайдеры всегда стоят 0 Ꝟ на стороне платформы.
Поддерживаемые возможности провайдеров
Полная матрица возможностей доступна в GET /v1/search/providers — capabilities у каждого провайдера. Ключевые срезы — ниже тремя таблицами по группам.
Режимы и потоковая передача
| Провайдер | basic |
advanced |
research |
Поток |
|---|---|---|---|---|
Провайдерbitrix-search |
basic✓ | advanced✓ | researchзависит от инстанса | Потокзависит от инстанса |
Провайдерtavily |
basic✓ | advanced✓ | research✓ | Потокбуферизованный |
Провайдерbrave |
basic✓ | advanced✓ | research✗ | Потокбуферизованный |
Провайдерexa |
basic✓ | advanced✓ | research✓ | Потокбуферизованный |
Провайдерyou-com |
basic✓ | advanced✓ | research✓ | Потокбуферизованный |
Провайдерlinkup |
basic✓ | advanced✓ | research✓ | Потокбуферизованный |
Провайдерperplexity |
basic✓ | advanced✓ | research✓ | Потокбуферизованный |
Провайдерjina |
basic✗ | advanced✗ | research✓ | Потокбуферизованный |
Провайдерz-ai |
basic✓ | advanced✓ | research✗ | Потокбуферизованный |
Прогрессивный поток отправляет промежуточные события thinking / tool_call / answer_delta. Буферизованный шлёт start и done, а в режиме research между ними приходят события провайдера: у tavily — tool_call и tool_result, у linkup — section_complete.
Синтезированный ответ и оформление
| Провайдер | answer |
Цитаты [N] |
score |
publishedDate |
Уточняющие вопросы |
|---|---|---|---|---|---|
Провайдерbitrix-search |
answer✓ | Цитаты [N]зависит от инстанса | scoreзависит от инстанса | publishedDateзависит от инстанса | Уточняющие вопросы✗ |
Провайдерtavily |
answer✓ | Цитаты [N]✗ | score✓ | publishedDate✓ | Уточняющие вопросы✗ |
Провайдерbrave |
answerв advanced |
Цитаты [N]✗ | score✗ | publishedDate✓ | Уточняющие вопросы✗ |
Провайдерexa |
answer✓ | Цитаты [N]✓ | score✓ | publishedDate✓ | Уточняющие вопросы✗ |
Провайдерyou-com |
answer✓ | Цитаты [N]✓ | score✗ | publishedDate✓ | Уточняющие вопросы✓ |
Провайдерlinkup |
answer✓ | Цитаты [N]✓ | score✗ | publishedDate✓ | Уточняющие вопросы✗ |
Провайдерperplexity |
answer✓ | Цитаты [N]✓ | score✗ | publishedDate✗ | Уточняющие вопросы✗ |
Провайдерjina |
answer✓ | Цитаты [N]✓ | score✗ | publishedDate✓ | Уточняющие вопросы✗ |
Провайдерz-ai |
answer✗ | Цитаты [N]✗ | score✗ | publishedDate✓ | Уточняющие вопросы✗ |
У brave поле answer приходит только при search_depth: "advanced" через опциональный суммаризатор. В basic — null.
Фильтры
| Провайдер | include_domains |
exclude_domains |
time_range |
|---|---|---|---|
Провайдерbitrix-search |
include_domainsзависит от инстанса | exclude_domainsзависит от инстанса | time_rangeзависит от инстанса |
Провайдерtavily |
include_domains✓ | exclude_domains✓ | time_range✓ |
Провайдерbrave |
include_domains✗ | exclude_domains✗ | time_range✓ |
Провайдерexa |
include_domains✓ | exclude_domains✓ | time_range✗ |
Провайдерyou-com |
include_domains✗ | exclude_domains✗ | time_range✗ |
Провайдерlinkup |
include_domains✗ | exclude_domains✗ | time_range✗ |
Провайдерperplexity |
include_domains✗ | exclude_domains✗ | time_range✗ |
Провайдерjina |
include_domains✓ | exclude_domains✓ | time_range✗ |
Провайдерz-ai |
include_domains✓ | exclude_domains✗ | time_range✓ |
Когда выбранный провайдер не поддерживает переданный фильтр, запрос завершается без ошибки — фильтр игнорируется. В ответе появляется заголовок X-Search-Filters-Ignored со списком пропущенных полей:
X-Search-Filters-Ignored: include_domains,time_range
Для brave при include_answer: true и search_depth: "basic" дополнительно приходит заголовок X-Answer-Not-Supported: brave-search-does-not-synthesize-answers, а поле answer в JSON — null. В режиме advanced тот же провайдер подмешивает суммаризатор и возвращает заполненный answer.
Когда какой провайдер выбрать
Короткие ориентиры:
bitrix-search— платформенный веб-поиск, не требует своего ключа (тарифицируется в Вайбах). Возвращает синтезированныйanswerс источниками — готовый RAG-вывод для AI-агентов без отдельной сборки результата. Конкретные возможности (режимresearch, прогрессивный поток SSE, фильтры) зависят от инстанса — точная матрица вGET /v1/search/providers.tavily— фильтры по доменам (include_domains/exclude_domains), окно времени публикации (time_range), числовая оценка релевантности (score). Универсальный выбор для англоязычных задач.brave— веб-поиск без синтезаanswerпо умолчанию, синтезатор включается наadvanced. Подходит для англоязычной выдачи и приватных запросов.exa— нейросетевой/семантический поиск. Подходит для исследовательских задач, где нужны связанные по смыслу страницы, а не точное совпадение ключевых слов.you-com— единственный провайдер с уточняющими вопросами в режиме research.linkup— обход веба в реальном времени (liveData: true), подходит для запросов про события последних часов.perplexity— модели Sonar, OpenAI-совместимый формат, глубокое исследование с цитатами.jina— только режим research, итеративный цикл «искать → читать → думать». ЧерезPOST /v1/searchнедоступен.z-ai— поиск без синтезированного ответа, отдаёт результаты с датами публикации.
Быстрый старт
Минимальный вызов POST /v1/search: текст вопроса в поле query и режим basic. В ответ приходит синтезированный answer с маркерами [N] и массив results с найденными страницами. Когда переходить на advanced — в разделе Как выбрать глубину.
curl -X POST https://vibecode.bitrix24.tech/v1/search \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "что нового в Cursor IDE",
"search_depth": "basic",
"max_results": 5
}'
Ответ:
{
"query": "что нового в Cursor IDE",
"provider": "bitrix-search",
"search_depth": "basic",
"answer": "… **Cursor 3 (выпущен в апреле 2026 года):** Масштабное обновление, которое превратило IDE в единую точку управления **ИИ-агентами** [1]. Теперь разработчик может не писать код вручную, а отдавать высокоуровневые приказы агентам [2]. …",
"results": [
{
"id": 1,
"url": "https://habr.com/ru/companies/bothub/news/1018686/",
"title": "Вышел Cursor 3: внутри Composer 2, и можно запускать... / Хабр",
"content": "...",
"score": null,
"publishedDate": null
},
{
"id": 2,
"url": "https://habr.com/ru/companies/bothub/articles/1044774/",
"title": "Актуальный гайд на Cursor в 2026 году / Хабр",
"content": "...",
"score": null,
"publishedDate": null
}
],
"images": [],
"ignored_filters": [],
"search_id": "ws_20261021193212_5332deb4",
"upstream_search_id": "20261021_193212_c2aee833",
"billing_source": "wallet",
"cost_vibes": 2,
"duration_ms": 14274
}
Маркеры [1], [2] в поле answer соответствуют значениям results[].id. Значение provider в ответе (здесь bitrix-search) зависит от инстанса — без явного provider запрос идёт через движок по умолчанию, настроенный на инстансе. Текущий дефолт показывает поле defaultProvider в GET /v1/me.
Полный пример
Непрерывный сценарий: узнать платформенного провайдера инстанса и цену режима basic, выполнить поиск и вывести ответ со списком источников.
const VIBE_KEY = process.env.VIBE_KEY
const BASE = 'https://vibecode.bitrix24.tech/v1'
async function api(method, path, body = null) {
const opts = { method, headers: { 'X-Api-Key': VIBE_KEY } }
if (body) {
opts.headers['Content-Type'] = 'application/json'
opts.body = JSON.stringify(body)
}
const res = await fetch(`${BASE}${path}`, opts)
const data = await res.json()
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`)
return data
}
// 1. Узнаём, какой провайдер платформенный на этом инстансе и сколько стоит режим basic
const { providers } = await api('GET', '/search/providers')
const platform = providers.find(p => p.platformManaged)
console.log('Платформенный провайдер:', platform.slug, '— basic:', platform.pricing.basic, 'Ꝟ')
// 2. Ищем в режиме basic. Без поля provider запрос идёт по каскаду выбора ключа
const result = await api('POST', '/search', {
query: 'что нового в Cursor IDE',
search_depth: 'basic',
max_results: 5,
})
console.log('Ответил провайдер:', result.provider, '— источник оплаты:', result.billing_source)
console.log('Списано с кошелька:', result.cost_vibes, 'Ꝟ')
// 3. Выводим ответ и источники: маркер [N] в answer указывает на элемент results с id, равным N
console.log(result.answer)
for (const source of result.results) console.log(`[${source.id}]`, source.title, source.url)
Связка /v1/search и /v1/ai/chat/completions, в которой LLM отвечает по свежим источникам с маркерами цитирования [N], — в рецепте Веб-поиск + LLM (RAG).
Тарификация
Стоимость указывается в виртуальной валюте платформы — Вайбы (Ꝟ). Списание происходит после успешного ответа провайдера, при ошибке провайдера баланс не меняется.
Тариф платформенного провайдера различается от инстанса к инстансу — какой движок платформенный и сколько Ꝟ стоят его режимы basic / advanced / research, возвращает GET /v1/search/providers в поле pricing. BYOK-провайдеры (tavily, brave, exa, you-com, linkup, perplexity, jina, z-ai) всегда стоят 0 Ꝟ на стороне платформы — вы оплачиваете запросы напрямую у поставщика по его тарифу.
Платный поиск сначала расходует доступную квоту ИИ портала, а запрос с ключом Cowork — квоту места. Сверх квоты ИИ используется кошелёк, если перерасход разрешён и доступен. Когда квота ИИ к запросу не применяется, оплата идёт из кошелька. Списание из квоты или кошелька выполняется после успешного ответа провайдера. Наличие денег в кошельке не отменяет ограничения квоты ИИ и окон места Cowork.
В синхронном ответе поиска и событии done потоков поиска и исследования поле billing_source показывает источник оплаты:
| Значение | Источник оплаты |
|---|---|
Значениеwallet |
Источник оплатыКошелёк, в том числе оплата сверх квоты ИИ |
Значениеquota |
Источник оплатыКвота ИИ портала |
Значениеcowork |
Источник оплатыКвота места Cowork |
Значениеbyok |
Источник оплатыСобственный ключ провайдера — BYOK, Bring Your Own Key. Квота ИИ и кошелёк платформы не расходуются |
Для бесплатного запроса через платформенный ключ поле billing_source отсутствует. Поле cost_vibes показывает только фактически списанную с кошелька сумму. При оплате квотой ИИ, квотой места Cowork или своим ключом оно равно 0.
Расход поиска входит в AI-квоту компании. В массиве byModel ответа GET /v1/ai/quota может появиться строка с зарезервированным modelId: "web-search". Это доля квоты на веб-поиск, а не модель каталога. Поля calls и pctOfLimit показывают число запросов и долю месячного лимита.
История запросов с разбивкой по провайдерам, расход Вайбов по периодам и средняя длительность доступны в кабинете на странице /search. Там же можно добавить, проверить и удалить BYOK-ключи через визуальный интерфейс. Кнопка «Использовать» рядом с каждым провайдером открывает диалог с готовыми сниппетами на cURL, JavaScript, Python, TypeScript SDK и текстовым промптом для AI-ассистентов.
Лимит частоты
- 60 запросов в минуту на портал для
POST /v1/search. - 20 запросов в минуту на портал для
POST /v1/research— глубокое исследование длится в десятки раз дольше обычного поиска.
Лимит общий для всех API-ключей портала — они делят его между собой. Распределение нагрузки по нескольким ключам портала предел не поднимает. Действующее значение собственного лимита эндпоинта — в заголовке x-ratelimit-limit.
При превышении возвращается 429 RATE_LIMITED.
Справочник эндпоинтов
| Метод | Путь | Описание |
|---|---|---|
| МетодPOST | Путь/v1/search |
ОписаниеСинхронный запрос или потоковая передача |
| МетодPOST | Путь/v1/research |
ОписаниеГлубокое исследование с многошаговым агентным циклом, только SSE |
| МетодGET | Путь/v1/search/providers |
ОписаниеСписок провайдеров с матрицей возможностей и тарифами |
| МетодGET | Путь/v1/search/credentials |
ОписаниеСписок своих BYOK-ключей |
| МетодPOST | Путь/v1/search/credentials |
ОписаниеДобавить BYOK-ключ выбранного провайдера |
| МетодDELETE | Путь/v1/search/credentials/:id |
ОписаниеУдалить BYOK-ключ |
| МетодPOST | Путь/v1/search/credentials/:id/test |
ОписаниеПроверить BYOK-ключ |
Каскад выбора ключа
Когда в запросе POST /v1/search не передан provider, платформа подбирает его в порядке: ключ пользователя (USER BYOK) → ключ портала (PORTAL BYOK) → движок по умолчанию, настроенный на инстансе (его показывает поле defaultProvider в GET /v1/me).
Для POST /v1/research каскад работает иначе. Если поле provider опущено, сервер сразу подставляет research-движок по умолчанию, настроенный на инстансе, — USER/PORTAL-дефолт по другому провайдеру (например, exa) здесь не учитывается. Если для этого движка нет ни USER, ни PORTAL, ни PLATFORM-ключа, возвращается 404 CREDENTIAL_NOT_FOUND. Каскад USER → PORTAL → PLATFORM применяется уже внутри выбранного провайдера. Чтобы пойти через другой research-провайдер, передавайте provider явно.
После добавления своего BYOK-ключа с isDefault: true платформа использует его автоматически — параметр provider можно не указывать.
Миграция с Tavily
Схема запроса повторяет Tavily Search API. Различия:
- Адрес:
https://api.tavily.com/search→https://vibecode.bitrix24.tech/v1/search. - Авторизация: поле
api_keyв теле → заголовокX-Api-Key: YOUR_API_KEY. - Добавлено опциональное поле
provider— выбор движка из списка доступных. - Добавлены опциональные поля
topic(generalилиnews) иinclude_images— запрос изображений. У Tavily есть эти возможности, у других движков — нет. Неподдерживаемые поля игнорируются и попадают вignored_filters.
При наличии своего ключа Tavily добавьте его через POST /v1/search/credentials и используйте provider: "tavily" или сделайте ключ дефолтным. Остальные поля запроса работают идентично.
Коды ошибок
Ошибки веб-поиска
| Код | HTTP | Описание |
|---|---|---|
КодINVALID_REQUEST |
HTTP400 | ОписаниеНе пройдена валидация — пустой query, query длиннее лимита, неизвестное значение provider, search_depth, topic, lang или time_range, превышены лимиты include_domains / exclude_domains |
КодINSUFFICIENT_BALANCE |
HTTP402 | ОписаниеНа балансе портала недостаточно Ꝟ для выбранного режима. Переключитесь на BYOK или пополните баланс |
КодBILLING_FROZEN |
HTTP402 | ОписаниеБиллинг-аккаунт заморожен — пополните баланс и снимите блокировку в кабинете |
КодAI_QUOTA_EXHAUSTED |
HTTP402 | ОписаниеКвота ИИ исчерпана, оплата сверх квоты недоступна. Причина — в error.reason, время сброса — в error.resetAt. Дождитесь сброса, разрешите перерасход в кабинете и пополните кошелёк или используйте свой ключ провайдера |
КодAI_PACING_LIMITED |
HTTP429 | ОписаниеДостигнут лимит равномерного расходования квоты ИИ. Ответ содержит error.reason, error.overageDenied, error.resetAt и заголовок Retry-After в секундах. Дождитесь указанного времени или используйте свой ключ провайдера |
КодCOWORK_QUOTA_EXHAUSTED |
HTTP402 | ОписаниеИсчерпано окно квоты места Cowork. Поле error.window принимает fiveHour, week или month. Дождитесь error.resetAt или задержки из заголовка Retry-After в секундах, либо используйте свой ключ провайдера |
КодCOWORK_SUBSCRIPTION_INACTIVE |
HTTP402 | ОписаниеНет активного места Cowork. Активируйте или возобновите место, либо используйте свой ключ провайдера |
КодPROVIDER_NOT_FOUND |
HTTP404 | ОписаниеПередан provider, которого нет в системе или он недоступен |
КодCREDENTIAL_NOT_FOUND |
HTTP404 | ОписаниеДля запрошенного провайдера у пользователя или портала нет BYOK-ключа, а платформенного ключа нет |
КодPROVIDER_DOES_NOT_SUPPORT_SEARCH |
HTTP404 | ОписаниеЗапрошен provider: "jina" в POST /v1/search — Jina работает только в POST /v1/research |
КодPROVIDER_DOES_NOT_SUPPORT_RESEARCH |
HTTP404 | ОписаниеЗапрошен brave или z-ai — либо bitrix-search, когда у движка инстанса нет режима research — в POST /v1/research. Эти провайдеры работают только в POST /v1/search. На инстансе, где bitrix-search привязан к движку с research, /v1/research его принимает |
КодRATE_LIMITED |
HTTP429 | ОписаниеПревышен лимит запросов в минуту на портал |
КодUPSTREAM_ERROR |
HTTP401/403/429/502 | ОписаниеПровайдер вернул ошибку, списания нет. Поле upstream_status в ответе несёт исходный статус провайдера. Для BYOK-ключа ответы провайдера 401 и 403 приходят с тем же статусом — провайдер отверг ваш ключ, повтор без его замены не поможет. Ответ провайдера 429 сохраняет статус для любого ключа и несёт заголовок Retry-After — повторите позже. Остальные ошибки провайдера, включая отказ ключа платформенного движка, приходят как 502 — повторите запрос |
КодFEATURE_NOT_ENABLED |
HTTP503 | ОписаниеWeb Search или глубокое исследование недоступно на этой платформе |
КодUPSTREAM_TIMEOUT |
HTTP503 | ОписаниеПровайдер превысил время ожидания запроса. Ответ содержит заголовок Retry-After: 30 — повторите запрос через указанное в нём время |
Ошибки BYOK-ключей
| Код | HTTP | Описание |
|---|---|---|
КодINVALID_CREDENTIAL |
HTTP400 | ОписаниеПри создании BYOK-ключа провайдер отклонил его на этапе предварительной проверки. Запись не сохранена |
КодINVALID_REQUEST |
HTTP400 | ОписаниеНе указан apiKey, неверный provider, имя длиннее 64 символов |
Системные ошибки
| Код | HTTP | Описание |
|---|---|---|
КодMISSING_API_KEY |
HTTP401 | ОписаниеОтсутствует заголовок X-Api-Key |
КодINVALID_API_KEY |
HTTP401 | ОписаниеКлюч не опознан: такой строки на платформе нет |
КодKEY_INACTIVE |
HTTP401 | ОписаниеКлюч отозван или заблокирован платформой. Истёкший срок — отдельный код KEY_EXPIRED |
КодSCOPE_DENIED |
HTTP403 | ОписаниеКлючу не хватает скоупа vibe:search |
КодINTERNAL_ERROR |
HTTP500 | ОписаниеВнутренняя ошибка сервера |
Полный список общих ошибок API — Ошибки.
Структура ответа об ошибке
{
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Insufficient vibes for this search. Top up your account to continue.",
"userMessage": "Недостаточно vibes — пополните баланс или добавьте свой BYOK-ключ (см. GET /v1/search/providers).",
"hint": "Add a BYOK key to search for free — see GET /v1/search/providers",
"required": 5,
"topupUrl": "https://vibecode.bitrix24.tech/r/upgrade?c=ai_quota_copay&sc=api&m=api&t=topup&p=…&e=…&s=…"
}
}
Поля userMessage, required и topupUrl приходят при биллинговых ошибках INSUFFICIENT_BALANCE и BILLING_FROZEN. Поле required — сумма в Ꝟ, необходимая для запроса, topupUrl — ссылка на пополнение баланса. Поле hint приходит при этих же биллинговых ошибках, а также при CREDENTIAL_NOT_FOUND — там оно подсказывает, как добавить свой BYOK-ключ для выбранного провайдера.
Квотные отказы AI_QUOTA_EXHAUSTED, AI_PACING_LIMITED, COWORK_QUOTA_EXHAUSTED и COWORK_SUBSCRIPTION_INACTIVE возвращаются в том же объекте error. Они приходят обычным HTTP-ответом до открытия потока SSE. Обрабатывайте статус и error.code до чтения событий потока. Поле error.learnMore может содержать дополнительные сведения при AI_QUOTA_EXHAUSTED.