For AI agents: markdown of this page — /docs-content-en/search/credentials/create.md documentation index — /llms.txt

Add a key

POST /v1/search/credentials

Saves a BYOK key for the chosen provider for the current user. After it is added, calls to POST /v1/search and POST /v1/research with that provider do not charge Ꝟ — you are billed directly by the provider.

Before saving, the server makes a trial call to the provider with the supplied key. If the provider rejects the key — 400 INVALID_CREDENTIAL is returned and the record is not created. Only after a successful check is the key encrypted and saved. After saving, the original value cannot be returned through the API — the output contains only the mask <first 5>********<last 4>.

Request fields (body)

Field Type Required Default Description
Fieldprovider Typestring Requiredyes Default— DescriptionOne of the BYOK providers: tavily, brave, exa, you-com, linkup, perplexity, jina, z-ai. bitrix-search is not accepted through v1
FieldapiKey Typestring Requiredyes Default— DescriptionA token from the chosen provider. Tavily — format tvly-…, Brave — a subscription token from the Brave dashboard, the rest — a token from the corresponding provider's dashboard
Fieldname Typestring Requiredyes Default— DescriptionA custom label for the key, shown in the list. From 1 to 64 characters
FieldisDefault Typeboolean Requiredno Defaultfalse DescriptionMake it default for the provider. Requests to POST /v1/search and POST /v1/research without the provider field will go through this key

Examples

curl — personal key

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/search/credentials \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "tavily",
    "apiKey": "YOUR_TAVILY_API_KEY",
    "name": "My Tavily",
    "isDefault": true
  }'

curl — OAuth application

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/search/credentials \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "tavily",
    "apiKey": "YOUR_TAVILY_API_KEY",
    "name": "My Tavily",
    "isDefault": true
  }'

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/search/credentials', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    provider: 'tavily',
    apiKey: 'YOUR_TAVILY_API_KEY',
    name: 'My Tavily',
    isDefault: true,
  }),
})

const cred = await res.json()
console.log('Key created:', cred.id)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/search/credentials', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    provider: 'tavily',
    apiKey: 'YOUR_TAVILY_API_KEY',
    name: 'My Tavily',
    isDefault: true,
  }),
})

const cred = await res.json()

Response fields

Field Type Description
Fieldid Typestring DescriptionIdentifier of the created key. Passed to DELETE /v1/search/credentials/:id and POST /v1/search/credentials/:id/test
Fieldprovider Typestring DescriptionProvider identifier: one of the eight BYOK providers
Fieldscope Typestring DescriptionVisibility level. When created through v1 — always USER
Fieldname Typestring DescriptionLabel from the request
FieldmaskedKey Typestring DescriptionMask <first 5>********<last 4>
FieldisDefault Typeboolean DescriptionWhether the key became default for the provider
FieldcreatedAt Typestring DescriptionCreation date in ISO 8601 format

Response example

201 — key created:

JSON
{
  "id": "cmol3pnk5001fo70zefbwb6dl",
  "provider": "tavily",
  "scope": "USER",
  "name": "My Tavily",
  "maskedKey": "tvly-********f456",
  "isDefault": true,
  "createdAt": "2026-04-30T06:26:51.653Z"
}

Error response example

400 — the provider rejected the key during the pre-check:

JSON
{
  "error": {
    "code": "INVALID_CREDENTIAL",
    "message": "Upstream HTTP 401"
  }
}

400 — an attempt to add bitrix-search:

JSON
{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "provider: Invalid enum value. Expected 'tavily' | 'brave' | 'exa' | 'you-com' | 'linkup' | 'perplexity' | 'jina' | 'z-ai', received 'bitrix-search'"
  }
}

Other situations are listed in the error table below.

Errors

HTTP Code Description
HTTP400 CodeINVALID_CREDENTIAL DescriptionThe provider rejected the key during the pre-check. The record is not saved. The message contains the reason — for example, Upstream HTTP 401 for a revoked Tavily key, Upstream HTTP 422 for an invalid Brave subscription token
HTTP400 CodeINVALID_REQUEST DescriptionapiKey not specified, name empty or longer than 64 characters, provider not from the list of eight BYOK providers
HTTP401 CodeMISSING_API_KEY DescriptionThe X-Api-Key header is missing
HTTP401 CodeINVALID_API_KEY DescriptionThe key is not recognized — no such key exists on the platform
HTTP401 CodeUNAUTHORIZED DescriptionThe request goes through a vibe_app_… key without Authorization: Bearer <session_token>
HTTP403 CodeSCOPE_DENIED DescriptionThe key lacks the vibe:search scope
HTTP404 CodePROVIDER_NOT_FOUND DescriptionA provider with this identifier does not exist or is disabled
HTTP429 CodeRATE_LIMITED DescriptionThe overall request limit is exceeded
HTTP500 CodeINTERNAL_ERROR DescriptionInternal server error

The full list of common API errors — Errors.

Known specifics

One default key per provider. When a new key is created with isDefault: true, all other USER keys of the same provider automatically stop being default. The previous key stays in the system — it can be used through an explicit provider in POST /v1/search or deleted.

Several keys of one provider without a default. When a user has several USER keys of one provider, none is marked isDefault: true, and only provider is specified in POST /v1/search — the most recent one by createdAt is taken. For predictable behavior, mark the desired key as default.

The key is verified with the provider before saving. The server makes a trial call to the chosen provider with the supplied apiKey. The record is created only on a positive result; in that case the lastVerifiedAt field is immediately filled with the current date. This closes the class of errors "a key chosen as default that the provider has already revoked" and removes the need for a separate POST /v1/search/credentials/:id/test step right after creation. The test endpoint is needed later — to re-verify an already-saved key after rotation at the provider.

Network errors before reaching the provider are masked as INVALID_CREDENTIAL. If the verification request did not reach the provider (DNS, a network timeout between Vibecode and the provider), the user sees the same 400 INVALID_CREDENTIAL with a message about the reason. This is a safe default — not to save a key whose status is not confirmed. Retry after a short time.

See also