Для AI-агентов: markdown этой страницы — /docs-content/cowork/coupon-redeem.md индекс документации — /llms.txt
Погасить купон
POST /v1/cowork/coupon/redeem
Погашает купон Cowork/Code и выдаёт пользователю подаренный тариф на подаренный срок за счёт платформы, без списания с аккаунта Битрикс24.
Пользователь и аккаунт берутся из привязки ключа, параметров пути нет. Операция необратима: погашенный купон обратно не возвращается.
Поля запроса (body)
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
code |
string | да | Купон в виде ПРЕФИКС-ТЕЛО-СУММА, от 1 до 64 символов. Регистр, пробелы и начертание дефисов приводятся к канонической форме на нашей стороне |
action |
string | нет | Что выбрал пользователь в развилке: apply, extend, force или resume-and-apply. Значение берётся из decision проверки купона: при kind apply или extend — само это значение, при kind: choose — kind выбранного элемента options. Поле опущено — считается apply, то есть поведение до появления развилки |
Примеры
Ось авторизации одна: эндпоинт принимает только ключ десктопа Cowork/Code. Личный ключ и ключ приложения получают 403 INSUFFICIENT_SCOPE либо 403 COWORK_DESKTOP_KEY_REQUIRED.
curl — ключ десктопа Cowork/Code
curl -X POST https://vibecode.bitrix24.tech/v1/cowork/coupon/redeem \
-H "X-Api-Key: YOUR_COWORK_KEY" \
-H "Content-Type: application/json" \
-d '{"code": "PRAKTIKUM-7HKM4TQZ2RVW-45C80C", "action": "force"}'
JavaScript — ключ десктопа Cowork/Code
const res = await fetch('https://vibecode.bitrix24.tech/v1/cowork/coupon/redeem', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_COWORK_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
code: 'PRAKTIKUM-7HKM4TQZ2RVW-45C80C',
action: 'force',
}),
})
if (!res.ok) {
const { error } = await res.json()
if (error.code === 'CONCURRENT_REDEMPTION') {
// Единственный код, который повторяют автоматически.
}
console.error(error.code)
} else {
const { data } = await res.json()
if (data.accessGranted) {
console.log(`${data.grantedTier} на ${data.grantedTermMonths} мес.`)
} else {
// Тариф выдан, доступа ещё нет — заявка ушла администратору аккаунта.
console.log(`${data.grantedTier} активирован, ждём решения администратора`)
}
}
Поля ответа
| Поле | Тип | Описание |
|---|---|---|
success |
boolean | true при успешном погашении |
data.grantedTier |
string | Выданный тариф: PRO, MAX или ULTRA |
data.grantedTermMonths |
number | Срок, на который выдан тариф, в месяцах |
data.accessGranted |
boolean | false означает, что тариф выдан, а доступ к Cowork/Code администратор аккаунта ещё не открыл |
Пример ответа
{
"success": true,
"data": {
"grantedTier": "PRO",
"grantedTermMonths": 3,
"accessGranted": true
}
}
Тариф выдан, но доступ к Cowork/Code на аккаунте ещё не открыт:
{
"success": true,
"data": {
"grantedTier": "PRO",
"grantedTermMonths": 3,
"accessGranted": false
}
}
Пример ответа при ошибке
409 — на месте пользователя уже стоит этот тариф:
{
"success": false,
"error": {
"code": "COUPON_SEAT_ALREADY_ON_TIER",
"message": "The coupon cannot be redeemed"
}
}
Ошибки
Отказ по самому купону приходит статусом 409, а error.code называет причину. Текст в message у всех таких отказов один, разбирать его не нужно — решение принимается по коду.
| HTTP | Код | Описание |
|---|---|---|
| 400 | INVALID_CODE |
В теле нет строкового поля code, оно пустое, длиннее 64 символов либо рядом лежит поле, которого тело не принимает |
| 400 | INVALID_ACTION |
Поле action есть, но его значение не входит в набор apply, extend, force, resume-and-apply |
| 400 | INVALID_JSON_BODY |
Тело передано, но не читается как JSON |
| 401 | MISSING_API_KEY |
Не передан заголовок X-Api-Key |
| 401 | INVALID_API_KEY |
Ключ не опознан: такой строки на платформе нет |
| 403 | INSUFFICIENT_SCOPE |
У ключа нет скоупа vibe:cowork |
| 403 | COWORK_DESKTOP_KEY_REQUIRED |
Ключ другого класса: личный ключ, ключ приложения, ключ места агента или проектный ключ деплоя |
| 403 | COUPON_FEATURE_DISABLED |
Купоны на аккаунте не включены |
| 403 | KEY_NOT_BOUND_TO_USER |
Ключ не привязан к пользователю аккаунта |
| 403 | WRITE_BLOCKED_READONLY_KEY |
Ключ выпущен только для чтения |
| 409 | COUPON_INVALID |
Купона не существует, он отозван, уже погашен, истёк, кампания закончилась, выбран её штучный потолок либо выбран лимит на пользователя или на аккаунт. Показывать одну формулировку — «Код не подходит» |
| 409 | COUPON_TOO_MANY_ATTEMPTS |
Десять неудач за час. Попытки закрыты на тридцать минут |
| 409 | COUPON_ALREADY_REDEEMED_BY_YOU |
Этот пользователь уже активировал этот купон |
| 409 | COUPON_NOT_ASSIGNED_TO_YOU |
Купон выписан на другой адрес электронной почты |
| 409 | COUPON_PORTAL_ACCESS_GATED |
Доступ к Cowork/Code на аккаунте закрыт |
| 409 | COUPON_TARIFF_NOT_ELIGIBLE |
Кампания ограничена списком тарифов Битрикс24, и тариф аккаунта в него не входит. Отказ терминальный: повторный вызов вернёт то же самое |
| 409 | COUPON_TARIFF_UNKNOWN |
Кампания ограничена списком тарифов Битрикс24, а тариф аккаунта платформа ещё не прочитала. Купон цел, попытка не засчитывается в лимит — повторите вызов позже |
| 409 | COUPON_SEAT_PAUSED |
Место приостановлено из-за нехватки средств. Подарок причину паузы не снимает — сначала пополнить баланс |
| 409 | COUPON_SEAT_CANCELLATION_SCHEDULED |
На месте назначена отмена, а погашение пришло без action: resume-and-apply. Когда тариф подарка не ниже действующего, это действие приходит в options проверки — отправьте его, чтобы снять отмену и применить подарок. Тариф подарка ниже действующего — действия не будет вовсе, отказ терминальный |
| 409 | COUPON_TIER_DOWNGRADE_BLOCKED |
Купон даёт тариф ниже действующего, и пользователь не выбрал force |
| 409 | COUPON_SEAT_ALREADY_ON_TIER |
Этот тариф на месте уже стоит, а погашение пришло без action: extend. Продление кампанией не разрешено либо срок покупки больше месяца — тогда проверка возвращает решение refuse, а не extend |
| 409 | COUPON_SEAT_PAID_TERM_ACTIVE |
У места идёт оплаченный отрезок без автосписания. Подарок перезаписал бы его, поэтому отказ терминальный — направляйте пользователя в поддержку |
| 409 | COUPON_SEAT_ALREADY_PAID_LONGER |
Место оплачено дальше, чем даёт купон, и пользователь не выбрал force |
| 409 | COUPON_SELF_PORTAL |
За порталом стоит сотрудник платформы с правом выдавать купоны — погашение на таком портале закрыто |
| 409 | COUPON_SEAT_IS_PAID |
На месте живое списание, и пользователь не выбрал force |
| 409 | COUPON_ACTION_NOT_AVAILABLE |
Присланное действие устарело: состояние места изменилось между проверкой и погашением. Купон цел и не потрачен |
| 409 | CONCURRENT_REDEMPTION |
За то же место конкурирует другая операция |
| 429 | RATE_LIMITED |
Суммарный лимит платформы — 10 запросов в минуту. Действующее для вашего ключа значение приходит в заголовке x-ratelimit-limit — оно ниже суммарного, поскольку лимит делится между репликами |
Полный список общих ошибок API — Ошибки.
Известные особенности
Общий экран успеха на accessGranted: false — самый дорогой класс обращений в поддержку. Операция для пользователя выглядит удачной, а запустить Cowork/Code он не может, и это читается как поломка. Нужен отдельный экран — «Тариф активирован, заявка на доступ отправлена администратору», — а не общий «Готово».
Присланное действие — намерение, а не разрешение. Между проверкой и погашением место могло измениться: пользователь оплатил тариф в другой вкладке, администратор понизил место, сработала отмена. Решение пересчитывается по свежему состоянию, и если выбранного действия там уже нет, приходит COUPON_ACTION_NOT_AVAILABLE — перечитайте проверку и покажите те действия, что вернулись сейчас.
CONCURRENT_REDEMPTION повторяют, остальные отказы купона — никогда. Купон исправен, правила пройдены, подарок не израсходован: к моменту ответа купон уже вернулся в оборот. Делайте до трёх повторов с задержкой 300–800 мс и случайным разбросом — без разброса десятки клиентов повторят синхронно и воспроизведут ту же конкуренцию. Пользователю на это время показывают ожидание, а не ошибку. Автоматический повтор любого другого отказа купона выжигает счётчик неудач за секунды. Отдельно от них стоит 429 RATE_LIMITED — это не отказ купона, счётчик неудач он не трогает, и повтор после паузы уместен.
Действие force сжигает остаток оплаченного срока без возврата. Сколько именно суток сгорит, приходит в losesDays проверки купона и на клиенте не пересчитывается. Подпись кнопки обязана называть это число до нажатия — после погашения вернуть срок нечем.
Купон одноразов на пользователя, но не обязательно на всех. Часть купонов рассчитана на несколько активаций разными людьми. Сколько людей держит один и тот же купон, наружу не сообщается, и в тексте для пользователя это не упоминают.
Счётчик неудачных попыток общий с проверкой купона — пара, на которую он заведён, и условие обнуления описаны в проверке купона.
Суммарный лимит платформы у погашения — 10 запросов в минуту, у проверки — 20 запросов в минуту. Действующие для вашего ключа значения приходят в заголовке x-ratelimit-limit. Они ниже суммарных, поскольку лимиты делятся между репликами.
Выписывать купоны с этого ключа нельзя, и это решение, а не незавершённая работа. Ключ десктопа лежит на машине пользователя, поэтому право выпуска на нём означало бы, что потолок кампании ничего не ограничивает. Программный выпуск живёт под другим классом ключа и вызывается сервером партнёра, а не приложением.