Управление подписками из кода

Списаниями, повторами и статусами занимается платформа — это описано в обзоре. На вашей стороне остаётся три вещи: завести тарифы, решить, какие из них видит витрина, и наблюдать за подписками, когда они пошли.

Всё это делается тем же 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 — размер страницы, максимум 100
  • query — поиск, от 3 символов
  • status[] — фильтр по статусам: active, charging, past_due, canceled
  • application_id[] — фильтр по приложениям
  • date_from — подписки, созданные с этой даты
  • date_to — подписки, созданные по эту дату
  • sort_bycreated_at, current_period_end, last_payment_at, amount
  • sort_dirasc или 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, максимум 100
  • page_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, даже если позиция существует.
  • Цена подписки берётся из номенклатуры, а не из остатка на складе: складские настройки цены к подпискам не применяются.
  • Разовые продажи — это заказы. Если списание не должно повторяться, вам нужен интернет-магазин, а не подписка.

© 2026 Gigma