
## Состояние подписки Cowork/Code

`GET /v1/cowork/state`

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

## Примеры

### curl — личный ключ

```bash
curl https://vibecode.bitrix24.tech/v1/cowork/state \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth-приложение

```bash
curl https://vibecode.bitrix24.tech/v1/cowork/state \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"
```

### JavaScript — личный ключ

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/cowork/state', {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})

if (!res.ok) {
  const { error } = await res.json()
  console.error(error.code, error.message)
} else {
  const state = await res.json()
  const tight = state.windows[state.bottleneck]
  console.log(`Окно ${state.bottleneck}: ${tight.pctUsed}%`, tight.exhausted ? 'исчерпано' : 'ок')
}
```

### JavaScript — OAuth-приложение

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/cowork/state', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

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

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

| Поле | Тип | Описание |
|------|-----|----------|
| `subscription.tier` | string | Текущий тариф: `FREE`, `PRO`, `MAX`, `ULTRA` |
| `subscription.state` | string | Состояние подписки: `ACTIVE`, `PAUSED`, `CANCELLED` |
| `subscription.currentPeriodStart` | string | Начало расчётного периода (ISO 8601) |
| `subscription.currentPeriodEnd` | string | Конец расчётного периода (ISO 8601) |
| `subscription.nextChargeAt` | string или null | Дата следующего списания, `null` для тарифа `FREE` |
| `subscription.cancelAtPeriodEnd` | boolean | `true`, если на конец периода запланирована отмена |
| `subscription.pendingTier` | string или null | Тариф ниже текущего, на который сиденье перейдёт в конце оплаченного периода: `FREE`, `PRO` или `MAX`. Дата перехода — `subscription.currentPeriodEnd`. Переход на тариф выше применяется сразу и в этом поле не появляется. `null`, когда понижение не запланировано, а также у бесплатного сиденья, у подписки в состоянии `PAUSED` или `CANCELLED` и у подписки с `cancelAtPeriodEnd: true` |
| `windows.fiveHour` | object | Скользящее 5-часовое окно |
| `windows.fiveHour.pctUsed` | number | Использование в процентах, целое 0–100 |
| `windows.fiveHour.resetAt` | string | Время сброса окна (ISO 8601) |
| `windows.fiveHour.exhausted` | boolean | `true`, если квота окна исчерпана |
| `windows.week` | object | Скользящее недельное окно, поля аналогичны `fiveHour` |
| `windows.month` | object | Месячное окно, совпадает с расчётным периодом, поля аналогичны `fiveHour` |
| `bottleneck` | string | Наиболее нагруженное окно: `fiveHour`, `week` или `month` |
| `recommendation.reason` | string | Причина рекомендации: `none`, `approaching` (≥75 % и есть тариф выше), `window_exhausted` (5-часовое или недельное окно исчерпано, месячное ещё нет), `fully_exhausted` (исчерпано месячное окно) |
| `recommendation.triggerWindow` | string или null | Окно, вызвавшее рекомендацию, `null` при `reason: none` |
| `recommendation.wait` | object или null | Когда снимется блокировка: `{ window, resetAt }`, `null` если ни одно окно не исчерпано |
| `recommendation.upgrade.available` | boolean | Доступен ли переход на тариф выше |
| `recommendation.upgrade.nextTier` | string или null | Рекомендуемый следующий тариф, `null` на тарифе `ULTRA` |
| `tiers` | array | Все четыре тарифа для сравнительной таблицы |
| `tiers[].tier` | string | Название тарифа: `FREE`, `PRO`, `MAX`, `ULTRA` |
| `tiers[].multiplier` | string или null | Множитель тарифа: `×1`, `×5`, `×20`, `null` для `FREE` |
| `tiers[].feeVibes` | number | Стоимость тарифа в Вайбах за месяц |
| `tiers[].current` | boolean | `true`, если тариф активен у владельца ключа |
| `tiers[].isNext` | boolean | `true`, если тариф совпадает с `recommendation.upgrade.nextTier` |
| `serverTime` | string | Серверное время в момент ответа (ISO 8601) |
| `offPeak` | object | Выгодные часы: действует ли скидка сейчас, когда начнётся ближайшая и сетка множителей по часам недели. Состав блока — [Выгодные часы в подписке Cowork/Code](/docs/cowork/off-peak) |
| `touSavedPct` | number или null | Какую долю расхода за текущий расчётный период сняли выгодные часы, в процентах |

Ключи `offPeak` и `touSavedPct` приходят, только когда выгодные часы включены для аккаунта. Пока возможность не включена, их нет в теле ответа вовсе, и в примере ниже они не показаны.

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

```json
{
  "subscription": {
    "tier": "FREE",
    "state": "ACTIVE",
    "currentPeriodStart": "2026-06-01T00:00:00.000Z",
    "currentPeriodEnd": "2026-07-01T00:00:00.000Z",
    "nextChargeAt": null,
    "cancelAtPeriodEnd": false,
    "pendingTier": null
  },
  "windows": {
    "fiveHour": { "pctUsed": 40, "resetAt": "2026-06-09T17:30:00.000Z", "exhausted": false },
    "week":     { "pctUsed": 24, "resetAt": "2026-06-12T09:00:00.000Z", "exhausted": false },
    "month":    { "pctUsed": 20, "resetAt": "2026-07-01T00:00:00.000Z", "exhausted": false }
  },
  "bottleneck": "fiveHour",
  "recommendation": {
    "reason": "none",
    "triggerWindow": null,
    "wait": null,
    "upgrade": { "available": true, "nextTier": "PRO" }
  },
  "tiers": [
    { "tier": "FREE",  "multiplier": null,  "feeVibes": 0,     "current": true,  "isNext": false },
    { "tier": "PRO",   "multiplier": "×1",  "feeVibes": 2000,  "current": false, "isNext": true  },
    { "tier": "MAX",   "multiplier": "×5",  "feeVibes": 10000, "current": false, "isNext": false },
    { "tier": "ULTRA", "multiplier": "×20", "feeVibes": 20000, "current": false, "isNext": false }
  ],
  "serverTime": "2026-06-09T14:05:00.000Z"
}
```

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

404 — подписка не активирована:

```json
{
  "success": false,
  "error": {
    "code": "COWORK_NOT_ACTIVATED",
    "message": "No active Cowork/Code subscription for this user+portal"
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|----------|
| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |
| 401 | `INVALID_API_KEY` | Неверный API-ключ |
| 403 | `INSUFFICIENT_SCOPE` | У ключа нет скоупа `vibe:cowork` |
| 404 | `COWORK_NOT_ACTIVATED` | Подписка Cowork/Code не найдена для пары пользователь и портал |
| 500 | `INVALID_TIER_CONFIGURATION` | Конфигурация тарифов на платформе некорректна |
| 503 | `COWORK_FEATURE_DISABLED` | Cowork/Code отключён на уровне платформы |

Полный список общих ошибок API — [Ошибки](/docs/errors).

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

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

**Признак исчерпания окна — поле `exhausted`, а не `pctUsed === 100`.** Значение `pctUsed` округляется до целого: 99,6 % отображается как `100`, хотя окно ещё не исчерпано.

**Время до сброса отсчитывайте от `serverTime`, а не от часов устройства** — расхождение часов клиента и сервера исказит счётчик.

**Окна сбрасываются лениво при чтении** — если запросов не было с момента сброса, он применяется при обращении к эндпоинту, поэтому снимок всегда актуален.

**Опрашивайте не чаще одного раза в 15–30 секунд.** Ответ не кэшируется (`Cache-Control: no-store`).

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

- [Сводка по подписке Cowork/Code](/docs/cowork/me)
- [Выгодные часы в подписке Cowork/Code](/docs/cowork/off-peak)
- [Cowork/Code](/docs/cowork)
- [Лимиты и оптимизация](/docs/optimization)
- [Ошибки](/docs/errors)
