#Поиск

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 — личный ключ

Terminal
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-приложение

Terminal
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 — личный ключ

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-приложение

javascript
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)

#Пример ответа

JSON
{
  "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 — недостаточно средств:

JSON
{
  "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`.

#Смотрите также