Здесь используется одна подписка и отдельный запрос изменения её условий. Полей trial_days, trial_amount или массива тарифных этапов в API нет. Переход на основной тариф организует ваш сервер после подтверждения первоначальной оплаты и активации подписки. Не нужно создавать вторую подписку.
До подтверждения клиент должен понимать цену триала, дату и сумму следующего списания, дальнейшую периодичность и способ отмены. Не считайте изменение API заменой информирования клиента о тарифе.
Шаг 1. Создайте подписку на 19 ₽
В примере используется обычное подключение h2h с email. Можно выбрать hosted: порядок смены тарифа остаётся тем же. Интервал пока месячный; срок триала зададим отдельной датой после первого успешного платежа.
curl -X POST 'https://api.cashera.cash/api/v1/integration/subscriptions' \-H "X-Api-Key: $CASHERA_API_KEY" \-H 'Accept: application/json' \-H 'Content-Type: application/json' \-d '{"amount": 1900,"external_id": "trial-customer-10428","interval": "monthly","interval_count": 1,"description": "Триал 19 ₽ на 5 дней, затем 290 ₽ в месяц","email": "customer@example.com","callback_url": "https://merchant.example/webhooks/cashera"}'
Используйте собственный публичный HTTPS callback URL вместо примера. Сохраните uuid подписки из ответа и отправьте клиенту confirmation_url. Если ссылка отсутствует, не активируйте доступ по одному успешному HTTP-ответу. При повторе создания используйте тот жеexternal_id и исходные параметры.
Шаг 2. Подтвердите оплату и активацию
- Проверьте подлинность каждого входящего webhook
- Получите
transaction.status_updatedсо статусомpaid, базовой суммой1900, валютойRUBи UUID нужной подписки в корневом объектеsubscription - Дождитесь состояния подписки
active, через событие или GET подписки - Сохраните UUID первой оплаты и
paid_at. Выдайте триальный доступ один раз
Эти события могут прийти в разном порядке: храните оба признака и запускайте переход после выполнения обоих условий. По одному active доступ не выдаётся. Для суммы, уплаченной клиентом с комиссией, проверяйтеgross_amount; базовая цена находится в amount.
Шаг 3. Вычислите конец триала
В этом сценарии пять дней означают 120 часов от paid_at первой успешной оплаты. Не считайте от создания подписки, открытия ссылки или времени доставки webhook. Если ваш продукт использует календарные дни, заранее задайте это отдельным правилом и учитывайте часовой пояс при вычислении даты.
// firstPayment проверен и сохранён в вашей БД.if (firstPayment.status !== 'paid' || firstPayment.paid_at === null) {throw new Error('Первый платёж не подтверждён');}const paidAt = Date.parse(firstPayment.paid_at);if (!Number.isFinite(paidAt)) {throw new Error('Некорректная дата оплаты');}const trialEnd = new Date(paidAt + 5 * 24 * 60 * 60 * 1000);if (trialEnd.getTime() <= Date.now()) {// Не подставляйте автоматически текущую дату: это может запустить немедленное списание.throw new Error('Конец триала уже в прошлом: требуется отдельное решение');}const operation = {key: 'trial-customer-10428-upgrade-v1',body: {amount: 29000,next_charge_at: trialEnd.toISOString(),interval: 'monthly',interval_count: 1,},};// Атомарно сохраните key и body с уникальной связью с этой подпиской// и этапом тарифа. Worker и обработчик webhook используют одну запись.// При retry перечитывайте сохранённую запись, не вычисляйте дату заново.
Шаг 4. Сразу установите основной тариф и будущую дату
Не ждите окончания пяти дней для вызова update. После первой оплаты и активации сразу запишите новые условия: 290 ₽, ближайшее списание в конце триала, затем раз в месяц. Сам update деньги не списывает. Для оплаты 1 ноября 2026 года в 09:00 UTC конец триала будет 6 ноября в 09:00 UTC:
curl -X POST 'https://api.cashera.cash/api/v1/integration/subscriptions/31dc7faa-c380-4ec7-a258-3202a2211e76/update' \-H "X-Api-Key: $CASHERA_API_KEY" \-H 'Accept: application/json' \-H 'Content-Type: application/json' \-H 'Idempotency-Key: trial-customer-10428-upgrade-v1' \-d '{"amount": 29000,"next_charge_at": "2026-11-06T09:00:00Z","interval": "monthly","interval_count": 1}'
Проверьте ответ 200: сумма 29000, месячный интервал и выбранная дата. amount в подписке уже будет 29000, хотя первая транзакция останется на 1900. История платежей и их комиссии не переписываются. Значение gross_amount может быть больше базовой цены, если комиссию оплачивает клиент. В примерах нет дополнительной комиссии клиента.
Используйте сохранённые ключ и JSON. Не меняйте будущую дату при каждом повторе. Если не удалось подтвердить переход, не показывайте пользователю, что месячный тариф уже настроен. Действуйте по инструкции по восстановлению.
Что происходит дальше
| Момент в UTC | Действие | Ваше приложение |
|---|---|---|
| 1 ноября, 09:00 | Подтверждён платёж 19 ₽ | Открывает триал до 6 ноября, 09:00 |
| После оплаты и активации | Успешный update на 290 ₽ и будущую дату | Сохраняет подтверждённые условия, новый платёж не создаёт |
| 6 ноября, 09:00 | Провайдер выполняет плановую попытку 290 ₽ | Продлевает доступ только после paid |
| Следующий месяц | Следующая дата определяется расписанием провайдера | Показывает фактическое next_charge_at, не заменяет месяц 30 днями |
Для регулярных платежей не вызывайте charge-now по собственному cron: плановые списания уже выполняет провайдер. Внеочередная попытка не переносит плановую дату и может привести к двум отдельным платежам за близкое время.
Если основное списание не прошло
Не продлевайте доступ по pending, failed или canceled платежа. Подписка может оставаться past_due, а сама по себе неудача не означает её отмену. Политику доступа после конца триала задаёт ваш сервис. Cashera не обещает автоматическую отмену через фиксированное число дней или заданное число повторов. Если повторная попытка нужна, сначала проверьте результат предыдущей и правила внеочередного списания.
Если клиент отказался, вызовите отмену подпискии подтвердите cancelled. Отмена не возвращает ранее уплаченные 19 ₽ или другие платежи.
