
# Web Search for AI

REST endpoints for web search on behalf of AI agents and applications. A single request returns a synthesized answer with links to sources; streaming mode delivers results as they become ready. For deep research with a multi-step agentic loop, use the separate [`POST /v1/research`](/docs/search/research) endpoint.

**Scope:** `vibe:search` (added automatically when a key is created) | **Base URL:** `https://vibecode.bitrix24.com/v1` | **Authorization:** `X-Api-Key`

[Quickstart](#quickstart) | [Endpoint reference](#endpoint-reference) | [Pricing](#pricing) | [Error codes](#error-codes) | [RAG recipe with LLM](/docs/recipes/web-search-with-llm)

## Documentation sections

- [Search](/docs/search/run) — synchronous request and streaming (SSE) via `POST /v1/search`
- [Deep research](/docs/search/research) — multi-step agentic research `POST /v1/research`
- [Providers](/docs/search/providers) — list of search engines and their capabilities
- [Your own keys (BYOK)](/docs/search/credentials) — adding personal keys for free search

## Which key to choose

Web Search works with two types of keys. The choice depends on whose behalf you send the request.

| Scenario | Key | Request headers |
|---------|------|-------------------|
| Your own Bitrix24 account, personal script or server | Personal API key `vibe_api_…` | `X-Api-Key: vibe_api_…` |
| Request on behalf of an end user in an OAuth application | Authorization key `vibe_app_…` | `X-Api-Key: vibe_app_…` + `Authorization: Bearer <session_token>` |

More on key formats and obtaining a `session_token` — [Keys and authorization](/docs/keys-auth).

## Providers

The platform offers platform-managed engines billed in Vibe credits, plus BYOK providers billed directly by the vendor. Which engines are available on a given instance, which one is platform-managed, and what it costs depend on the instance configuration. The current list is returned by [`GET /v1/search/providers`](/docs/search/providers).

| Provider | Purpose | Pricing |
|-----------|-----------|-----------|
| `bitrix-search` | Platform web search. The specific engine and its capabilities depend on the instance — see [`GET /v1/search/providers`](/docs/search/providers) | platform-managed, price in Vibe credits — see [`GET /v1/search/providers`](/docs/search/providers) |
| `tavily` | Tavily — web search with domain and time filters, relevance scoring | 0 Ꝟ (BYOK) |
| `brave` | Brave Search — private web search, optional summarizer in `advanced` | 0 Ꝟ (BYOK) |
| `exa` | Exa — neural/semantic search with full content extraction | 0 Ꝟ (BYOK) |
| `you-com` | You.com — search with citations and follow-up questions | 0 Ꝟ (BYOK) |
| `linkup` | Linkup — real-time web crawl with deep research mode | 0 Ꝟ (BYOK) |
| `perplexity` | Perplexity Sonar — Sonar models for search and deep research | 0 Ꝟ (BYOK) |
| `jina` | Jina DeepSearch — iterative "search → read → think" loop, research only | 0 Ꝟ (BYOK) |
| `z-ai` | Z.AI Web Search — search without a synthesized answer, with publication dates | 0 Ꝟ (BYOK) |

The current list with the capability matrix and prices — [`GET /v1/search/providers`](/docs/search/providers). Which provider is platform-managed, its price, and the default engine vary from instance to instance. All BYOK providers require your own key, which you add via [Your own keys (BYOK)](/docs/search/credentials). BYOK providers always cost 0 Ꝟ on the platform side.

## Supported provider capabilities

The full capability matrix is available in [`GET /v1/search/providers`](/docs/search/providers) — `capabilities` for each provider. The key subsets are shown below in three tables, one per group.

### Modes and streaming

| Provider | `basic` | `advanced` | `research` | Stream |
|-----------|:-------:|:----------:|:----------:|:------|
| `bitrix-search` | ✓ | ✓ | instance-dependent | instance-dependent |
| `tavily` | ✓ | ✓ | ✓ | buffered |
| `brave` | ✓ | ✓ | ✗ | buffered |
| `exa` | ✓ | ✓ | ✓ | buffered |
| `you-com` | ✓ | ✓ | ✓ | buffered |
| `linkup` | ✓ | ✓ | ✓ | buffered |
| `perplexity` | ✓ | ✓ | ✓ | buffered |
| `jina` | ✗ | ✗ | ✓ | buffered |
| `z-ai` | ✓ | ✓ | ✗ | buffered |

Progressive streaming emits intermediate `thinking` / `tool_call` / `answer_delta` events. Buffered streaming sends only `start` and `done`.

### Synthesized answer and formatting

| Provider | `answer` | Citations `[N]` | `score` | `publishedDate` | Follow-up questions |
|-----------|:--------:|:------------:|:-------:|:----------------:|:-------------------:|
| `bitrix-search` | ✓ | instance-dependent | instance-dependent | instance-dependent | ✗ |
| `tavily` | ✓ | ✗ | ✓ | ✓ | ✗ |
| `brave` | in `advanced` | ✗ | ✗ | ✓ | ✗ |
| `exa` | ✓ | ✓ | ✓ | ✓ | ✗ |
| `you-com` | ✓ | ✓ | ✗ | ✓ | ✓ |
| `linkup` | ✓ | ✓ | ✗ | ✓ | ✗ |
| `perplexity` | ✓ | ✓ | ✗ | ✗ | ✗ |
| `jina` | ✓ | ✓ | ✗ | ✓ | ✗ |
| `z-ai` | ✗ | ✗ | ✗ | ✓ | ✗ |

For `brave`, the `answer` field is returned only with `search_depth: "advanced"`, via the optional summarizer. In `basic` it is `null`.

### Filters

| Provider | `include_domains` | `exclude_domains` | `time_range` |
|-----------|:-----------------:|:-----------------:|:------------:|
| `bitrix-search` | instance-dependent | instance-dependent | instance-dependent |
| `tavily` | ✓ | ✓ | ✓ |
| `brave` | ✗ | ✗ | ✓ |
| `exa` | ✓ | ✓ | ✗ |
| `you-com` | ✗ | ✗ | ✗ |
| `linkup` | ✗ | ✗ | ✗ |
| `perplexity` | ✗ | ✗ | ✗ |
| `jina` | ✓ | ✓ | ✗ |
| `z-ai` | ✓ | ✗ | ✓ |

When the selected provider does not support a passed filter, the request completes without error — the filter is ignored. The response carries an `X-Search-Filters-Ignored` header with the list of skipped fields:

```
X-Search-Filters-Ignored: include_domains,time_range
```

For `brave` with `include_answer: true` and `search_depth: "basic"`, an additional `X-Answer-Not-Supported: brave-search-does-not-synthesize-answers` header is returned, and the `answer` field in JSON is `null`. In `advanced` mode the same provider engages the summarizer and returns a populated `answer`.

## When to choose which provider

Quick guidelines:

- **`bitrix-search`** — platform web search, requires no key of your own (billed in Vibe credits). Returns a synthesized `answer` with sources — ready-made RAG output for AI agents, with no separate assembly step. Its specific capabilities (the `research` mode, progressive SSE streaming, filters) depend on the instance — the exact matrix is in [`GET /v1/search/providers`](/docs/search/providers).
- **`tavily`** — domain filters (`include_domains` / `exclude_domains`), publication time window (`time_range`), numeric relevance score (`score`). A universal choice for English-language queries.
- **`brave`** — web search without `answer` synthesis by default; the synthesizer is enabled on `advanced`. Suitable for English-language results and private queries.
- **`exa`** — neural/semantic search. Suitable for research tasks that need semantically related pages rather than an exact keyword match.
- **`you-com`** — the only provider with follow-up questions in research mode.
- **`linkup`** — real-time web crawl (`liveData: true`), suitable for queries about events from the last few hours.
- **`perplexity`** — Sonar models, OpenAI-compatible format, deep research with citations.
- **`jina`** — research mode only, an iterative "search → read → think" loop. Not available via [`POST /v1/search`](/docs/search/run).
- **`z-ai`** — search without a synthesized answer, returns results with publication dates.

## Quickstart

A minimal call to [`POST /v1/search`](/docs/search/run): the question text in the `query` field and `advanced` mode for agentic search. The response contains a synthesized `answer` and a `results` array with the pages found; whether citations are included depends on the instance engine — see the capability matrix.

```bash
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": "advanced",
    "max_results": 5
  }'
```

Response:

```json
{
  "query": "what is new in Cursor IDE",
  "provider": "bitrix-search",
  "search_depth": "advanced",
  "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": "...",
      "score": null,
      "publishedDate": null
    },
    {
      "id": 2,
      "url": "https://cursor.com/changelog",
      "title": "Changelog",
      "content": "...",
      "score": null,
      "publishedDate": null
    }
  ],
  "search_id": "ws_20260430113025_a1b2c3d4",
  "upstream_search_id": "AG_xyz",
  "cost_vibes": 5,
  "duration_ms": 8523
}
```

The `[1]`, `[2]` markers in the `answer` field correspond to `results[].id` values. The `provider` value in the response (here `bitrix-search`) depends on the instance — without an explicit `provider`, the request goes through the default engine configured on the instance. The current default is shown by the `defaultProvider` field in [`GET /v1/me`](/docs/keys-auth).

## Full scenario: RAG with LLM

Pairing `/v1/search` + `/v1/ai/chat/completions` for LLM answers grounded in fresh sources with `[N]` citation markers — a ready-made integration recipe:

→ [Web search + LLM (RAG)](/docs/recipes/web-search-with-llm)

## Pricing

Cost is expressed in the platform's virtual currency — Vibe credits (Ꝟ). The charge occurs after a successful provider response. On a provider error the balance is unchanged.

The platform provider's pricing varies from instance to instance — which engine is platform-managed and how many Ꝟ its `basic` / `advanced` / `research` modes cost are returned by [`GET /v1/search/providers`](/docs/search/providers) in the `pricing` field. BYOK providers (`tavily`, `brave`, `exa`, `you-com`, `linkup`, `perplexity`, `jina`, `z-ai`) always cost 0 Ꝟ on the platform side — you pay the vendor directly for those requests, at the vendor's own rates.

The `cost_vibes` field in the response shows the amount actually charged.

Request history broken down by provider, Vibe credits spent by period, and average duration are available on the `/search` page in your Vibecode account. There you can also add, test, and delete BYOK keys through a visual interface. The "Use" button next to each provider opens a dialog with ready-made snippets in cURL, JavaScript, Python, the TypeScript SDK, and a text prompt for AI assistants.

## Rate limit

- 60 requests per minute per Bitrix24 account for [`POST /v1/search`](/docs/search/run).
- 20 requests per minute per Bitrix24 account for [`POST /v1/research`](/docs/search/research) — deep research takes tens of times longer than a regular search.

The limit is shared by every API key of the Bitrix24 account — they all draw from the same pool. Spreading the load across several keys does not raise the ceiling.

When exceeded, `429 RATE_LIMITED` is returned.

## Endpoint reference

| Method | Path | Description |
|-------|------|----------|
| POST | [`/v1/search`](/docs/search/run) | Synchronous request or streaming |
| POST | [`/v1/research`](/docs/search/research) | Deep research with a multi-step agentic loop, SSE only |
| GET | [`/v1/search/providers`](/docs/search/providers) | List of providers with the capability matrix and pricing |
| GET | [`/v1/search/credentials`](/docs/search/credentials/list) | List of your BYOK keys |
| POST | [`/v1/search/credentials`](/docs/search/credentials/create) | Add a BYOK key for the selected provider |
| DELETE | [`/v1/search/credentials/:id`](/docs/search/credentials/delete) | Delete a BYOK key |
| POST | [`/v1/search/credentials/:id/test`](/docs/search/credentials/test) | Test a BYOK key |

## Key selection cascade

When `provider` is not passed in the [`POST /v1/search`](/docs/search/run) request, the platform selects it in the following 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`](/docs/keys-auth)).

For [`POST /v1/research`](/docs/search/research) the cascade works differently. If the `provider` field is omitted, the server immediately substitutes the default research engine configured on the instance — a USER/PORTAL default for a different provider (e.g. `exa`) is not considered here. If that engine has no USER, PORTAL, or PLATFORM key, `404 CREDENTIAL_NOT_FOUND` is returned. The USER → PORTAL → PLATFORM cascade is applied **within** the selected provider. To go through a different research provider, pass `provider` explicitly.

Once you add your own BYOK key with `isDefault: true`, the platform uses it automatically — the `provider` parameter can be omitted.

## Migration from Tavily

The request schema mirrors the Tavily Search API. Differences:

- Endpoint: `https://api.tavily.com/search` → `https://vibecode.bitrix24.com/v1/search`.
- Authorization: the `api_key` field in the body → the `X-Api-Key: YOUR_API_KEY` header.
- Added an optional `provider` field — choice of engine from the available list.
- Added optional `topic` (`general` or `news`) and `include_images` (image requests) fields. Tavily has these capabilities, but other engines do not. Unsupported fields are ignored and listed in `ignored_filters`.

If you have your own Tavily key, add it via [`POST /v1/search/credentials`](/docs/search/credentials/create) and use `provider: "tavily"` or make the key the default. The other request fields work identically.

## Error codes

### Web search errors

| Code | HTTP | Description |
|-----|------|---------|
| `INVALID_REQUEST` | 400 | Validation failed — empty `query`, `query` longer than the limit, unknown value for `provider`, `search_depth`, `topic`, `lang` or `time_range`, `include_domains` / `exclude_domains` limits exceeded |
| `INSUFFICIENT_BALANCE` | 402 | The portal balance does not have enough Ꝟ for the selected mode. Switch to BYOK or top up the balance |
| `BILLING_FROZEN` | 402 | The billing account is frozen — top up the balance and remove the block in your Vibecode account |
| `PROVIDER_NOT_FOUND` | 404 | The `provider` passed is not in the system or is unavailable |
| `CREDENTIAL_NOT_FOUND` | 404 | The requested provider has no BYOK key for the user or portal, and there is no platform key |
| `PROVIDER_DOES_NOT_SUPPORT_SEARCH` | 404 | `provider: "jina"` was requested in [`POST /v1/search`](/docs/search/run) — Jina works only in [`POST /v1/research`](/docs/search/research) |
| `PROVIDER_DOES_NOT_SUPPORT_RESEARCH` | 404 | `brave` or `z-ai` — or `bitrix-search` when the instance engine lacks research — was requested in [`POST /v1/research`](/docs/search/research). These providers work only in [`POST /v1/search`](/docs/search/run). On an instance where `bitrix-search` maps to a research-capable engine, `/v1/research` accepts it |
| `RATE_LIMITED` | 429 | The per-minute request limit per portal was exceeded |
| `UPSTREAM_ERROR` | 502 | The provider returned an error. No charge — retry the request |
| `FEATURE_NOT_ENABLED` | 503 | Web Search or deep research is unavailable on this platform |
| `UPSTREAM_TIMEOUT` | 503 | The provider exceeded the request timeout. The response carries the `Retry-After: 30` header — retry the request after the time it specifies |

### BYOK key errors

| Code | HTTP | Description |
|-----|------|---------|
| `INVALID_CREDENTIAL` | 400 | When creating a BYOK key, the provider rejected it during the pre-flight check. The record was not saved |
| `INVALID_REQUEST` | 400 | `apiKey` not specified, invalid `provider`, name longer than 64 characters |

### System errors

| Code | HTTP | Description |
|-----|------|---------|
| `MISSING_API_KEY` | 401 | The `X-Api-Key` header is missing |
| `INVALID_API_KEY` | 401 | Invalid API key |
| `KEY_INACTIVE` | 401 | The API key is deactivated, blocked, or expired |
| `SCOPE_DENIED` | 403 | The key lacks the `vibe:search` scope |
| `INTERNAL_ERROR` | 500 | Internal server error |

The full list of common API errors — [Errors](/docs/errors).

## Error response structure

```json
{
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Insufficient vibes for this search.",
    "userMessage": "Insufficient Vibe credits — 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 `userMessage` and `required` fields are returned on the `INSUFFICIENT_BALANCE` and `BILLING_FROZEN` billing errors. The `required` field is the amount in Ꝟ needed for the request. The `hint` field is returned on those same billing errors and on `CREDENTIAL_NOT_FOUND`, where it explains how to add your own BYOK key for the selected provider.

## See also

- [Search (POST /v1/search)](/docs/search/run) — request parameters, streaming format, response fields
- [Deep research (POST /v1/research)](/docs/search/research) — multi-step agentic research
- [Providers](/docs/search/providers) — table of providers with the capability matrix
- [Your own keys (BYOK)](/docs/search/credentials) — adding and testing BYOK keys
- [Web search + LLM (RAG)](/docs/recipes/web-search-with-llm) — recipe pairing `/v1/search` with `/v1/ai/chat/completions`
- [Keys and authorization](/docs/keys-auth) — personal key and authorization key, obtaining a `session_token`
- [AI Router](/docs/ai) — a unified interface to chat models
- [Limits and optimization](/docs/optimization) — common request rate rules
- [Errors](/docs/errors) — API error code reference
