
## Test a key

`POST /v1/search/credentials/:id/test`

Checks whether the provider accepts the saved BYOK key. Internally it sends a minimal validation request to the provider's API and returns the result. The key's `lastVerifiedAt` and `lastError` fields are updated in any case — whether the check succeeds or not.

## Parameters

| Parameter | Type | Req. | Description |
|----------|-----|:-----:|---------|
| `id` (path) | string | yes | Key identifier from the [`GET /v1/search/credentials`](/docs/search/credentials/list) response or from the creation response |

The request body is not passed. Unknown fields are ignored.

## Examples

### curl — personal key

```bash
curl -X POST \
  -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.com/v1/search/credentials/cmol3pnk5001fo70zefbwb6dl/test
```

### curl — OAuth app

```bash
curl -X POST \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  https://vibecode.bitrix24.com/v1/search/credentials/cmol3pnk5001fo70zefbwb6dl/test
```

### JavaScript — personal key

```javascript
const res = await fetch(
  'https://vibecode.bitrix24.com/v1/search/credentials/cmol3pnk5001fo70zefbwb6dl/test',
  {
    method: 'POST',
    headers: { 'X-Api-Key': 'YOUR_API_KEY' },
  },
)

const result = await res.json()
if (result.valid) {
  console.log('The key was accepted by the provider')
} else {
  console.error('The check failed:', result.error)
}
```

### JavaScript — OAuth app

```javascript
const res = await fetch(
  'https://vibecode.bitrix24.com/v1/search/credentials/cmol3pnk5001fo70zefbwb6dl/test',
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
    },
  },
)

const result = await res.json()
```

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `valid` | boolean | `true` — the provider accepted the key. `false` — the provider responded with an error |
| `error` | string \| null | The provider's error text. `null` when `valid: true` |

## Response example

Successful check:

```json
{
  "valid": true,
  "error": null
}
```

The provider did not accept the key:

```json
{
  "valid": false,
  "error": "Upstream HTTP 401"
}
```

## Error response example

404 — the key is not found:

```json
{
  "error": {
    "code": "CREDENTIAL_NOT_FOUND",
    "message": "cmol3pnk5001fo70zefbwb6dl"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |
| 401 | `INVALID_API_KEY` | Invalid API key |
| 401 | `UNAUTHORIZED` | The request goes through a `vibe_app_…` key without `Authorization: Bearer <session_token>` |
| 403 | `SCOPE_DENIED` | The key lacks the `vibe:search` scope |
| 404 | `CREDENTIAL_NOT_FOUND` | A key with this `id` does not exist for the current user |
| 429 | `RATE_LIMITED` | The overall request limit is exceeded |
| 500 | `INTERNAL_ERROR` | Internal server error |

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

## Known specifics

**Distinguish the error levels.** HTTP 200 with `valid: false` — the provider responded but rejected the key (invalid token, expired key). HTTP 4xx — an authorization error in the Vibe API. Check the response status first, then the `valid` field.

**State update.** On `valid: true`, the key's `lastVerifiedAt` and `lastError` fields are reset to the current time and `null`. On `valid: false` — `lastVerifiedAt` is also updated (to record that a check occurred), and `lastError` is recorded. You can get the current state via [`GET /v1/search/credentials`](/docs/search/credentials/list).

**The check does not charge Ꝟ.** The endpoint makes a minimal validation call that bypasses the billing cycle, so the user's balance does not change.

## See also

- [Your own keys (BYOK)](/docs/search/credentials) — subsection overview
- [List your keys](/docs/search/credentials/list) — `GET /v1/search/credentials`, view `lastVerifiedAt` and `lastError`
- [Add a key](/docs/search/credentials/create) — `POST /v1/search/credentials`
- [Delete a key](/docs/search/credentials/delete) — `DELETE /v1/search/credentials/:id`
- [Search (POST /v1/search)](/docs/search/run) — BYOK key selection cascade
- [Errors](/docs/errors) — API error code reference
