MMeerPartners docs

API: Affiliate (self-service)

Self-service API инфлюенсера MeerPartners: профиль и KYC, каталог офферов, трекинг-ссылки, баланс, статистика и методы вывода.

Группа /api/v1/affiliate/* — кабинет инфлюенсера через API. Все эндпоинты требуют JWT инфлюенсера (Authorization: Bearer <access_token>). affiliate_id всегда берётся из токена, никогда из запроса (анти-IDOR). Денежные суммы — строки NUMERIC.

Embed-токен (scoped)

Scoped embed-токен (scope: affiliate:embed, выдаётся через token-exchange) работает в этой группе только на чтение в рамках своего affiliate_id. Мутации — создание/удаление методов вывода, изменение профиля и отправка KYC — требуют полного токена; иначе 403 EMBED_SCOPE_DENIED.

Списочные ответы здесь имеют форму { "items": [...], "total": N }.

Профиль

GET /affiliate/profile

GET/api/v1/affiliate/profile🔒 Bearer JWT

Профиль инфлюенсера: контакты, язык, статус KYC, реферальный код.

user_idintegerrequired
ID пользователя.
affiliate_idintegerrequired
ID партнёрского профиля.
emailstringoptional
Email (может отсутствовать).
display_namestringoptional
Отображаемое имя.
language_codestringoptional
Язык интерфейса (ru / en).
statusstringoptional
Статус профиля.
kyc_statusstringoptional
Статус KYC: none / pending / verified / rejected.
payout_currencystringoptional
Валюта выплат по умолчанию.
referral_codestringoptional
Реферальный код инфлюенсера для приглашения суб-партнёров.
created_atstringoptional
Дата создания (ISO 8601).
Ответ 200
{
  "user_id": 1042,
  "affiliate_id": 88,
  "email": "creator@example.com",
  "display_name": "Аня",
  "language_code": "ru",
  "status": "active",
  "kyc_status": "verified",
  "payout_currency": "RUB",
  "referral_code": "ANYA7K",
  "created_at": "2026-05-01T10:00:00Z"
}

PUT /affiliate/profile

PUT/api/v1/affiliate/profile🔒 Bearer JWT

Обновить отображаемое имя и/или язык. Требует полный токен.

display_namestringoptional
Новое отображаемое имя (до 160 символов).
language_codestringoptional
Язык: ru или en.

Возвращает обновлённый объект профиля (как в GET /affiliate/profile).

POST /affiliate/profile/kyc

POST/api/v1/affiliate/profile/kyc🔒 Bearer JWT

Отправить документы на KYC-проверку. Переводит статус из none/rejected в pending. Требует полный токен.

document_typestringrequired
Тип документа (например passport, national_id, driver_license), 1–64 символа.
document_refstringoptional
Ссылка/идентификатор загруженного документа (до 512 символов).
Ответ 200
{ "kyc_status": "pending" }

Ошибки: KYC_ALREADY_SUBMITTED (409 — уже pending/verified), PROFILE_NOT_FOUND (404), EMBED_SCOPE_DENIED (403).

Офферы

GET /affiliate/offers

GET/api/v1/affiliate/offers🔒 Bearer JWT

Каталог доступных офферов: все публичные плюс приватные, к которым выдан доступ.

Query-параметры: tenant_id (фильтр по бизнесу), geo (2-буквенный код страны), model (cpl/cpa/revshare/hybrid), skip (0+), limit (1–200, по умолчанию 50).

Ответ 200
{
  "items": [
    {
      "id": 501,
      "tenant_id": 17,
      "name": "Acme Premium",
      "slug": "acme-premium",
      "visibility": "public",
      "status": "active",
      "monetization_model": "cpa",
      "currency": "RUB",
      "hold_days": 14,
      "geo": ["RU", "KZ"],
      "cpa_amount": "750.00",
      "cpl_amount": null,
      "revshare_percent": null,
      "multilevel_enabled": true,
      "affiliate_access_status": null
    }
  ],
  "total": 12
}

affiliate_access_status — доступ к приватному офферу (approved / requested / null для публичных).

GET /affiliate/offers/{offer_id}

GET/api/v1/affiliate/offers/{offer_id}🔒 Bearer JWT

Детальная карточка оффера: всё из списка плюс условия и параметры multi-level.

termsobjectoptional
Условия оффера (правила, ограничения).
attribution_window_hoursintegeroptional
Окно атрибуции в часах (по умолчанию 720 = 30 дней).
max_levelsintegeroptional
Максимум уровней реферальной сети (если включён multi-level).
level_ratesobjectoptional
Ставки по уровням L0…L7.

Если status = paused — это отражается в поле, а UI показывает причину (OFFER_PAUSED).

Трекинг-ссылки

GET/api/v1/affiliate/links🔒 Bearer JWT

Список ваших трекинг-ссылок. Query: skip (0+), limit (1–500, по умолчанию 100).

POST /affiliate/links

POST/api/v1/affiliate/links🔒 Bearer JWT

Создать ссылку на оффер. Возвращает короткий code для пути /r/{code}.

offer_idintegerrequired
ID оффера, на который создаём ссылку.
sub_id1stringoptional
Метка для аналитики (до 128 символов).
sub_id2stringoptional
Метка для аналитики (до 128 символов).
sub_id3stringoptional
Метка для аналитики (до 128 символов).
Ответ 201
{
  "id": 9001,
  "offer_id": 501,
  "tenant_id": 17,
  "code": "a1B2c3",
  "is_active": true,
  "deep_link_params": {},
  "created_at": "2026-06-14T12:00:00Z"
}

Ошибки: LINK_LIMIT_REACHED (422), OFFER_PAUSED (422), OFFER_NOT_FOUND (404).

GET/api/v1/affiliate/links/{link_id}🔒 Bearer JWT

Ссылка вместе со статистикой.

clicksintegeroptional
Всего кликов.
unique_clicksintegeroptional
Уникальных кликов.
conversionsintegeroptional
Конверсий.
epcstringoptional
Earnings per click (строка NUMERIC).
Ответ 200
{
  "id": 9001,
  "offer_id": 501,
  "tenant_id": 17,
  "code": "a1B2c3",
  "is_active": true,
  "deep_link_params": {},
  "created_at": "2026-06-14T12:00:00Z",
  "clicks": 4210,
  "unique_clicks": 3880,
  "conversions": 96,
  "epc": "17.05"
}

Как формировать ссылку с метками и макросами — на странице Трекинг-ссылки.

Баланс

GET /affiliate/balance

GET/api/v1/affiliate/balance🔒 Bearer JWT

Баланс по валютам: доступно к выводу, в hold и заблокировано под активную заявку. Валюты с нулевыми суммами в ответ не попадают.

balancesarrayrequired
Список агрегатов по валютам.
balances[].currencystringrequired
Валюта (ISO-код).
balances[].payablestringrequired
Доступно к выводу.
balances[].holdstringrequired
В hold — начислено, ещё «зреет».
balances[].lockedstringrequired
Заблокировано под активную payout-заявку.
Ответ 200
{
  "balances": [
    { "currency": "RUB", "payable": "12400.00", "hold": "3100.00", "locked": "0.00" },
    { "currency": "USD", "payable": "85.00", "hold": "0.00", "locked": "10.00" }
  ]
}

Статистика

GET /affiliate/stats

GET/api/v1/affiliate/stats🔒 Bearer JWT

Агрегаты по кликам, конверсиям и комиссиям: по дням, по офферам и по уровням сети. Query: date_from, date_to (формат YYYY-MM-DD).

period_fromstringoptional
Начало периода (дата).
period_tostringoptional
Конец периода (дата).
total_clicksintegerrequired
Всего кликов за период.
total_conversionsintegerrequired
Всего конверсий.
total_commissionstringrequired
Суммарная комиссия (NUMERIC).
by_dayarrayrequired
Разбивка по дням (день × оффер).
by_offerarrayrequired
Разбивка по офферам.
by_levelarrayrequired
Разбивка комиссий по уровням (L0 — прямые, L1+ — сетевые).
Ответ 200 (фрагмент)
{
  "period_from": "2026-06-01",
  "period_to": "2026-06-14",
  "total_clicks": 18240,
  "total_conversions": 412,
  "total_commission": "215300.00",
  "by_day": [
    {
      "day": "2026-06-14",
      "offer_id": 501,
      "offer_name": "Acme Premium",
      "tenant_id": 17,
      "clicks": 1320,
      "unique_clicks": 1190,
      "conversions": 31,
      "revenue": "0.00",
      "commission_total": "23250.00",
      "currency": "RUB"
    }
  ],
  "by_level": [
    { "level": 0, "currency": "RUB", "commission_total": "190000.00", "conversions": 380 },
    { "level": 1, "currency": "RUB", "commission_total": "25300.00", "conversions": 32 }
  ]
}

Методы вывода

GET /affiliate/payout-methods

GET/api/v1/affiliate/payout-methods🔒 Bearer JWT

Список сохранённых методов вывода. Реквизиты зашифрованы и наружу не отдаются — только маскированный хвост display_last4.

Ответ 200
{
  "items": [
    {
      "id": 301,
      "method_type": "card",
      "display_last4": "4242",
      "is_default": true,
      "is_verified": true,
      "created_at": "2026-05-10T09:00:00Z"
    }
  ]
}

POST /affiliate/payout-methods

POST/api/v1/affiliate/payout-methods🔒 Bearer JWT

Добавить метод вывода. Реквизиты шифруются AES-256-GCM перед записью. Требует полный токен (embed → 403 EMBED_SCOPE_DENIED).

method_typestringrequired
Тип метода (card, crypto, и т.п.), 1–24 символа.
detailsobjectrequired
Реквизиты в открытом виде (например card_number, wallet_address). Шифруются на сервере.
is_defaultbooleanoptional
Сделать методом по умолчанию. По умолчанию false.

В ответе (201) — объект метода с display_last4; полные реквизиты не возвращаются.

DELETE /affiliate/payout-methods/{method_id}

DELETE/api/v1/affiliate/payout-methods/{method_id}🔒 Bearer JWT

Удалить свой метод вывода. Требует полный токен. Успех — 204 No Content без тела.

Что дальше