لوكلاء AI: ملف markdown لهذه الصفحة — /docs-content-en/search/run.md فهرس التوثيق — /llms.txt

مقالات التوثيق متاحة حاليًا باللغة الإنجليزية فقط.

Search

POST /v1/search

Performs a web search and returns a synthesized answer with links to sources. Supports synchronous mode and streaming via Server-Sent Events (stream: true). Deep research with a multi-step agentic loop is a separate endpoint POST /v1/research.

Request fields (body)

Field Type Required Default Description
Fieldquery Typestring Requiredyes Default— DescriptionQuery text. From 1 to 400 characters
Fieldsearch_depth Typestring Requiredno Defaultbasic DescriptionSearch depth: basic or advanced. advanced costs more — switch to it only when the basic response lacks the data you need, see How to choose the depth. The price of each mode is listed in GET /v1/search/providers
Fieldprovider Typestring Requiredno Defaultcascade USER → PORTAL → instance default engine DescriptionForced engine choice: one of bitrix-search, tavily, brave, exa, you-com, linkup, perplexity, z-ai. jina is available only in POST /v1/research
Fieldtopic Typestring Requiredno Defaultgeneral DescriptionSearch topic: general or news. Not all engines support the news mode — those that do populate publishedDate for news results, while the rest ignore it
Fieldmax_results Typenumber Requiredno Default5 DescriptionNumber of results in the response. From 1 to 20
Fieldmax_steps Typenumber Requiredno Default3 DescriptionMaximum number of steps in agentic mode. From 1 to 5. Honored only by engines that support it — for bitrix-search this depends on the instance engine
Fieldlang Typestring Requiredno Defaultru DescriptionSearch language: ru, en or auto. The default engine ignores this field — see "Known specifics"
Fieldinclude_answer Typeboolean Requiredno Defaulttrue DescriptionInclude the synthesized answer in the answer field
Fieldinclude_raw_content Typeboolean Requiredno Defaultfalse DescriptionRequest the full text of the pages found. For engines that support it, the text arrives in results[].rawContent
Fieldinclude_images Typeboolean Requiredno Defaultfalse DescriptionRequest images for the query. For engines that support it, the links arrive in the top-level images array
Fieldinclude_domains Typestring[] Requiredno Default[] DescriptionRestrict the search to the domains in the list. Up to 10 hostnames
Fieldexclude_domains Typestring[] Requiredno Default[] DescriptionExclude domains. Up to 10 hostnames
Fieldtime_range Typestring | null Requiredno Defaultnull DescriptionPublication time window: day, week, month, year
Fieldstream Typeboolean Requiredno Defaultfalse Descriptiontrue — streaming via SSE instead of a JSON response

Not all providers support every filter — see the table in Web Search for AI. An unsupported filter is ignored, and the response carries an X-Search-Filters-Ignored header with the list of skipped fields.

How to choose the depth

A request without search_depth runs in basic mode. advanced costs more. The prices of both modes on your instance are listed in GET /v1/search/providers.

Task Depth
TaskFind a fact, price, date, link or recent news item Depthbasic
TaskGive a language model context for answering the user Depthbasic
TaskRequests in a loop, on a schedule, or on every dashboard or widget refresh Depthbasic
TaskA one-off request when the basic response lacks the data you need Depthadvanced
TaskA summary of one topic across many sources Depthadvanced
TaskMulti-step research with a report DepthPOST /v1/research, not advanced in a loop

Rule for agents and apps: send the request with basic first. Switch to advanced only if the basic response lacks the data you need. Do not make advanced your default.

A request with advanced differs from the examples below only in the search_depth value:

JSON
{
  "query": "what is new in Cursor IDE",
  "search_depth": "advanced",
  "max_results": 5,
  "lang": "auto"
}

Apps that refresh on their own — dashboards, widgets, scheduled runs — pay for every request. Spend per period is refresh rate × number of widgets × mode price. Cache the result on your side and do not repeat an identical request more often than the data changes.

Examples

curl — personal key

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/search \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "what is new in Cursor IDE",
    "search_depth": "basic",
    "max_results": 5,
    "lang": "auto"
  }'

curl — OAuth application

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/search \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "what is new in Cursor IDE",
    "search_depth": "basic",
    "max_results": 5,
    "lang": "auto"
  }'

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/search', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    query: 'what is new in Cursor IDE',
    search_depth: 'basic',
    max_results: 5,
    lang: 'auto',
  }),
})

const data = await res.json()
console.log(data.answer)
data.results.forEach((r) => console.log(`[${r.id}] ${r.title} — ${r.url}`))

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/search', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    query: 'what is new in Cursor IDE',
    search_depth: 'basic',
    max_results: 5,
    lang: 'auto',
  }),
})

const data = await res.json()

Response fields

Field Type Description
Fieldquery Typestring DescriptionThe original query text
Fieldprovider Typestring DescriptionIdentifier of the provider that processed the request (e.g. bitrix-search, tavily)
Fieldsearch_depth Typestring DescriptionThe applied search depth: basic or advanced
Fieldanswer Typestring | null DescriptionSynthesized answer. Engines with citation support mark the sources with [N]. Comes back null when include_answer: false, and for engines that do not support synthesis: the capabilities.output.synthesizedAnswer flag in GET /v1/search/providers shows which engines do
Fieldresults Typearray DescriptionArray of found sources
Fieldresults[].id Typenumber DescriptionSequential number. Matches the [N] citation marker in answer for engines that emit citations
Fieldresults[].url Typestring DescriptionPage address
Fieldresults[].title Typestring DescriptionPage title
Fieldresults[].content Typestring DescriptionAlways a short description or snippet of the page. The full text arrives in a separate rawContent field, not here
Fieldresults[].rawContent Typestring | null DescriptionThe full page text when include_raw_content: true for engines that support it. Size capped at roughly 40 KB per result. null when the full text was not requested or the engine does not return it
Fieldresults[].score Typenumber | null DescriptionRelevance score from the provider — a number from 0 to 1: the higher the value, the more relevant the result. Comes back null when the engine does not return a score: the capabilities.output.relevanceScore flag in GET /v1/search/providers shows which engines do
Fieldresults[].publishedDate Typestring | null DescriptionPublication date in ISO 8601 format. Comes back null when the engine does not return a date: the capabilities.output.publishedDate flag in GET /v1/search/providers shows which engines do. Engines that support topic: "news" populate it for news results
Fieldimages Typearray DescriptionTop-level array of images when include_images: true for engines that support it. Each element is an object with a url field. Empty array when images were not requested or the engine does not return them
Fieldignored_filters Typestring[] DescriptionThe passed filters and parameters the engine could not apply. The same list as the X-Search-Filters-Ignored header, delivered in the response body. May contain topic, include_images, include_domains, time_range, and others — the set depends on the engine
Fieldsearch_id Typestring DescriptionRequest identifier in the format ws_<14 digits>_<8 hex>
Fieldupstream_search_id Typestring | null DescriptionIdentifier at the external provider. Useful for incident investigation
Fieldcost_vibes Typenumber DescriptionHow many Ꝟ were actually charged
Fieldduration_ms Typenumber DescriptionRequest processing duration in milliseconds
Fieldpartial_charge Typeboolean DescriptionPresent when parallel requests drained the remaining balance before the current charge completed. The request still succeeded, and the amount actually charged is less than the nominal cost — the total is in cost_vibes
Fieldcharge_log_failed Typeboolean DescriptionPresent when the usage log could not be written. The result was delivered, no funds were charged (cost_vibes: 0)

Response example

JSON
{
  "query": "what is new in Cursor IDE",
  "provider": "bitrix-search",
  "search_depth": "basic",
  "answer": "Cursor 3 — a redesign of the IDE interface [1]. An agents window was added [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...",
      "rawContent": null,
      "score": null,
      "publishedDate": null
    },
    {
      "id": 2,
      "url": "https://cursor.com/changelog",
      "title": "Changelog",
      "content": "Latest features in Cursor IDE...",
      "rawContent": null,
      "score": null,
      "publishedDate": null
    }
  ],
  "images": [],
  "ignored_filters": [],
  "search_id": "ws_20260430113025_a1b2c3d4",
  "upstream_search_id": "AG_xyz",
  "cost_vibes": 5,
  "duration_ms": 8523
}

The provider value in the example (bitrix-search) and cost_vibes depend on the instance: without an explicit provider, the request is handled by the default engine configured on the instance (shown by the defaultProvider field in GET /v1/me), and the charged amount is its price from GET /v1/search/providers.

With include_raw_content: true on a supporting engine the rawContent field is populated with the full page text, and with include_images: true the top-level images array is populated with image links. If the engine does not support topic or include_images, those parameters land in ignored_filters.

Output safety. rawContent is unsanitized text from the open web, and images[] are third-party URLs. Before rendering in a browser, sanitize the text and proxy or validate the image links — do not insert them into the DOM as-is.

Streaming (SSE)

With stream: true the response arrives as an event stream with the text/event-stream content type. Each event is an event: <type> + data: <JSON> pair, separated by a blank line.

Possible events:

Event When it occurs data fields
Eventstart When it occursAt the start of the request data fieldssearch_id, provider, search_depth
Eventthinking When it occursIntermediate agent reasoning data fieldscontent — a text fragment
Eventtool_call When it occursThe agent called an internal tool data fieldstool (web_search / content_extraction / external_tool), description
Eventtool_result When it occursThe tool returned a result data fieldsdescription, items_count
Eventanswer_delta When it occursThe next fragment of the final answer data fieldscontent — a chunk of text
Eventdone When it occursThe final block data fieldsthe same fields as in the synchronous response
Eventerror When it occursA failure during processing data fieldserror.code, error.message

Example stream:

event: start
data: {"search_id":"ws_20260430113025_a1b2c3d4","provider":"bitrix-search","search_depth":"basic"}

event: thinking
data: {"content":"Let's look into the sources now"}

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":"a redesign of the IDE interface [1]."}

event: done
data: {"query":"what is new in Cursor IDE","provider":"bitrix-search","search_depth":"basic","answer":"Cursor 3 — a redesign of the IDE interface [1].","results":[{"id":1,"url":"https://cursor.com/blog/cursor-3","title":"Meet the new Cursor","content":"...","rawContent":null,"score":null,"publishedDate":null}],"images":[],"ignored_filters":[],"search_id":"ws_20260430113025_a1b2c3d4","upstream_search_id":"AG_xyz","cost_vibes":5,"duration_ms":8523}

Whether a real event stream with intermediate thinking / tool_call / answer_delta is emitted depends on the engine: for bitrix-search this varies by instance, while the other providers stream in buffered mode — only start and done arrive. A progressive stream is indicated by the capabilities.modes.streaming field in GET /v1/search/providers.

Error response example

402 — insufficient balance:

JSON
{
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Insufficient vibes for this search.",
    "userMessage": "Insufficient vibes — top up your balance or add your own BYOK key (see GET /v1/search/providers).",
    "hint": "Add a BYOK key to search for free — see GET /v1/search/providers",
    "required": 5
  }
}

The required field is the amount in Ꝟ needed for the request. The other situations are listed in the error table below.

Errors

HTTP Code Description
HTTP400 CodeINVALID_REQUEST DescriptionEmpty query, query longer than 400 characters, max_results outside the 1..20 range, max_steps outside the 1..5 range, provider outside the list of supported providers, an unknown value for search_depth, topic, lang or time_range, include_domains / exclude_domains longer than 10 elements
HTTP402 CodeINSUFFICIENT_BALANCE DescriptionThe portal balance does not have enough Ꝟ for the selected mode
HTTP402 CodeBILLING_FROZEN DescriptionThe billing account is frozen
HTTP402 Codecompany_budget_exhausted DescriptionThe monthly company spend budget set by the portal administrator is exhausted. The scope field names the budget that was hit: USER — the caller's own budget, PORTAL — the budget of the whole portal. The canRequest field tells whether an increase can be requested: true for a personal budget, false for the portal one, which only an administrator raises. The rejection arrives only on a paid call. A search made with your own BYOK key is free and keeps working
HTTP403 CodeSCOPE_DENIED DescriptionThe key lacks the vibe:search scope
HTTP404 CodePROVIDER_NOT_FOUND DescriptionThe provider passed does not exist in the system or is disabled
HTTP404 CodeCREDENTIAL_NOT_FOUND DescriptionThe provider has no USER, PORTAL, or PLATFORM key
HTTP404 CodePROVIDER_DOES_NOT_SUPPORT_SEARCH Descriptionprovider: "jina" was requested — Jina works only in POST /v1/research. The search_id field is present in the response
HTTP429 CodeRATE_LIMITED DescriptionExceeded the limit of 60 requests per minute per portal, shared across all of the portal's API keys. The exact value arrives in the x-ratelimit-limit header (the cap is divided across replicas)
HTTP429 CodeSEARCH_DAILY_CAP_REACHED DescriptionWith this request, the Bitrix24 account's paid search spend for the current day in UTC+3 would exceed the cap set by the Bitrix24 account admin. The provider is not called and nothing is charged. The cap is shared by /v1/search and POST /v1/research. The response carries a Retry-After header, and the error body carries resetAt — the start of the next day in UTC+3 — and hint. Searches on your own BYOK key are not limited by the cap
HTTP500 CodeINTERNAL_ERROR DescriptionInternal server error. The response contains search_id
HTTP401/403/429/502 CodeUPSTREAM_ERROR DescriptionThe provider returned an error; no charge. The upstream_status field in the response carries the provider's original status. For a BYOK key, provider 401 and 403 responses keep their status — the provider rejected your key, so retrying without replacing it will not help. A provider 429 keeps its status for any key and carries the Retry-After header — retry later. Every other provider error, including a rejected platform-engine key, arrives as 502 — retry the request
HTTP503 CodeFEATURE_NOT_ENABLED DescriptionWeb Search is unavailable on this platform
HTTP503 CodeUPSTREAM_TIMEOUT DescriptionThe provider exceeded the request timeout. No charge. The response carries the Retry-After: 30 header — retry the request after the time it specifies

The full list of common API errors — Errors.

Known specifics

Key selection cascade. When the provider field is omitted, the platform picks the source in the order: user key (USER BYOK) → Bitrix24 account key (PORTAL BYOK) → the default engine configured on the instance (shown by the defaultProvider field in GET /v1/me). Your own BYOK key with isDefault: true is used automatically — you do not need to pass provider.

The charge happens only after a successful response. Before the request the balance is checked: if insufficient, 402 INSUFFICIENT_BALANCE is returned without calling the provider. On UPSTREAM_ERROR or UPSTREAM_TIMEOUT the balance does not change — the provider returned no result, so there is nothing to charge for.

The default engine ignores lang in /v1/search. It does not forward lang to the upstream provider — the field always appears in X-Search-Filters-Ignored.

An empty result set is charged in full. When the provider found no sources and returned results: [], cost_vibes is still charged in full. This is by design: the charge covers the provider's processing of the request, not the number of results.

The charge_log_failed field signals a lost audit record. If the provider responds successfully but the usage log cannot be written, the response is still delivered to the client with cost_vibes: 0 and the charge_log_failed: true flag. No Vibe credits are charged — the audit log for this request is also absent. The scenario is rare and is visible in the AI Search section (/search).

provider: "jina" is available only in /v1/research. A request with provider: "jina" on the current endpoint returns 404 PROVIDER_DOES_NOT_SUPPORT_SEARCH. The list of providers supporting /v1/search is checked via the capabilities.modes.search.basic or capabilities.modes.search.advanced field in GET /v1/search/providers.

A Bitrix24 account admin can turn off the advanced mode. Paid search through the platform engine with search_depth: "advanced" then runs as basic, and the request is not rejected. The response and the SSE start and done events carry search_depth: "basic", and the response headers, synchronous and streaming alike, include X-Search-Depth-Downgraded: advanced. The charge follows the basic price, and the request counts toward the daily spend cap at that price. Search on your own BYOK key is not affected.

See also