Подписчики, кредиты, платежи
Деньги ассистента через API: кто подписан и до какого числа, отмена подписки, ручное начисление кредитов и полный журнал платежей с доходом в долларах.
Что здесь
| Метод | Путь | Что делает |
|---|---|---|
GET | /assistants/{assistantId}/subscribers | Все подписки ассистента |
POST | /assistants/{assistantId}/subscribers/{subscriberId}/cancel | Отменить подписку в платёжном шлюзе |
POST | /assistants/{assistantId}/credits | Выставить или прибавить кредиты посетителю |
GET | /assistants/{assistantId}/transactions | Платежи ассистента с фильтрами и итогами |
Авторизация — ключ user_…. Доступ у владельца ассистента и у пользователя с расшаренным доступом; чужой или несуществующий ассистент — 404 {"success": false, "error": "Project not found or access denied"}.
Посетитель во всех методах опознаётся публичным id public_id вида u_k3m9x2p7qa. Его видно в транзакциях (user.public_id) и в карточке пользователя в интерфейсе.
Подписки
Список подписок
Все подписки ассистента одним списком: действующие, просроченные, отменённые и истёкшие, с текущим балансом кредитов подписчика. Фильтров и страниц у метода нет — отдаётся всё.
GET /assistants/{assistantId}/subscribers
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | integer | да | Путь. Id ассистента. |
curl -s "$BASE/assistants/$ASSISTANT/subscribers" \
-H "Authorization: Bearer $KEY"
{
"success": true,
"subscribers": [
{
"id": 318,
"status": "active",
"interval": "month",
"amount": 1900,
"currency": "RUB",
"credits_per_period": 20000,
"current_period_start": "2026-09-16 05:44:27",
"current_period_end": "2026-10-16 05:44:27",
"next_charge_at": "2026-10-16 05:43:58",
"cancelled_at": null,
"created_at": "2026-09-16 05:44:27",
"ai_credits": 19622,
"user_id": 104522,
"user_name": "Анна",
"user_email": "user@example.com"
}
]
}
Порядок: active, past_due, pending, cancelled, expired, внутри статуса — по current_period_end от поздних к ранним.
| Свойство | Тип | Описание |
|---|---|---|
id | integer | Id подписки — его передают в отмену. |
status | string | active — действует; past_due — списание не прошло, идут повторные попытки; pending — оформляется; cancelled — отменена (доступ до конца оплаченного периода); expired — закончилась. |
interval | string | Период тарифа: day, week, month, year. |
amount | integer | Цена за период в валюте подписки. |
currency | string | Валюта, ISO-код. |
credits_per_period | integer | Сколько кредитов начисляется за период. |
current_period_start, current_period_end | string | Границы оплаченного периода, YYYY-MM-DD HH:MM:SS UTC. |
next_charge_at | string или null | Когда следующее списание. |
cancelled_at | string или null | Когда отменена. |
created_at | string | Когда оформлена. |
ai_credits | integer или null | Текущий баланс кредитов подписчика у этого ассистента. |
user_id | integer | Внутренний id пользователя. |
user_name, user_email | string | Имя и почта подписчика. У входа через Telegram почта служебная — tg_<id>@telegram.local. |
Отменить подписку
Отменяет автосписание в платёжном шлюзе подписки (CloudPayments, Paddle, PayOnline) и помечает подписку отменённой. Подписку, выданную вручную (gateway = manual: владельцем или бонусом), шлюз не ведёт — она отменяется сразу у нас: status = cancelled, cancelled_at — текущее время, next_charge_at сбрасывается. Доступ человек сохраняет до конца оплаченного периода, деньги не возвращаются. Отменить можно только подписку в статусе active или past_due.
POST /assistants/{assistantId}/subscribers/{subscriberId}/cancel
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | integer | да | Путь. Id ассистента. |
subscriberId | integer | да | Путь. id подписки из списка (не id пользователя). |
curl -s -X POST "$BASE/assistants/$ASSISTANT/subscribers/318/cancel" \
-H "Authorization: Bearer $KEY"
Пример ответа собран по коду:
{
"success": true,
"subscription": {
"id": 318,
"status": "cancelled",
"cancelled_at": "2026-09-25T18:40:00+00:00"
}
}
Если шлюз уже сам закрыл подписку после неудачных списаний, отмена всё равно фиксируется. Если шлюз отказал в отмене, ответ — 502, подписка остаётся в прежнем статусе, в subscription — её текущее состояние:
{
"success": false,
"error": "Gateway did not cancel the subscription",
"subscription": {"id": 318, "status": "active", "cancelled_at": null}
}
| HTTP | Когда |
|---|---|
| 404 | Ассистент чужой; подписки с таким id нет у ассистента или она не в статусе active или past_due: {"success": false, "error": "Subscription not found"} |
| 400 | Шлюз подписки не настроен: {"success": false, "error": "Gateway not available"} |
| 502 | Шлюз не отменил подписку: {"success": false, "error": "Gateway did not cancel the subscription", "subscription": {…}} |
Возобновить отменённую подписку через API нельзя: человеку придётся оформить новую. Проверяйте id — это id подписки, а не пользователя.
Кредиты
Начислить кредиты посетителю
Выставляет или прибавляет кредиты конкретному посетителю у этого ассистента без оплаты: компенсация, подарок, тестовый пользователь для автотестов. Строка баланса создаётся, если её не было. Платёж и событие purchase не пишутся.
POST /assistants/{assistantId}/credits
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | integer | да | Путь. Id ассистента. |
user | string | да | Тело. public_id посетителя, до 64 символов. |
credits | integer | да | Тело. 0–1 000 000. |
mode | string | нет | Тело. set (по умолчанию) — выставить баланс ровно в credits; add — прибавить к текущему. |
curl -s -X POST "$BASE/assistants/$ASSISTANT/credits" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"user": "u_k3m9x2p7qa", "credits": 500, "mode": "add"}'
Пример ответа собран по коду:
{
"success": true,
"user": "u_k3m9x2p7qa",
"ai_credits": 1250
}
ai_credits — баланс после операции.
| HTTP | Когда |
|---|---|
| 404 | Ассистент чужой: {"success": false, "error": "Project not found or access denied"}; посетителя с таким public_id нет: {"success": false, "error": "User not found"} |
| 400 | Тело не разбирается как JSON: {"success": false, "error": "invalid_json", "message": "Request body is not valid JSON: Syntax error"} |
| 422 | Нет user или credits, credits вне 0–1 000 000, mode не set и не add |
Тело ошибки валидации:
{
"success": false,
"message": "The user field is required. (and 2 more errors)",
"errors": {
"user": ["The user field is required."],
"credits": ["The credits field must be at least 0."],
"mode": ["The selected mode is invalid."]
}
}
public_id ищется по всей площадке, а не только среди пользователей ассистента: начислить можно любому существующему посетителю, баланс заведётся ему у вашего ассистента.
Платежи
Список платежей
Все платежи ассистента с суммами, статусом, шлюзом, начисленными кредитами, сырыми данными шлюза и покупателем, плюс итог дохода по выборке. Только чтение.
GET /assistants/{assistantId}/transactions
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | integer | да | Путь. Id ассистента. |
status | string | нет | Строка запроса. pending, completed, failed, refunded, bonus. Значение не проверяется: неизвестный статус даёт пустую выборку. |
gateway | string | нет | Строка запроса. Шлюз: cloudpayments, paddle, payonline, bonus и другие подключённые. |
user | string | нет | Строка запроса. public_id покупателя. Неизвестный id — пустая выборка. |
from, to | string | нет | Строка запроса. Границы по дате создания платежа включительно, YYYY-MM-DD или YYYY-MM-DD HH:MM:SS, UTC. Дата без времени — полночь: чтобы захватить весь день в to, передайте 2026-09-30 23:59:59. Неразборчивая дата молча игнорируется. |
limit | integer | нет | Строка запроса. 1–1000, по умолчанию 100. |
offset | integer | нет | Строка запроса. По умолчанию 0. |
curl -s "$BASE/assistants/$ASSISTANT/transactions?status=completed&from=2026-09-01&to=2026-09-30%2023:59:59&limit=100" \
-H "Authorization: Bearer $KEY"
{
"success": true,
"total": 14,
"revenue_usd": 118.46,
"revenue_by_currency": [
{ "currency": "RUB", "amount": 9870, "count": 13 },
{ "currency": "USD", "amount": 1, "count": 1 }
],
"transactions": [
{
"id": 15210,
"gateway": "cloudpayments",
"gateway_payment_id": "3780000000",
"status": "completed",
"amount": 490,
"amount_usd": 5.82,
"currency": "RUB",
"credits_added": 5428,
"metadata": {
"credits": 5428,
"interval": "week",
"plan_name": "На неделю",
"is_subscription_initial": true,
"card_type": "Visa",
"card_last_four": "0000",
"payment_method": "Sbp",
"subscription_id": "sc_XXXXXXXX"
},
"user": {
"public_id": "u_a1b2c3d4e5",
"name": "Анна",
"email": "user@example.com"
},
"created_at": "2026-09-22T03:10:16+00:00",
"updated_at": "2026-09-22T03:10:53+00:00"
}
]
}
Платежи идут от новых к старым.
| Свойство | Тип | Описание |
|---|---|---|
total | integer | Сколько платежей подходит под фильтр, без учёта limit и offset. |
revenue_usd | number | Доход по завершённым (completed) платежам выборки в долларах — сумма amount_usd. Единственный верный итог при разных валютах. |
revenue_by_currency | array | Разбивка завершённых платежей по валютам: currency, amount (сумма в этой валюте), count. Складывать между собой нельзя. |
transactions[].id | integer | Внутренний id платежа. |
transactions[].gateway | string | Шлюз. bonus — подарок от площадки без денег. |
transactions[].gateway_payment_id | string или null | Id транзакции в шлюзе — для сверки с кабинетом кассы. |
transactions[].status | string | pending — создан, оплаты нет; completed — оплачен; failed — не прошёл; refunded — возвращён; bonus — подарок, в доход не входит. |
transactions[].amount | number | Сумма в валюте платежа. |
transactions[].amount_usd | number или null | Сумма в долларах, по ней считается доход. Для RUB — по курсу, для локализованных валют Paddle (например, MXN) — цена тарифа в долларах. |
transactions[].currency | string | Валюта, ISO-код. |
transactions[].credits_added | integer | Сколько кредитов начислено этим платежом. |
transactions[].metadata | object или null | Сырые данные шлюза: тариф, период, причина отказа, тип карты и последние цифры, признак рекуррента. Набор ключей зависит от шлюза. |
transactions[].user | object | Покупатель: public_id, name, email. Поля null, если учётка удалена. |
transactions[].created_at, updated_at | string | ISO 8601, UTC. |
| HTTP | Когда |
|---|---|
| 404 | Ассистент не найден или нет доступа: {"success": false, "error": "Project not found or access denied"}; нечисловой assistantId — {"success": false, "error": "The route … could not be found."} |
Сценарий: компенсация после сбоя
Найти платёж человека, убедиться, что он прошёл, и добавить кредиты сверху:
curl -s "$BASE/assistants/$ASSISTANT/transactions?user=u_k3m9x2p7qa" \
-H "Authorization: Bearer $KEY"
curl -s -X POST "$BASE/assistants/$ASSISTANT/credits" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"user": "u_k3m9x2p7qa", "credits": 1000, "mode": "add"}'