## Коннекторы для Коворка и приложений Вайбкод

`GET /v1/connectors`

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

Заявки на доступ доступны только Коворку.

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

Ключ устройства Коворка с назначением `cowork-desktop` сохраняет доступ от лица сотрудника. Персональный ключ приложения Вайбкод или OAuth-ключ приложения допускается только с явно выданным действующим `vibe:connectors`, действующим приложением и совпадающими владельцем и порталом ключа. Пока функция не включена для портала, маршруты отвечают `404 ROUTE_NOT_FOUND`. При включённой функции остальные ключи получают `403 CONNECTOR_KEY_NOT_ALLOWED`.

Приложение действует от лица владельца ключа, а не сотрудника, открывшего страницу, или пользователя из заголовков. Оно видит только общие подключения `PORTAL`, разрешённые администратором и правами владельца. Скоуп не создаёт подключение или правило администратора и не выдаёт доступ по сотруднику-зрителю.

Точный белый список приложения: `GET /v1/connectors`, `POST /v1/connectors/mcp`, `GET /v1/connectors/write-tickets/{id}` и `GET /v1/me`. Все остальные ручки и операции хоста, включая заявки на доступ и управление подключениями, закрыты с `CONNECTOR_KEY_NOT_ALLOWED`. Ограниченный сотрудник Коворка по-прежнему получает каталог с состояниями `ACCESS_RESTRICTED`; ограниченный владелец приложения получает `403 PORTAL_ACCESS_BLOCKED`.

Хост хранит ключ и не передаёт его агенту. Запись владелец подтверждает в веб-кабинете. Билеты приложения и счётчик ожидания ограничены текущим порталом и тем же приложением и тем же ключом; даже другой ключ того же владельца не прочитает билет. Коворк сохраняет прежнюю семантику сотрудника.

## Параметры

| Параметр | Тип | Обяз. | Описание |
| --- | --- | --- | --- |
| `slug` (path) | string | да | Системное имя из `data.items[].slug` списка `GET /v1/connectors` |
| `note` (body) | string | нет | Причина заявки, до 500 символов. Пробелы по краям удаляются. Тело можно опустить или передать `{}`. Неизвестные поля отклоняются |
| `id` (path) | string | да | `ticketId` из `_meta["vibe/confirmation"]` результата шлюза |

## Примеры

### curl — список коннекторов

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

### curl — заявка на доступ

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

### curl — исход подтверждения

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

`bridge-test` — условное имя в примере. Подставьте `slug` из списка.

### JavaScript — исход подтверждения

```javascript
const response = await fetch(
  'https://vibecode.bitrix24.tech/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)
```

## Поля ответа

Успех обёрнут в `{ success: true, data }`. Для списка `data` содержит следующие поля.

| Поле | Тип | Описание |
| --- | --- | --- |
| `data.items` | array | До 100 записей, отсортированных по системному имени |
| `data.items[].slug` | string | Системное имя коннектора |
| `data.items[].title` | string | Название для сотрудника |
| `data.items[].summary` | string | Краткое описание |
| `data.items[].iconUrl` | string / null | URL иконки или `null` |
| `data.items[].category` | string | Категория сервиса |
| `data.items[].connectionScope` | string | `PORTAL` — компания, `USER` — сотрудник; приложение получает только `PORTAL` |
| `data.items[].state` | string | Состояние из таблицы ниже |
| `data.items[].mode` | string / null | `READ`, `READ_WRITE` или `null` |
| `data.items[].retryAfter` | string / null | Время ISO 8601 для повторной заявки после отказа при `NOT_ENABLED`, иначе `null` |
| `data.items[].webUrl` | string | Карточка сервиса в веб-кабинете |
| `data.items[].pricing` | object / null | Диапазон цен инструментов в Вайбах за один успешный вызов: `minVibes` и `maxVibes` — строки с десятичной суммой. `null` — коннектор бесплатный |
| `data.pendingConfirmations.count` | integer | Число живых ожидающих подтверждений по доступным порталам сотрудника |
| `data.pendingConfirmations.url` | string | Страница всех ожидающих подтверждений |

Заявка отвечает `201` с `data.id` и `data.status = "PENDING"`. Исход подтверждения содержит следующие поля.

| Поле | Тип | Описание |
| --- | --- | --- |
| `data.status` | string | Один из пяти статусов ниже |
| `data.summary` | string | Описание действия. У `REJECTED`, `CONSUMED`, `EXPIRED` только заголовок без аргументов |
| `data.expiresAt` | string | Срок действия в ISO 8601 |
| `data.webUrl` | string | URL подтверждения в системном браузере |
| `data.continueText` | string / null | `null` у `PENDING`, у остальных — готовый текст словаря для агента |

## Состояния

| `state` | Что показать сотруднику |
| --- | --- |
| `ACCESS_RESTRICTED` | Доступ к порталу ограничен администратором |
| `UNAVAILABLE` | Коннектор временно выключен |
| `REQUEST_PENDING` | Заявка ждёт решения |
| `NOT_ENABLED` | Можно попросить доступ |
| `WAITING_ADMIN` | Ждёт подключения компании администратором |
| `NEEDS_REAUTH` | Нужно переподключить сервис по `webUrl` |
| `NOT_CONNECTED` | Нужно подключить сервис по `webUrl` |
| `ACTIVE` | Инструменты доступны |

## Статусы подтверждения

| `status` | Действие хоста |
| --- | --- |
| `PENDING` | Ждёт решения, продолжать опрос |
| `APPROVED` | Одобрено, передать `continueText` и повторить исходный вызов |
| `REJECTED` | Отказано, передать `continueText` и остановить опрос |
| `CONSUMED` | Одобрение использовано, передать `continueText` и остановить опрос. Это не доказательство успешной записи |
| `EXPIRED` | Истекло, передать `continueText` и остановить опрос |

## Отказы платного вызова

Инструмент с ценой больше нуля списывает её с баланса Вайбов портала за каждый успешный вызов. Сбой внешнего сервиса, таймаут и любой отказ шлюза не списываются. Перед обращением к внешнему сервису шлюз проверяет баланс, суточный потолок правила портала и бюджет компании. При отказе вызов не выполняется, а `tools/call` отвечает ошибкой инструмента: `isError: true` и код в `_meta["vibe/error"].code`.

| `code` | `retryable` | Поле `_meta["vibe/error"]` | Действие хоста |
| --- | --- | --- | --- |
| `INSUFFICIENT_BALANCE` | `false` | `topUpUrl` | Объяснение и кнопка «Пополнить», которая открывает `topUpUrl` в системном браузере |
| `ACCOUNT_FROZEN` | `false` | `topUpUrl` | Объяснение и кнопка «Пополнить», как у `INSUFFICIENT_BALANCE`. Счёт портала заморожен |
| `DAILY_CAP_REACHED` | `true` | `retryAfter` | Объяснение и время `retryAfter`, когда вызов снова станет возможен. Это начало следующих суток UTC в ISO 8601 |
| `COMPANY_BUDGET_EXHAUSTED` | `false` | нет | Объяснение без кнопки пополнения. Деньги на счёте есть, бюджет компании увеличивает администратор портала |

Для пишущего инструмента проверка идёт до подтверждения записи. Без денег подтверждение не создаётся, а одобренное подтверждение при отказе не расходуется и действует до своего срока. После пополнения повторный вызов исполняется без нового одобрения.

## Пример ответа

Пример структуры исхода ожидающего подтверждения.

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

## Пример ответа при ошибке

`429 CONNECTOR_ACCESS_REQUEST_COOLDOWN` — заявка отклонена менее суток назад.

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

`error.retryAfter` — отдельное время ISO 8601. `error.details`, если присутствует при ошибке ввода, содержит список путей и сообщений проверки.

## Ошибки

| HTTP | Код | Когда |
| --- | --- | --- |
| 400 | `INVALID_BODY` | Некорректное тело заявки |
| 403 | `CONNECTOR_KEY_NOT_ALLOWED` | Ключ не десктопа Коворк |
| 403 | `OWNER_BLOCKED` | Владелец ключа заблокирован или больше не активен на портале |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | POST-заявка ключом в режиме только чтения |
| 403 | `PORTAL_ACCESS_BLOCKED` | Заявка сотрудника с ограниченным доступом |
| 403 | `CONNECTOR_BLOCKED` | Коннектор запрещён администратором |
| 403 | `CONNECTOR_DISABLED` | Коннектор выключен |
| 404 | `ROUTE_NOT_FOUND` | Флаг коннекторов выключен |
| 404 | `CONNECTOR_NOT_FOUND` | Коннектор заявки не найден |
| 404 | `CONNECTOR_WRITE_TICKET_NOT_FOUND` | Тикет не этого сотрудника или портала, не найден либо его чтение запрещено |
| 409 | `CONNECTOR_ACCESS_REQUEST_EXISTS` | Ожидающая заявка уже существует |
| 409 | `CONNECTOR_ALREADY_ENABLED` | Сотруднику уже выдан доступ |
| 429 | `CONNECTOR_ACCESS_REQUEST_COOLDOWN` | Повторная заявка после отказа, срок в `error.retryAfter` |
| 429 | `RATE_LIMITED` | Превышен лимит запросов |
| 503 | `CONNECTOR_VAULT_NOT_CONFIGURED` | Хранилище не настроено, исход тикета недоступен |

Общие ошибки авторизации и заморозки — [Ошибки](/docs/errors).

## Известные особенности

- Список при ограниченном доступе отвечает `200`, все записи имеют `ACCESS_RESTRICTED`. Счётчик учитывает только доступные порталы с обоими флагами, активным членством и без самоудаления.

- Чтение тикета требует обоих флагов `connectors` и `connectors-write`, живого портала, активного членства, разрешённого доступа и отсутствия самоудаления по порталу ключа. Тикет принадлежит этому же порталу и владельцу ключа.

- Опрос — не чаще раза в 3 секунды. Платформенные потолки: список 120/мин на ключ, заявка 10/час на ключ, опрос 1200/мин суммарно на ключ и 60/мин на пару ключ–тикет. Потолки делятся на реплики, действующее значение маршрута приходит в `x-ratelimit-limit`.

- Передавайте `continueText` агенту дословно для любого статуса кроме `PENDING`. Шлюз использует одобрение до обращения к внешнему сервису. Результат повторного вызова, а не статус `CONSUMED`, показывает успех или ошибку записи.

- Запись дополнительно требует `connectors-write` и подходящей версии десктопа. В продуктовой среде `connectorsWriteMinDesktopVersion` остаётся `null` до решения оператора. Пустая настройка закрывает запись всем.

## Смотрите также

- [Шлюз коннекторов](/docs/connectors-mcp)
- [Ключи и авторизация](/docs/keys-auth)


## Долгие операции BRIDGE

Хост сохраняет UUID действия в `params._meta["vibe/idempotencyKey"]` и повторяет потерянный запуск с теми же UUID и аргументами. Для результата pending он вызывает `connectors_get_result({operationId})` через `POST /v1/connectors/mcp` с прежним ключом. Новый V1-адрес и новый ключ не нужны. Правила живого доступа и владения действуют и при повторе; переподключение или отзыв доступа скрывает старое содержимое, но не отменяет расчёт принятого успешного вызова.

Платный WRITE сначала требует одобрения владельца; после него повторяют тот же UUID. Повтор принятой операции не расходует второй билет и не создаёт второго списания. Таймаут не означает отмену. Pending остаётся в журнале с исходным временем вызова и без оплаченной суммы до завершения. Примеры, сроки и ограничения: [операции MCP BRIDGE](./connectors-mcp.md).
