#Поиск
POST /v1/search
Выполняет поиск в интернете и возвращает синтезированный ответ со ссылками на источники. Поддерживает синхронный режим и потоковую передачу через Server-Sent Events (stream: true). Глубокое исследование с многошаговым агентным циклом — отдельный эндпоинт `POST /v1/research`.
#Поля запроса (body)
| Поле | Тип | Обяз. | По умолч. | Описание |
|---|---|---|---|---|
query |
string | да | — | Текст запроса. От 1 до 400 символов |
search_depth |
string | нет | basic |
Глубина поиска: basic или advanced. Цена режима — в `GET /v1/search/providers` |
provider |
string | нет | каскад USER → PORTAL → PLATFORM | Принудительный выбор движка: один из bitrix-search, tavily, brave, exa, you-com, linkup, perplexity, z-ai. jina доступен только в `POST /v1/research` |
max_results |
number | нет | 5 | Количество результатов в ответе. От 1 до 20 |
max_steps |
number | нет | 3 | Максимум шагов агентного режима. От 1 до 5. Учитывает только bitrix-search |
lang |
string | нет | ru |
Язык поиска: ru, en или auto |
include_answer |
boolean | нет | true |
Включить синтезированный ответ в поле answer |
include_raw_content |
boolean | нет | false |
Запросить полный текст найденных страниц |
include_domains |
string[] | нет | [] |
Поиск только по доменам из списка. До 10 имён хоста |
exclude_domains |
string[] | нет | [] |
Исключить домены. До 10 имён хоста |
time_range |
string | null | нет | null |
Окно времени публикации: day, week, month, year |
stream |
boolean | нет | false |
true — потоковая передача через SSE вместо JSON-ответа |
Часть фильтров поддерживается не всеми провайдерами — см. таблицу в Web Search для AI. Неподдерживаемый фильтр игнорируется, в ответе появляется заголовок X-Search-Filters-Ignored со списком пропущенных полей.
#Примеры
#curl — личный ключ
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": "advanced",
"max_results": 5,
"lang": "ru"
}'
#curl — OAuth-приложение
curl -X POST https://vibecode.bitrix24.tech/v1/search \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "что нового в Cursor IDE",
"search_depth": "advanced",
"max_results": 5,
"lang": "ru"
}'
#JavaScript — личный ключ
const res = await fetch('https://vibecode.bitrix24.tech/v1/search', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: 'что нового в Cursor IDE',
search_depth: 'advanced',
max_results: 5,
lang: 'ru',
}),
})
const data = await res.json()
console.log(data.answer)
data.results.forEach((r) => console.log(`[${r.id}] ${r.title} — ${r.url}`))
#JavaScript — OAuth-приложение
const res = await fetch('https://vibecode.bitrix24.tech/v1/search', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: 'что нового в Cursor IDE',
search_depth: 'advanced',
max_results: 5,
lang: 'ru',
}),
})
const data = await res.json()
#Поля ответа
| Поле | Тип | Описание |
|---|---|---|
query |
string | Текст исходного запроса |
provider |
string | Идентификатор провайдера, который обработал запрос (например, bitrix-search, tavily) |
search_depth |
string | Применённая глубина поиска: basic или advanced |
answer |
string | null | Синтезированный ответ с маркерами [N]. null для brave или при include_answer: false |
results |
array | Массив найденных источников |
results[].id |
number | Порядковый номер. Совпадает с маркером [N] в answer |
results[].url |
string | Адрес страницы |
results[].title |
string | Заголовок страницы |
results[].content |
string | Краткое описание или сниппет страницы. При include_raw_content: true — полный текст страницы (длина ограничена провайдером) |
results[].score |
number | null | Оценка релевантности от провайдера. Для tavily — число от 0 до 1, чем выше — тем релевантнее. null для bitrix-search и brave |
results[].published_date |
string | null | Дата публикации в формате ISO 8601. null для bitrix-search |
search_id |
string | Идентификатор запроса в формате ws_<14 цифр>_<8 hex> |
upstream_search_id |
string | null | Идентификатор у внешнего провайдера. Полезен для разбора инцидентов |
cost_vibes |
number | Сколько Ꝟ списано фактически |
duration_ms |
number | Длительность обработки запроса в миллисекундах |
partial_charge |
boolean | Присутствует, когда параллельные запросы исчерпали остаток баланса до конца текущего списания. Запрос завершился успешно, фактически списано меньше номинальной стоимости — итог в cost_vibes |
charge_log_failed |
boolean | Присутствует, когда не удалось записать журнал использования. Результат отдан, средства не списаны (cost_vibes: 0) |
#Пример ответа
{
"query": "что нового в Cursor IDE",
"provider": "bitrix-search",
"search_depth": "advanced",
"answer": "Cursor 3 — переработка интерфейса IDE [1]. Появилось окно агентов [2].",
"results": [
{
"id": 1,
"url": "https://cursor.com/blog/cursor-3",
"title": "Meet the new Cursor",
"content": "Cursor 3 brings a new agent-first interface...",
"score": null,
"published_date": null
},
{
"id": 2,
"url": "https://cursor.com/changelog",
"title": "Changelog",
"content": "Latest features in Cursor IDE...",
"score": null,
"published_date": null
}
],
"search_id": "ws_20260430113025_a1b2c3d4",
"upstream_search_id": "AG_xyz",
"cost_vibes": 5,
"duration_ms": 8523
}
#Потоковая передача (SSE)
При stream: true ответ приходит как поток событий text/event-stream. Каждое событие — это пара event: <type> + data: <JSON>, разделённая пустой строкой.
Возможные события:
| Событие | Когда возникает | Поля data |
|---|---|---|
start |
В начале запроса | search_id, provider, search_depth |
thinking |
Промежуточные размышления агента | content — текстовый фрагмент |
tool_call |
Агент вызвал внутренний инструмент | tool (web_search / content_extraction / external_tool), description |
tool_result |
Инструмент вернул результат | description, items_count |
answer_delta |
Очередной фрагмент финального ответа | content — кусок текста |
done |
Финальный блок | те же поля, что в синхронном ответе |
error |
Сбой во время обработки | error.code, error.message |
Пример потока:
event: start
data: {"search_id":"ws_20260430113025_a1b2c3d4","provider":"bitrix-search","search_depth":"advanced"}
event: thinking
data: {"content":"Сейчас посмотрим в источниках"}
event: tool_call
data: {"tool":"web_search","description":"web search query"}
event: tool_result
data: {"description":"got 5 sources","items_count":5}
event: answer_delta
data: {"content":"Cursor 3 — "}
event: answer_delta
data: {"content":"переработка интерфейса IDE [1]."}
event: done
data: {"query":"что нового в Cursor IDE","provider":"bitrix-search","search_depth":"advanced","answer":"Cursor 3 — переработка интерфейса IDE [1].","results":[{"id":1,"url":"https://cursor.com/blog/cursor-3","title":"Meet the new Cursor","content":"...","score":null,"published_date":null}],"search_id":"ws_20260430113025_a1b2c3d4","upstream_search_id":"AG_xyz","cost_vibes":5,"duration_ms":8523}
Реальный поток событий с промежуточными thinking / tool_call / answer_delta отправляет только bitrix-search. Для остальных восьми провайдеров поток буферизованный — приходит только start и done. Признак прогрессивного потока — поле capabilities.modes.streaming в `GET /v1/search/providers`.
#Пример ответа при ошибке
402 — недостаточно средств:
{
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Insufficient vibes for this search.",
"userMessage": "Недостаточно Вайбов — пополните баланс или добавьте BYOK Tavily/Brave credential.",
"hint": "POST /v1/search/credentials with a tavily- or brave- key to switch to BYOK (free)."
}
}
Остальные ситуации перечислены в таблице ошибок ниже.
#Ошибки
| HTTP | Код | Описание |
|---|---|---|
| 400 | INVALID_REQUEST |
Пустой query, query длиннее 400 символов, max_results вне диапазона 1..20, max_steps вне диапазона 1..5, provider не из списка девяти, неизвестное значение search_depth, lang или time_range, include_domains / exclude_domains длиннее 10 элементов |
| 402 | INSUFFICIENT_BALANCE |
На балансе портала недостаточно Ꝟ для выбранного режима |
| 402 | BILLING_FROZEN |
Биллинг-аккаунт заморожен |
| 403 | SCOPE_DENIED |
Ключу не хватает скоупа vibe:search |
| 404 | PROVIDER_NOT_FOUND |
Передан provider, которого нет в системе или он отключён |
| 404 | CREDENTIAL_NOT_FOUND |
Для провайдера нет ни USER, ни PORTAL, ни PLATFORM-ключа |
| 404 | PROVIDER_DOES_NOT_SUPPORT_SEARCH |
Запрошен provider: "jina" — Jina работает только в `POST /v1/research`. Поле search_id присутствует в ответе |
| 429 | RATE_LIMITED |
Превышен лимит 60 запросов в минуту на API-ключ |
| 500 | INTERNAL_ERROR |
Внутренняя ошибка сервера. В ответе присутствует search_id |
| 502 | UPSTREAM_ERROR |
Провайдер вернул ошибку. Списания нет |
| 503 | FEATURE_NOT_ENABLED |
Web Search недоступен на этой платформе |
| 504 | UPSTREAM_TIMEOUT |
Провайдер превысил время ожидания запроса. Списания нет |
Полный список общих ошибок API — Ошибки.
#Известные особенности
Каскад выбора ключа. Когда поле provider опущено, платформа подбирает источник в порядке: ключ пользователя (USER BYOK) → ключ портала (PORTAL BYOK) → платформенный ключ (PLATFORM, bitrix-search). Свой BYOK-ключ с isDefault: true начинает срабатывать автоматически — provider указывать необязательно.
Списание происходит только после успешного ответа. Перед запросом проверяется баланс: при нехватке возвращается 402 INSUFFICIENT_BALANCE без обращения к провайдеру. При UPSTREAM_ERROR или UPSTREAM_TIMEOUT баланс не меняется — провайдер не вернул результат, оплачивать нечего.
lang: "auto" для bitrix-search приводится к ru. Других языков агентный режим не предоставляет — для англоязычных запросов используйте один из BYOK-провайдеров: tavily, brave, exa или другие из списка `GET /v1/search/providers`.
Пустая выдача оплачивается полностью. Когда провайдер не нашёл ни одного источника и вернул results: [], cost_vibes всё равно списывается в полном размере. Это поведение по дизайну — оплачивается обработка запроса провайдером, а не количество результатов.
Поле charge_log_failed сигнализирует о потерянной аудит-записи. При успешном ответе провайдера, но сбое записи журнала использования, ответ всё равно отдаётся клиенту с cost_vibes: 0 и флагом charge_log_failed: true. Списание Вайбов не произошло — аудит-журнал по этому запросу также отсутствует. Сценарий редкий, виден в дашборде /search.
provider: "jina" доступен только в /v1/research. Запрос с provider: "jina" в текущем эндпоинте возвращает 404 PROVIDER_DOES_NOT_SUPPORT_SEARCH. Список провайдеров, поддерживающих /v1/search, проверяется по полю capabilities.modes.search.basic или capabilities.modes.search.advanced в `GET /v1/search/providers`.
#Смотрите также
- Web Search для AI — обзор раздела, тарификация, миграция с Tavily
- Глубокий поиск (POST /v1/research) — многошаговое агентное исследование
- Провайдеры — список движков с тарифами и возможностями
- Свои ключи (BYOK) — добавление BYOK-ключей восьми провайдеров
- Веб-поиск + LLM (RAG) — рецепт связки с
/v1/ai/chat/completionsдля ответов с цитированием - Ключи и авторизация — личный ключ и ключ авторизации
- Ошибки — справочник кодов ошибок API
- Лимиты и оптимизация — общие правила частоты запросов