# Authorization, keys and permissions

A detailed breakdown of the codes the Vibecode API returns when a key is not recognized, lacks the required permissions, or runs in read-only mode.

The summary table of all Vibecode API codes — [Error codes](/docs/errors).

## `MISSING_API_KEY` (401)

The request carries no `X-Api-Key` header.

```json
{
  "success": false,
  "error": {
    "code": "MISSING_API_KEY",
    "message": "API key required. Pass via X-Api-Key header."
  }
}
```

**Causes:**
- The `X-Api-Key` or `Authorization` header was not passed.
- The header was passed with an empty value.

**Fix:**
- Add the `X-Api-Key: vibe_api_...` or `X-Api-Key: vibe_app_...` header.
- Verify that the environment variable holding the key is set correctly (for CLI tools and SDKs).

---

## `INVALID_API_KEY` (401)

The passed key does not exist or its format is unrecognized.

```json
{
  "success": false,
  "error": {
    "code": "INVALID_API_KEY",
    "message": "Invalid API key"
  }
}
```

**Causes:**
- A typo or extra whitespace in the key.
- The key was deleted by its owner or an administrator.
- The key is from a different environment — staging instead of production or the other way around.
- The prefix is not among the supported ones: `vibe_api_`, `vibe_app_`, `vibe_live_`.

**Fix:**
- Check the key in your account on the `/keys` page.
- Create a new key if the old one was deleted.

---

## `TOKEN_MISSING` (401)

The key carries no Bitrix24 credentials, so there is no way to call Bitrix24.
The cause depends on the key type — these are two different scenarios.

**A personal key (`vibe_api_*`)** reaches Bitrix24 through a webhook. When the key has no
webhook, the response on entity calls (`/v1/{entity}` and `POST /v1/batch`) carries a
machine-readable reason in `error.details`. Other routes return the same code without `details`:

```json
{
  "success": false,
  "error": {
    "code": "TOKEN_MISSING",
    "message": "This personal API key (vibe_api_*) has no Bitrix24 webhook credentials, ...",
    "details": {
      "reason": "INT_TARIFF_REQUIRED",
      "paywallCode": "INT_TARIFF_REQUIRED"
    }
  }
}
```

Values of `details.reason`:

| Reason | What it means | What to do |
|---|---|---|
| `INT_TARIFF_REQUIRED` | The Bitrix24 account is not on a commercial plan | Upgrade to a commercial plan, then reconnect the key |
| `VIBE_SCOPES_ONLY` | The key requested no Bitrix24 scope at all — by design it gets no webhook | Create a key with the Bitrix24 scopes you need |
| `WEBHOOK_NOT_CONFIGURED` | Bitrix24 access is fine or undetermined, and the key carries no webhook | Reconnect the key. When `details.hint` is present, re-check via `GET /v1/me?refresh=tariff` |
| `WEBHOOK_MINT_REFUSED_BY_PORTAL` | Bitrix24 refused the key owner the right to create incoming webhooks — that right is closed by default and a regular employee cannot grant it to themselves | A portal administrator must open the right to create incoming webhooks; the platform then mints the webhook on its own within 15 minutes, no reconnect needed |
| `WEBHOOK_MINT_FAILED` | The last webhook-mint attempt failed for an unrecognized reason | No action needed — the platform retries automatically; check again via `GET /v1/me?refresh=tariff` |

**Reconnecting** — `POST /api/keys/:id/reconnect`: issues a webhook for the key without
changing the key string (no integration has to be reconfigured) and clears the auto-disable
on linked bots. Not applicable to app keys, system-managed keys, or keys with no Bitrix24
scopes — those still need a new key.

⚠️ Reconnecting is NOT available for every key: the platform refuses it with
`400 RECONNECT_NOT_APPLICABLE` for app keys, keys with a system-managed purpose (including the
Cowork key), keys linked to a server, to a live agent or to a live managed bot, and keys with
no Bitrix24 scopes. For
these keys the error message does not offer reconnecting at all — the cause has to be closed on
the Bitrix24 account, and the platform then mints the webhook on its own.

`paywallCode` arrives only for the plan-related reason and repeats it. The `upgradeUrl`
field — a link to the upgrade page in the Bitrix24 account — never comes with
`INT_TARIFF_REQUIRED`.

The same condition also blocks app installation and placement binding —
there it arrives as a standalone `403` code, covered in [Billing and plans](/docs/errors/billing).

**An app key (`vibe_app_*`)** keeps the Bitrix24 tokens in a per-user session, not on
the key. For a call with `X-Api-Key` alone and no `Authorization: Bearer <session token>`,
`TOKEN_MISSING` is the correct answer — this branch carries no `details`, and `message`
describes the missing OAuth step. Full flow — [Keys and authorization](/docs/keys-auth).

**How to check a key's state up front:** `GET /v1/me` for a personal key returns a
`b24Credentials` block (`ready`, and when `ready: false` the same `reason` plus actions), and
`GET /v1/keys` returns a `b24Ready` flag on every key. The `/v1/me` response is cached for 30 seconds,
so right after fixing the Bitrix24 side, request it as `GET /v1/me?refresh=tariff` — otherwise
the previous state is returned for up to half a minute. `GET /v1/keys` is not cached.

---

## `SCOPE_DENIED` (403)

The key lacks the required scope for the requested operation.

```json
{
  "success": false,
  "error": {
    "code": "SCOPE_DENIED",
    "message": "This endpoint requires 'crm' scope"
  }
}
```

**Causes:**
- CRM entities require the `crm` scope, tasks require `task`, the bot platform requires `imbot`, the AI Router requires `vibe:ai`, infrastructure requires `vibe:infra`.
- The key's scope was narrowed at creation time.

**Fix:**
- Open the key page in your account and issue a new key with a broader scope set.
- The full list of scopes and their purpose is on the [Keys and authorization](/docs/keys-auth) page.

---

## `BITRIX_ACCESS_DENIED` (403)

Bitrix24 returned `ACCESS_DENIED`: the user or app lacks permission for the entity or operation.

```json
{
  "success": false,
  "error": {
    "code": "BITRIX_ACCESS_DENIED",
    "message": "ACCESS_DENIED"
  }
}
```

**Causes:**
- The user lacks permission for the entity in CRM (e.g. another user's deal with restricted visibility).
- The scope set in the Bitrix24 account is narrower than the key's own scope set. Bitrix24 scopes are fixed for the key at issue time, so a scope added to an already issued key shows up in `GET /v1/me`, while the key still accesses the account's data with its original set.
- The requested module is disabled in the Bitrix24 account (no CRM, no bot platform, and so on).

**The fix depends on the key type.** When the refusal comes from the scope set, `error.hint` names the specific case. The hint is not always there: a bare `ACCESS_DENIED` with no explanation from Bitrix24 may arrive without one.

- **API key (`vibe_api_`).** The scope set the key uses to call Bitrix24 is stored on the account side, separately from the set recorded on the key itself. [Reissue the key](/docs/keys-auth#reissue), reconnect it, or create a new one with the scope selected — editing the app's permissions in the account changes nothing in this case.
- **Authorization key (`vibe_app_`).** Recreate the application with the required scope and complete authorization again. Reissuing the key does not grant a scope here.
- **Chat and bot methods.** For these methods the refusal is not explained by scopes alone: the key owner must be an administrator of the Bitrix24 account. Issue the key under an administrator account — widening the scopes will not help here.
- If the cause is the employee's permissions rather than the key's scopes, check the user's permissions in the Bitrix24 entity card.

For the full description of how scopes are fixed to a key, and what to do if the refusal repeats after a reissue, see [Keys and authorization](/docs/keys-auth).

---

## `WRITE_BLOCKED_READONLY_KEY` (403)

The key is in read-only mode (`accessMode: "READONLY"`), but the request performs a write. The mode, how to switch it, and the Bitrix24 account policy are described in full in [Access mode](/docs/keys-auth/access-mode).

```json
{
  "success": false,
  "error": {
    "code": "WRITE_BLOCKED_READONLY_KEY",
    "message": "Key is in read-only mode. Switch to read+write in /keys to enable writes.",
    "details": {
      "method": "crm.item.add",
      "keyName": "MCP key",
      "currentMode": "READONLY",
      "switchUrl": "/keys"
    }
  }
}
```

**`details` fields:**

| Field | When returned | Description |
|------|-------------------|----------|
| `method` | Only when proxying to Bitrix24 | The Bitrix24 method name that would have been called on a successful write (e.g. `crm.item.add`). Not returned for management keys — the block is based on the request's HTTP method |
| `keyName` | Always | The key name from your account. If the key has no name, `"unnamed"` is returned |
| `currentMode` | Always | The key's effective mode — always `"READONLY"` for this error |
| `switchUrl` | Always | The path to the page in your account where the mode is switched — `"/keys"` |

**Causes:**

- **An API key or authorization key (`vibe_api_`, `vibe_app_`)** in `READONLY` mode made a call that proxies to Bitrix24 as a write operation: create, update, delete, an action on an entity.
- **A management key (`vibe_live_`)** in `READONLY` mode made a request with the `POST`, `PATCH`, `PUT`, or `DELETE` HTTP method — e.g. an attempt to create a key via `POST /v1/keys` or delete a feedback record.

**Fix:**

- The key owner should open [API Keys](/keys), select "Read and write" in the **Access mode** block of the relevant key's card, and save. The mode takes effect on the next request — no reissue needed.
- If the toggle in the card is unavailable, the Bitrix24 account administrator has restricted the mode. Ask the administrator to lift the restriction for this key.
- When working through an AI agent, the effective mode is returned by `GET /v1/me` in the `data.accessMode` field. If writes are needed permanently, issue a separate key in "read and write" mode.

## See also

- [Error codes](/docs/errors)
- [Billing and plans](/docs/errors/billing)
- [Keys and authorization](/docs/keys-auth)
- [Access mode](/docs/keys-auth/access-mode)
- [Management keys](/docs/management-keys)
- [Scopes](/docs/scopes)
- [Retries and error handling in code](/docs/errors/handling)
