Управление подписками из кода
Списаниями, повторами и статусами занимается платформа — это описано в обзоре. На вашей стороне остаётся три вещи: завести тарифы, решить, какие из них видит витрина, и наблюдать за подписками, когда они пошли.
Всё это делается тем же API, которым работает интерфейс платформы. Ниже <employee_token> — Bearer сотрудника, полученный при входе; это серверный секрет, во фронтенд он не попадает.
1. Завести тариф
Тариф — это обычная номенклатура с признаком подписки и длиной периода:
POST /api/nomenclatures HTTP/1.1
Host: api.gigma.ru
Authorization: Bearer <employee_token>
Content-Type: application/json
{
"name": "Доступ Pro, год",
"kind_id": 1,
"is_subscription": true,
"billing_period_months": 12,
"price": "9900.00"
} kind_id: 1 — вид «услуга», обычный выбор для доступа. billing_period_months задаёт, как часто платформа будет списывать: 1 — ежемесячно, 12 — раз в год, максимум 120. price — сумма одного периода. Контракт — создание номенклатуры.
Годовой и месячный варианты одного продукта заводят отдельными позициями и связывают через parent_nomenclature_id: метод subscription-catalog/grouped соберёт их в одну карточку, а подпись каждого варианта возьмёт из variant_label и порядок — из variant_sort_order. Назначать приложению нужно каждый вариант отдельно, иначе в карточке не будет выбора периода.
2. Назначить тариф приложению
POST /api/applications/12/subscription-nomenclatures HTTP/1.1
Host: api.gigma.ru
Authorization: Bearer <employee_token>
Content-Type: application/json
{
"nomenclature_id": 5120,
"sort_order": 10,
"is_active": true
} Назначить можно только позицию своего проекта с is_subscription: true — иначе 404. sort_order задаёт порядок в витрине, is_active: false прячет тариф, не удаляя назначение. Контракт — назначение тарифа.
Пока тариф не назначен, витрина его не покажет. Приложение, созданное через API, сразу помечено флагом subscription_catalog_configured, поэтому его каталог отдаёт только назначенные и активные позиции — до первого назначения он пуст. Обратное поведение осталось для совместимости: у приложений из проектов, где есть подписки без привязки к приложению, флаг опущен, и каталог отдаёт все подписочные позиции проекта, включая чужие. Проверить флаг можно в карточке приложения.
Чтобы тариф можно было купить
Создание тарифа ничего не проверяет — несостоятельный тариф всплывёт только на оформлении у клиента, ответом 422. Проверьте заранее:
priceбольше нуля;billing_period_monthsне меньше1;- тариф назначен приложению (шаг 2);
- у бизнеса есть склад с платёжной интеграцией — общий список требований в обзоре.
Ещё одно правило оформления: на один и тот же тариф у клиента не может быть двух активных подписок, повторная попытка вернёт 422.
3. Проверить витриной
GET /api/counterparty/subscription-catalog HTTP/1.1
Host: api.gigma.ru
Token: <application_token>
Accept: application/json Проверяйте тем запросом, который делает сайт, — контракт в каталоге тарифов. Сгруппированный вариант для карточек с выбором периода — subscription-catalog/grouped.
4. Наблюдать за подписками
Дальше подписки живут сами: платформа списывает, повторяет при отказе и меняет статусы. Из кода это видно двумя методами — списком и карточкой, а разбор конкретного случая даёт лента статусов.
Список подписок
- Метод
- GET
- URL
https://api.gigma.ru/api/tables/subscriptions- Авторизация
- Bearer token
- Headers
Authorization: Bearer {token}- Успешный ответ
200
Параметры запроса
page— номер страницыper_page— размер страницы, максимум100query— поиск, от 3 символовstatus[]— фильтр по статусам:active,charging,past_due,canceledapplication_id[]— фильтр по приложениямdate_from— подписки, созданные с этой датыdate_to— подписки, созданные по эту датуsort_by—created_at,current_period_end,last_payment_at,amountsort_dir—ascилиdesc
Ответ
{
"columns": [{ "id": 210, "table_id": 12, "order": 0, "key": "id", "text": "№" }],
"subscriptions": [
{
"id": 981,
"status": "active",
"amount": "9900.00",
"current_period_end": "2027-08-18T00:00:00+00:00"
}
],
"counters": { "active": 128, "charging": 4, "past_due": 2, "canceled": 37 },
"pagination": { "total": 171, "per_page": 25, "current_page": 1, "last_page": 7 }
} counters считает подписки по статусам с учётом текущих фильтров — по ним удобно строить сводку без второго запроса.
Карточка подписки
- Метод
- GET
- URL
https://api.gigma.ru/api/subscriptions/{id}- Авторизация
- Bearer token
- Headers
Authorization: Bearer {token}- Успешный ответ
200
Ответ
{
"subscription": {
"id": 981,
"status": "active",
"plan_slug": "nomenclature-5120",
"amount": "9900.00",
"currency": "RUB",
"billing_period_months": 12,
"current_period_start": "2026-08-18T00:00:00+00:00",
"current_period_end": "2027-08-18T00:00:00+00:00",
"last_payment_at": "2026-08-18T10:15:00+00:00",
"last_payment_error": null,
"next_charge_at": "2027-08-18T00:00:00+00:00",
"canceled_at": null,
"counterparty": { "id": 3312, "name": "Иванов Иван", "phone_1": "79990000000" },
"application": { "id": 12, "name": "Сайт" },
"nomenclature": { "id": 5120, "name": "Доступ Pro, год" }
}
} last_payment_error — причина последнего отказа банка, next_charge_at — когда платформа попробует списать в следующий раз.
Лента изменений статуса
- Метод
- GET
- URL
https://api.gigma.ru/api/subscriptions/{id}/status-events- Авторизация
- Bearer token
- Headers
Authorization: Bearer {token}- Успешный ответ
200
Параметры запроса
page_size— размер страницы, по умолчанию25, максимум100page_token— токен следующей страницы из предыдущего ответа
Ответ
{
"status_events": [
{
"name": "subscriptions/981/status-events/4471",
"id": 4471,
"event_type": "payment_failed",
"from_status": "charging",
"to_status": "past_due",
"initiator": { "type": "system", "id": null },
"origin": "scheduler",
"created_at": "2026-08-18T09:00:00.000000Z"
}
],
"next_page_token": ""
} События идут от новых к старым. Пустой next_page_token означает, что страниц больше нет.
Отдельное событие
- Метод
- GET
- URL
https://api.gigma.ru/api/subscriptions/{id}/status-events/{status_event}- Авторизация
- Bearer token
- Headers
Authorization: Bearer {token}- Успешный ответ
200
Параметры запроса
Параметры не передаются: событие выбирается идентификаторами в пути.
Ответ
{
"name": "subscriptions/981/status-events/4471",
"id": 4471,
"event_type": "payment_failed",
"from_status": "charging",
"to_status": "past_due",
"initiator": { "type": "system", "id": null },
"origin": "scheduler",
"created_at": "2026-08-18T09:00:00.000000Z"
} Ошибки
404— подписки нет в вашем проекте либо событие не принадлежит этой подписке.
Что учесть
- Отменить или возобновить подписку из этого контура нельзя. Методы
cancel,resume, смена карты и повтор платежа живут в клиентском контуре под Bearer клиента — см. изменение и отмену. Сотрудник подписку только видит. - Назначьте тарифы каждому приложению. У приложения, созданного через API, каталог фильтруется сразу, поэтому без назначений он пуст. Показ всех подписочных позиций проекта остаётся только у приложений с опущенным флагом
subscription_catalog_configured— там клиент увидит и чужие тарифы. - Тариф без
is_subscriptionназначить нельзя — метод ответит404, даже если позиция существует. - Цена подписки берётся из номенклатуры, а не из остатка на складе: складские настройки цены к подпискам не применяются.
- Разовые продажи — это заказы. Если списание не должно повторяться, вам нужен интернет-магазин, а не подписка.