## Connectors for the Cowork desktop

`GET /v1/connectors`

`POST /v1/connectors/{slug}/access-requests`

`GET /v1/connectors/write-tickets/{id}`

The Cowork desktop lists services for the employee, requests access and reads the outcome of a write confirmation.

Only a device key with purpose `cowork-desktop` is accepted. Other keys receive `403 CONNECTOR_KEY_NOT_ALLOWED`. The host stores the key and never passes it to the agent. The person makes confirmation decisions in the web account.

## Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `slug` (path) | string | yes | Name from `data.items[].slug` in `GET /v1/connectors` |
| `note` (body) | string | no | Reason for requesting access, up to 500 characters. Leading and trailing whitespace is trimmed. The body can be omitted or set to `{}`. Unknown fields are rejected |
| `id` (path) | string | yes | `ticketId` from `_meta["vibe/confirmation"]` in the gateway result |

## Examples

### curl — list connectors

```bash
curl https://vibecode.bitrix24.com/v1/connectors \
  -H "X-Api-Key: YOUR_COWORK_DEVICE_KEY"
```

### curl — request access

```bash
curl -X POST https://vibecode.bitrix24.com/v1/connectors/bridge-test/access-requests \
  -H "X-Api-Key: YOUR_COWORK_DEVICE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"note":"Project access"}'
```

### curl — confirmation outcome

```bash
curl https://vibecode.bitrix24.com/v1/connectors/write-tickets/5f0c1f7e-2b8a-4c1e-9d6f-3a7b9e2c4d10 \
  -H "X-Api-Key: YOUR_COWORK_DEVICE_KEY"
```

`bridge-test` is an example name. Use a `slug` from the list.

### JavaScript — confirmation outcome

```javascript
const response = await fetch(
  'https://vibecode.bitrix24.com/v1/connectors/write-tickets/5f0c1f7e-2b8a-4c1e-9d6f-3a7b9e2c4d10',
  { headers: { 'X-Api-Key': 'YOUR_COWORK_DEVICE_KEY' } },
)
const result = await response.json()
console.log(result)
```

## Response fields

Success is wrapped in `{ success: true, data }`. The list has the following fields in `data`.

| Field | Type | Description |
| --- | --- | --- |
| `data.items` | array | Up to 100 entries, sorted by name |
| `data.items[].slug` | string | Connector name |
| `data.items[].title` | string | Employee-facing title |
| `data.items[].summary` | string | Short description |
| `data.items[].iconUrl` | string / null | Icon URL or `null` |
| `data.items[].category` | string | Service category |
| `data.items[].connectionScope` | string | `PORTAL` — company, `USER` — employee |
| `data.items[].state` | string | State from the table below |
| `data.items[].mode` | string / null | `READ`, `READ_WRITE` or `null` |
| `data.items[].retryAfter` | string / null | ISO 8601 time for requesting access again after rejection in `NOT_ENABLED`, otherwise `null` |
| `data.items[].webUrl` | string | Service card in the web account |
| `data.pendingConfirmations.count` | integer | Number of live pending confirmations across the employee’s accessible Bitrix24 accounts |
| `data.pendingConfirmations.url` | string | Page with all pending confirmations |

An access request returns `201` with `data.id` and `data.status = "PENDING"`. The confirmation outcome has the following fields.

| Field | Type | Description |
| --- | --- | --- |
| `data.status` | string | One of the five statuses below |
| `data.summary` | string | Action summary. `REJECTED`, `CONSUMED` and `EXPIRED` contain only the heading, without arguments |
| `data.expiresAt` | string | Expiration time in ISO 8601 |
| `data.webUrl` | string | Confirmation URL to open in the system browser |
| `data.continueText` | string / null | `null` for `PENDING`, otherwise the dictionary text to pass to the agent |

## States

| `state` | What to show the employee |
| --- | --- |
| `ACCESS_RESTRICTED` | Access to the Bitrix24 account is restricted by the administrator |
| `UNAVAILABLE` | Connector is unavailable |
| `REQUEST_PENDING` | Access request awaits a decision |
| `NOT_ENABLED` | Access can be requested |
| `WAITING_ADMIN` | Waiting for the administrator to connect the company |
| `NEEDS_REAUTH` | Reconnect the service through `webUrl` |
| `NOT_CONNECTED` | Connect the service through `webUrl` |
| `ACTIVE` | Tools are available |

## Confirmation statuses

| `status` | Host action |
| --- | --- |
| `PENDING` | Awaiting a decision, keep polling |
| `APPROVED` | Approved, pass `continueText` and repeat the original call |
| `REJECTED` | Rejected, pass `continueText` and stop polling |
| `CONSUMED` | Approval used, pass `continueText` and stop polling. This is not proof of a successful write |
| `EXPIRED` | Expired, pass `continueText` and stop polling |

## Response example

Example shape of a pending confirmation outcome.

```json
{
  "success": true,
  "data": {
    "status": "PENDING",
    "summary": "bridge-test \u00b7 update_record",
    "expiresAt": "2026-10-01T12:10:00.000Z",
    "webUrl": "https://vibecode.bitrix24.com/connectors/confirm/5f0c1f7e-2b8a-4c1e-9d6f-3a7b9e2c4d10",
    "continueText": null
  }
}
```

## Error response example

`429 CONNECTOR_ACCESS_REQUEST_COOLDOWN` — the request was rejected less than a day ago.

```json
{
  "success": false,
  "error": {
    "code": "CONNECTOR_ACCESS_REQUEST_COOLDOWN",
    "message": "The request was rejected recently",
    "retryAfter": "2026-10-02T12:00:00.000Z"
  }
}
```

`error.retryAfter` is a separate ISO 8601 timestamp. When present for an input error, `error.details` contains a list of validation paths and messages.

## Errors

| HTTP | Code | When |
| --- | --- | --- |
| 400 | `INVALID_BODY` | Invalid access-request body |
| 403 | `CONNECTOR_KEY_NOT_ALLOWED` | Key is not a Cowork desktop key |
| 403 | `OWNER_BLOCKED` | Key owner is no longer active in the Bitrix24 account |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | POST access request with a read-only key |
| 403 | `PORTAL_ACCESS_BLOCKED` | Access request by an employee with restricted access |
| 403 | `CONNECTOR_BLOCKED` | Connector blocked by the administrator |
| 403 | `CONNECTOR_DISABLED` | Connector disabled |
| 404 | `ROUTE_NOT_FOUND` | Connectors flag is off |
| 404 | `CONNECTOR_NOT_FOUND` | Requested connector not found |
| 404 | `CONNECTOR_WRITE_TICKET_NOT_FOUND` | Ticket belongs to another employee or Bitrix24 account, is missing, or cannot be read |
| 409 | `CONNECTOR_ACCESS_REQUEST_EXISTS` | Pending access request already exists |
| 409 | `CONNECTOR_ALREADY_ENABLED` | Employee already has access |
| 429 | `CONNECTOR_ACCESS_REQUEST_COOLDOWN` | Request after rejection, retry time in `error.retryAfter` |
| 429 | `RATE_LIMITED` | Request limit exceeded |
| 503 | `CONNECTOR_VAULT_NOT_CONFIGURED` | Vault is not configured, ticket outcome is unavailable |

For common authorization and deletion-freeze errors, see [Errors](/docs/errors).

## Known specifics

- With restricted access, the list returns `200` and every entry has state `ACCESS_RESTRICTED`. The count includes only accessible Bitrix24 accounts with both flags, active membership and no pending self-deletion.

- Reading a ticket requires both `connectors` and `connectors-write`, a live Bitrix24 account, active membership, permitted access and no pending self-deletion in the key’s account. The ticket belongs to that account and the key owner.

- Poll at most once every 3 seconds. Platform-wide ceilings: list 120/min per key, request 10/hour per key, polling 1200/min total per key and 60/min per key-ticket pair. Ceilings are divided across replicas, and the active route limit is returned in `x-ratelimit-limit`.

- Pass `continueText` to the agent verbatim for every status except `PENDING`. The gateway uses the approval before calling the external service. The repeated call’s result, rather than status `CONSUMED`, reports whether the write succeeded or failed.

- Writing also requires `connectors-write` and an eligible desktop version. In production, `connectorsWriteMinDesktopVersion` remains `null` until the operator decides to enable it. An empty setting blocks writing for everyone.

## See also

- [Connector gateway](/docs/connectors-mcp)
- [Keys and authorization](/docs/keys-auth)
