Для AI-агентов: markdown этой страницы — /docs-content/cowork/relay-ticket.md индекс документации — /llms.txt

Билет для телефонного доступа

POST /v1/cowork/relay-ticket

Выдаёт десктопу Cowork/Code подписанный билет для подключения к ретранслятору — серверу, через который телефон получает доступ к десктопу. Платформа только подтверждает, кто подключается: трафик через неё не идёт, а десктоп не регистрируется как сервер.

Билет действует 5 минут и привязан к публичному ключу десктопа из тела запроса: с другим ключом ретранслятор его не примет. Держите билет в памяти и используйте его для переподключений, пока до expiresAt остаётся больше 60 секунд. Когда до expiresAt остаётся 60 секунд или меньше, при следующем подключении запросите новый билет.

Скоуп: vibe:cowork плюс класс ключа десктопа Cowork/Code. У владельца ключа должно быть активное место Cowork/Code.

Поля запроса (body)

Поле Тип Обяз. Описание
pubkey string да Публичный ключ Ed25519, которым десктоп представляется ретранслятору: ровно 32 байта в base64url без знаков = в конце — 43 символа

Примеры

Эндпоинт принимает только ключ десктопа Cowork/Code, поэтому примеров два.

curl — ключ десктопа Cowork/Code

Terminal
curl -X POST https://vibecode.bitrix24.tech/v1/cowork/relay-ticket \
  -H "X-Api-Key: YOUR_COWORK_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pubkey": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"}'

JavaScript — ключ десктопа Cowork/Code

javascript
let cached = null

async function getRelayTicket(pubkey) {
  // Переиспользуем билет, пока до истечения больше 60 секунд
  if (cached && Date.parse(cached.expiresAt) - Date.now() > 60_000) {
    return cached.ticket
  }

  const res = await fetch('https://vibecode.bitrix24.tech/v1/cowork/relay-ticket', {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_COWORK_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ pubkey }),
  })
  if (!res.ok) {
    const { error } = await res.json()
    throw new Error(`${res.status} ${error.code}`)
  }

  cached = await res.json() // { ticket, expiresAt } — без обёртки success/data
  return cached.ticket
}

Поля ответа

Поле Тип Описание
ticket string Токен JWS (JSON Web Signature) в компактной записи с подписью EdDSA. Передавайте его ретранслятору как есть
expiresAt string Момент истечения билета (ISO 8601), через 5 минут после выдачи

Для справки: заголовок билета несёт alg: "EdDSA", typ: "JWT" и kid ключа подписи. В полезной нагрузке лежат typ: "cowork-relay-ticket", iss: "vibecode-platform", aud: "cowork-relay", sub и portal, cnf.jwk, в поле x которого лежит переданный pubkey, а также jti, iat и exp. Поля sub и portal — псевдонимы: ретранслятор различает по ним пользователей и аккаунты, но настоящих идентификаторов не узнаёт.

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

Значение ticket сокращено:

JSON
{
  "ticket": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsImtpZCI6Ii4uLiJ9.eyJ0eXAiOiJjb3dvcmstcmVsYXktdGlja2V0Ii4uLn0.c2lnbmF0dXJl",
  "expiresAt": "2026-09-22T12:05:00.000Z"
}

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

403 — ключ со скоупом vibe:cowork, но не от десктопа Cowork/Code:

JSON
{
  "success": false,
  "error": {
    "code": "COWORK_DESKTOP_KEY_REQUIRED",
    "message": "Only a Cowork/Code desktop key may request a relay ticket."
  }
}

Ошибки

HTTP Код Описание
400 INVALID_PUBKEY Поле pubkey не передано или не является 32-байтовым ключом в base64url без знаков = в конце
400 FST_ERR_CTP_EMPTY_JSON_BODY Передан заголовок Content-Type: application/json, а тело пустое
400 FST_ERR_CTP_INVALID_JSON_BODY Тело не разбирается как JSON
401 MISSING_API_KEY Не передан заголовок X-Api-Key
401 INVALID_API_KEY Ключ не опознан: такой строки на платформе нет
401 KEY_INACTIVE Ключ отозван — например, устройство отключили через DELETE /v1/cowork/key
401 KEY_EXPIRED Срок действия ключа истёк
402 ACCOUNT_FROZEN Счёт заморожен из-за отрицательного баланса. Этот вызов с баланса не оплачивается, поэтому отказ приходит, только пока на аккаунте действуют прежние правила заморозки. Новые правила закрывают лишь платные вызовы, платформа включает их постепенно
403 INSUFFICIENT_SCOPE У ключа нет скоупа vibe:cowork
403 COWORK_DESKTOP_KEY_REQUIRED Ключ не относится к классу десктопа Cowork/Code — такой отказ получает и ключ агентского места, и ключ стороннего агента
403 COWORK_SEAT_INACTIVE Место Cowork/Code есть, но его состояние не ACTIVE, а PAUSED, PARKED или CANCELLED
403 WRITE_BLOCKED_READONLY_KEY Ключ выпущен в режиме «только чтение»
404 COWORK_NOT_ACTIVATED У владельца ключа нет места Cowork/Code на этом аккаунте
413 PAYLOAD_TOO_LARGE Тело больше 4 КБ
415 FST_ERR_CTP_INVALID_MEDIA_TYPE Тело прислано с типом содержимого, который этот маршрут не разбирает. Отправляйте тело с заголовком Content-Type: application/json
429 RATE_LIMITED Превышен лимит запросов одного пользователя в аккаунте — несколько ключей одного пользователя делят общий лимит. Суммарный лимит платформы — 30 запросов в час. Действующее для вашего ключа значение приходит в заголовке x-ratelimit-limit — оно ниже суммарного, поскольку лимит делится между репликами
503 COWORK_FEATURE_DISABLED Cowork/Code отключён на уровне платформы
503 COWORK_RELAY_NOT_CONFIGURED Выдача билетов сейчас недоступна на этой платформе

Полный список общих ошибок API — Ошибки.

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

Успешный ответ (200) — это сам объект, без обёртки success. Ошибки приходят в конверте { success: false, error: { code, message } }. Определяйте успех по HTTP-статусу (res.ok).

Билет не сохраняется на платформе. Каждый вызов выдаёт новый билет, а прежние действуют до своего expiresAt. Отозвать выданный билет нельзя.

Эндпоинт сначала проверяет, доступна ли выдача билетов, и только потом — тело запроса. Пока выдача билетов недоступна, эндпоинт отвечает 503 COWORK_RELAY_NOT_CONFIGURED даже на запрос с неверным pubkey.

Как реагировать на отказы.

  • 401 — попросите пользователя войти заново.
  • 400, 403 INSUFFICIENT_SCOPE и 403 COWORK_DESKTOP_KEY_REQUIRED — повтор вернёт тот же отказ, исправьте запрос или ключ.
  • 404 COWORK_NOT_ACTIVATED и 403 COWORK_SEAT_INACTIVE — пользователю нужно активное место Cowork/Code.
  • 503 — состояние платформы, а не проблема ключа: повторите позже.
  • 429 — повторяйте с растущей паузой.

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