Партнёрская программа
Владелец задаёт процент от прибыли, партнёры приводят людей по своей ссылке и смотрят баланс в чате через партнёрского агента. На странице — методы владельца и устройство программы.
Как устроена программа
Программа своя у каждого ассистента: процент, партнёры и начисления живут внутри ассистента, общей партнёрки на площадке нет.
| Что | Как работает |
|---|---|
| Кто партнёр | Любой пользователь ассистента. Его код ссылки (8 символов) создаётся при первом запросе ссылки и дальше не меняется. |
| Ссылка | https://framesuite.app/f/{frame_slug}?r=<код>, при своём домене — https://<домен>/?r=<код>. Старые формы ?partner=<код> и ?ref=<код> тоже принимаются; ref считается партнёрским, только если код существует, иначе это метка источника трафика. |
| Привязка | Переход по ссылке кладёт куку на 30 дней. Человек привязывается к партнёру в момент создания учётки (в том числе гостевой), при входе гостя в аккаунт привязка переносится. До создания учётки действует последний переход, после привязки повторные переходы её не меняют. Привязать самого себя нельзя. |
| Что считается | Процент берётся от прибыли приведённого человека: выручка по его завершённым платежам минус себестоимость его сообщений. Начисление пожизненное — со всех платежей, включая продления. |
| Возвраты | Возврат платежа пишет сторно, заработок уменьшается. Восстановление платежа снимает сторно. |
| Процент | Всегда текущий: смена процента пересчитывает весь заработок партнёра, в том числе прошлый. |
| Выплаты | Ручные: партнёр пишет в поддержку, владелец платит сам. Таблицы заявок и API выплат нет. |
Заработок — величина живая: себестоимость копится, пока человек общается с ассистентом, поэтому earned_usd может уменьшаться. Меньше нуля он не бывает.
Тумблер и процент независимы. По умолчанию программа выключена (partner_enabled: false). Пока она выключена, начислений нет вовсе, а методы партнёра /partner/me/* отвечают 403. Переходы по ссылкам при этом всё равно запоминаются: включение не начисляет задним числом, но и не теряет уже приведённых людей. Выключение прекращает новые начисления.
Партнёр видит свою статистику в чате — через партнёрского агента, который ходит в методы /partner/me/*. Владелец управляет программой методами ниже, ключом user_…. Методы владельца открыты и владельцу ассистента, и пользователю с расшаренным доступом; чужой ассистент — 404.
Настройки программы
Получить настройки
Тумблер и текущий процент.
GET /assistants/{assistantId}/partner
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | integer | да | Путь. Id ассистента. |
curl -s "$BASE/assistants/$ASSISTANT/partner" \
-H "Authorization: Bearer $KEY"
{
"success": true,
"partner_enabled": true,
"partner_percent": 50
}
| Свойство | Тип | Описание |
|---|---|---|
partner_enabled | boolean | Включена ли программа. По умолчанию false. |
partner_percent | number | Доля партнёра от прибыли реферала, 0–100, два знака после запятой. По умолчанию 0. |
Изменить тумблер и процент
Оба поля необязательны и независимы: пришло одно — второе не меняется. Процент можно задать заранее и включить программу позже.
PUT /assistants/{assistantId}/partner
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | integer | да | Путь. Id ассистента. |
partner_enabled | boolean | нет | Тело. Тумблер программы. |
partner_percent | number | нет | Тело. 0–100, округляется до двух знаков. |
curl -s -X PUT "$BASE/assistants/$ASSISTANT/partner" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"partner_enabled": true, "partner_percent": 30}'
{
"success": true,
"partner_enabled": true,
"partner_percent": 30
}
Заработок партнёра всегда считается по текущему partner_percent. Снизили процент — уменьшился и уже накопленный заработок всех партнёров, повысили — вырос.
| HTTP | Когда |
|---|---|
| 404 | Ассистент не найден или нет доступа: {"error": "Project not found or access denied"} |
| 422 | Процент вне 0–100 или не число, тумблер не boolean |
Тело ошибки валидации:
{
"error": "Validation failed",
"messages": {
"partner_percent": ["The partner percent field must not be greater than 100."],
"partner_enabled": ["The partner enabled field must be true or false."]
}
}
Партнёры и выплаты
Сводка по партнёрам
Все партнёры ассистента: сколько людей привёл каждый, сколько они принесли и сколько партнёру причитается. Владелец видит партнёров поимённо — почта нужна, чтобы договориться о выплате. В обратную сторону правило строже: партнёр своих рефералов видит только обезличенно.
GET /assistants/{assistantId}/partner/earnings
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | integer | да | Путь. Id ассистента. |
limit | integer | нет | Строка запроса. 1–500, по умолчанию 50. |
offset | integer | нет | Строка запроса. С какой строки, по умолчанию 0. |
curl -s "$BASE/assistants/$ASSISTANT/partner/earnings?limit=50&offset=0" \
-H "Authorization: Bearer $KEY"
{
"success": true,
"total": 2,
"limit": 50,
"offset": 0,
"currency": "USD",
"percent": 50,
"partners": [
{
"partner_user_id": 104211,
"referral_code": "k7m2xq9d",
"email": "partner@example.com",
"name": "Анна",
"referrals_count": 312,
"revenue_usd": 48.2,
"expense_usd": 21.4,
"profit_usd": 26.8,
"earned_usd": 13.4
},
{
"partner_user_id": 98120,
"referral_code": "p4hn8wzr",
"email": "guest_XXXXXXXX@anonymous.local",
"name": "Guest",
"referrals_count": 2,
"revenue_usd": 0,
"expense_usd": 1.2,
"profit_usd": -1.2,
"earned_usd": 0
}
]
}
| Свойство | Тип | Описание |
|---|---|---|
total | integer | Сколько всего партнёров, у которых есть хотя бы один привязанный человек. |
percent | number | Текущий процент программы. |
partners[].partner_user_id | integer | Id пользователя-партнёра, ключ строки. |
partners[].referral_code | string | Код партнёрской ссылки — по нему удобнее опознать партнёра в переписке. |
partners[].email, name | string | Контакты партнёра. У гостя без аккаунта — служебная почта guest_…@anonymous.local и имя Guest. |
partners[].referrals_count | integer | Сколько людей привёл. Дубли одной и той же гостевой учётки считаются одним человеком. |
partners[].revenue_usd | number | Выручка с его людей в USD: приходы минус возвраты. Только платежи при включённой программе. |
partners[].expense_usd | number | Себестоимость сообщений его людей у этого ассистента, USD. |
partners[].profit_usd | number | revenue_usd − expense_usd, может быть отрицательной. |
partners[].earned_usd | number | Сколько причитается партнёру: percent × profit_usd / 100, не меньше нуля. |
Партнёры идут по возрастанию partner_user_id. Суммы — живые: пересчитываются при каждом запросе.
| HTTP | Когда |
|---|---|
| 404 | Ассистент не найден или нет доступа |
Партнёрский агент
Партнёр получает ссылку и видит баланс через агента «Партнёрская программа» в чате. Установка заводит одного агента со слагом partner: системный промпт с условиями программы, четыре коннектора на /partner/me/* (balance, referrals, earnings, link) и пять подсказок-чипов внутри агента. Модель — быстрая google/gemini-3.5-flash-lite, агент безлимитный, картинки у него выключены. Приветственный экран установка не трогает: к агенту партнёров приводят прямой ссылкой.
Состояние агента
Установлен ли агент, сколько у него коннекторов и подсказок, и пример ссылки.
GET /assistants/{assistantId}/partner/agent
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | integer | да | Путь. Id ассистента. |
curl -s "$BASE/assistants/$ASSISTANT/partner/agent" \
-H "Authorization: Bearer $KEY"
{
"success": true,
"partner_enabled": true,
"partner_percent": 50,
"example_link": "https://bota.chat/?r=<код>",
"installed": true,
"agent_id": 810,
"agent_slug": "partner",
"category": "Сделайте за минуту",
"connectors_count": 4,
"quick_actions_count": 5
}
| Свойство | Тип | Описание |
|---|---|---|
example_link | string | Образец партнёрской ссылки с заглушкой <код>. На своём домене — https://<домен>/?r=…, без него — https://framesuite.app/f/{frame_slug}?r=…. |
installed | boolean | Агент установлен. |
agent_id | integer или null | Id агента. |
agent_slug | string или null | Слаг для прямой ссылки ?agent=…. |
category | string или null | Категория агента. |
connectors_count | integer | Сколько коннекторов у агента, штатно 4. |
quick_actions_count | integer | Сколько подсказок-чипов, штатно 5. |
До установки: installed: false, agent_id, agent_slug и category — null, счётчики — 0.
Установить или обновить агента
Заводит партнёрского агента или обновляет уже установленного: тексты, промпт, адреса коннекторов. Повторный вызов дублей не создаёт. Агентов-кнопок из ранних версий установщика вызов удаляет. Тумблер программы не трогает — включать отдельно через PUT …/partner.
POST /assistants/{assistantId}/partner/agent
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | integer | да | Путь. Id ассистента. |
percent | number | нет | Тело. 0–100. Если передан — записывается в partner_percent ассистента. |
category | string | нет | Тело. Категория агента, до 64 символов. По умолчанию partner. |
curl -s -X POST "$BASE/assistants/$ASSISTANT/partner/agent" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"percent": 30}'
Пример ответа собран по коду:
{
"success": true,
"partner_enabled": false,
"agent_id": 812,
"agent_slug": "partner",
"created": true,
"category": "partner",
"percent": 30,
"connectors": [
{ "name": "balance", "url": "https://framesuite.app/api/v1/partner/me/summary" },
{ "name": "referrals", "url": "https://framesuite.app/api/v1/partner/me/referrals" },
{ "name": "earnings", "url": "https://framesuite.app/api/v1/partner/me/earnings" },
{ "name": "link", "url": "https://framesuite.app/api/v1/partner/me/link" }
],
"quick_actions": [
"Покажи мой баланс",
"Дай мою реферальную ссылку",
"Покажи моих рефералов",
"Хочу вывести деньги",
"Вопросы и ответы"
],
"legacy_agents_removed": 0,
"example_link": "https://framesuite.app/f/AbCdEf123456?r=<код>"
}
| Свойство | Тип | Описание |
|---|---|---|
created | boolean | true — агента не было, создан; false — обновлён. |
percent | number | Процент программы после вызова. |
connectors | array | Имена и адреса коннекторов агента. |
quick_actions | array | Тексты подсказок-чипов — ровно в том виде, в каком они уходят в чат от лица пользователя. На «Вопросы и ответы» ответ заготовлен и приходит сразу, без модели. |
legacy_agents_removed | integer | Сколько агентов-кнопок из прошлых версий удалено. |
| HTTP | Когда |
|---|---|
| 404 | Ассистент не найден или нет доступа |
| 422 | percent вне 0–100, category длиннее 64 символов |
Прямая ссылка на агента
Публичный вход ассистента понимает параметр ?agent= — чат откроется сразу на партнёрском агенте. Он сочетается с партнёрским кодом:
https://framesuite.app/f/{frame_slug}?agent=partner
https://framesuite.app/f/{frame_slug}?agent=partner&r=k7m2xq9d
https://<ваш домен>/?agent=partner
Значение — слаг агента (partner), принимается также числовой id. Агент должен принадлежать этому ассистенту, иначе параметр молча игнорируется. Подробнее о ссылках на агентов — в разделе Экран-профиль и ссылки.
Методы партнёра
Методы /partner/me/* вызывает партнёрский агент во время разговора, а не владелец. Ключом user_… их не вызвать: авторизация — короткий токен пользователя, который движок коннекторов выпускает на каждый вызов (JWT, живёт 5 минут, область действия partner). И партнёр, и ассистент берутся из подписанного токена, поэтому параметров user_id и project_id (project_id называется так по историческим причинам, это id ассистента) у методов нет и чужие данные запросить нельзя.
| Метод | Путь | Что отдаёт |
|---|---|---|
POST или GET | /partner/me/summary | Сводка партнёра: referrals_count, revenue_usd, expense_usd, profit_usd, earned_usd, percent, link, currency |
POST или GET | /partner/me/referrals | Обезличенный список приведённых: number, referred_at, registered, paid, revenue_usd, earned_usd; постранично limit (1–500, по умолчанию 50) и offset |
POST или GET | /partner/me/earnings | Журнал платежей рефералов, с которых считается доля: id, payment_id, kind (revenue или reversal), status (pending или cancelled), amount_usd, percent, created_at; постранично |
POST или GET | /partner/me/link | Код, готовая ссылка и текущий процент |
Движок шлёт POST с телом {name, arguments, context}, параметры страниц — внутри arguments. Токен ищется по порядку: заголовок X-Agent-User-Token, поле context.user_token в теле, заголовок Authorization: Bearer. Ответы — в конверте коннекторов:
{ "ok": true, "result": { "code": "k7m2xq9d", "link": "https://framesuite.app/f/AbCdEf123456?r=k7m2xq9d", "percent": 30 } }
| HTTP | Когда |
|---|---|
| 401 | Нет токена (Connector token is required), токен просрочен, подделан или это ключ user_… (Invalid or expired token), токен другой области (Token scope mismatch) |
| 403 | Программа выключена: {"ok": false, "error_code": 403, "description": "Партнёрская программа на этом ассистенте не активна"} |
В earnings поле amount_usd — сумма платежа реферала, а не заработок партнёра; складывать строки журнала в баланс нельзя, баланс — только earned_usd из сводки.