Payli|Partner API
← На сайт

Payli Partner API

REST API для получения каталога, создания заказов, отслеживания статусов, получения результата, проверки баланса и возврата заказов.

Base URL
https://payli.ru
пути ниже указаны полностью, напр. https://payli.ru/api/partner/v1/services
Content-Type
application/json
Авторизация
Authorization: Bearer <API_TOKEN>
Лимиты
GET — 600 / мин · POST — 60 / мин

Авторизация

Все запросы выполняются с API-токеном.

Authorization: Bearer <API_TOKEN>

Права токена (scopes)

Чтение (каталог, заказы, баланс, переписка) доступно любому действующему токену. Действия требуют прав, которые выдаются токену при создании; без нужного права — 403 insufficient_scope или 403 forbidden.

orders_create_acquirer
scope
POST /orders с оплатой ссылкой (sbp, card, crypto); POST-действия в чате ручного заказа
orders_refund
scope
POST /orders/{public_id}/refund

Общие правила

  • Заголовок запроса: Content-Type: application/json.
  • Все суммы передаются и возвращаются в рублях: 100.00.
  • Все даты возвращаются в формате RFC3339: 2026-05-06T09:31:09Z.
  • Неизвестные поля в теле POST /orders не допускаются — 400 invalid_json. В остальных POST (чат, подтверждение, спор) лишние поля игнорируются.
  • Для безопасных повторов POST /orders передавайте idempotency_key (или заголовок Idempotency-Key): повтор с тем же ключом вернёт уже созданный заказ с флагом idempotent_replay: true; тело повторного запроса не сверяется — ключ должен быть уникальным на каждый отдельный заказ.

GETКаталог · Сервисы

Список доступных сервисов каталога.

GET/api/partner/v1/services
Response
{
  "services": [
    {
      "code": "steam",
      "name": "Steam",
      "available": true,
      "min_rub": 100.00,
      "max_rub": 15000.00,
      "base_commission_percent": 4.00
    }
  ]
}
code
string
код сервиса
name
string
название
available
boolean
доступен ли сервис
min_rub / max_rub
number
Steam: границы суммы, зачисляемой на аккаунт (credited_rub — amount_pay_rub за вычетом комиссии); вне границ — 422 invalid_amount
base_commission_percent
number
базовая комиссия

GETКаталог · Категории

Список категорий с подкатегориями.

GET/api/partner/v1/categories
Response
{
  "categories": [
    {
      "id": 33,
      "name": "Mobile Legends",
      "description": "Пополнение Mobile Legends",
      "available": true,
      "sort": 100,
      "subcategories": [
        {
          "id": 36,
          "name": "Global",
          "description": "",
          "available": true,
          "sort": 100
        }
      ]
    }
  ]
}
id
number
ID категории
name
string
название
description
string
описание
available
boolean
доступна ли категория
sort
number
порядок сортировки
subcategories
array
подкатегории (id, name, description, available, sort)

GETКаталог · Товары категории

Товары выбранной категории.

GET/api/partner/v1/categories/{category_id}/products
Response
{
  "category": {
    "id": 33,
    "name": "Mobile Legends",
    "available": true
  },
  "products": [
    {
      "id": 681,
      "category_id": 33,
      "subcategory_id": 36,
      "subcategory_name": "Global",
      "name": "156 + 16 алмазов",
      "description": "Пакет алмазов",
      "help_description": "Укажите User ID и Server",
      "type": "topup",
      "available": true,
      "price_rub": 214.00,
      "pricing": {
        "default_method": "sbp",
        "methods": {
          "sbp":    { "amount_rub": 214.00, "commission_percent": 7.00 },
          "card":   { "amount_rub": 221.00, "commission_percent": 10.00 },
          "crypto": { "amount_rub": 214.00, "amount_usdt": 2.41, "commission_percent": 7.00 }
        }
      },
      "fields": [
        {
          "key": "Input1",
          "placeholder": "User ID"
        }
      ]
    }
  ]
}
id
number
ID товара (для product_id в заказе)
category_id / subcategory_id
number
категория и подкатегория
subcategory_name
string
название подкатегории
name / description / help_description
string
названия и подсказки
type
string
тип: topup, voucher, esim, manual (ручная выдача исполнителем — заказ идёт через чат)
available
boolean
доступен ли товар
price_rub
number
цена в рублях (по умолчанию — СБП)
pricing
object
цены по способам оплаты: pricing.methods.{sbp|card|crypto} → amount_rub + commission_percent (crypto также amount_usdt). Способ присутствует, только если доступен. default_method=sbp.
fields
array
поля формы заказа: key, placeholder, description, max_length, validation_rule, values (допустимые значения), sensitive

Поле с sensitive: true — это учётные данные покупателя (пароль или токен от аккаунта). Вводите его скрытым полем и не показывайте покупателю повторно. В ответах API поля заказа возвращаются в том виде, в котором вы их прислали, включая значения sensitive-полей — храните их как секрет.

GETКаталог · Товар по id

Один товар по идентификатору.

GET/api/partner/v1/products/{product_id}
Response
{
  "product": {
    "id": 681,
    "category_id": 33,
    "subcategory_id": 36,
    "subcategory_name": "Global",
    "name": "156 + 16 алмазов",
    "description": "Пакет алмазов",
    "help_description": "Укажите User ID и Server",
    "type": "topup",
    "available": true,
    "price_rub": 214.00,
    "pricing": {
      "default_method": "sbp",
      "methods": {
        "sbp":    { "amount_rub": 214.00, "commission_percent": 7.00 },
        "card":   { "amount_rub": 221.00, "commission_percent": 10.00 },
        "crypto": { "amount_rub": 214.00, "amount_usdt": 2.41, "commission_percent": 7.00 }
      }
    },
    "fields": [
      {
        "key": "Input1",
        "placeholder": "User ID"
      }
    ]
  }
}

Товар eSIM содержит дополнительный объект esim:

Response · eSIM
{
  "product": {
    "id": 1042,
    "category_id": 50,
    "subcategory_id": 51,
    "subcategory_name": "Европа",
    "name": "Европа · 10 ГБ · 30 дней",
    "type": "esim",
    "available": true,
    "price_rub": 390.00,
    "pricing": {
      "default_method": "sbp",
      "methods": {
        "sbp":    { "amount_rub": 390.00, "commission_percent": 7.00 },
        "card":   { "amount_rub": 402.00, "commission_percent": 10.00 },
        "crypto": { "amount_rub": 390.00, "amount_usdt": 4.39, "commission_percent": 7.00 }
      }
    },
    "fields": [],
    "esim": {
      "country_code": "EU",
      "geo_scope": "region",
      "package_type": "data",
      "data_unit": "GB",
      "data_qty": 10,
      "data_unlimited": false,
      "validity_days": 30,
      "voice_minutes": 0,
      "voice_unlimited": false,
      "sms": 0,
      "sms_unlimited": false,
      "sms_incoming_only": false,
      "operator": "Orange",
      "max_generation": "5G",
      "can_renew": true,
      "coverage_count": 39,
      "coverage_country_codes": ["FR", "DE", "IT", "ES"]
    }
  }
}

POSTСоздание заказа

POST/api/partner/v1/orders

Создаёт заказ и возвращает ссылку на оплату. После оплаты статус заказа можно получить через GET /api/partner/v1/orders/{public_id}.

Поля

typereq
string
тип заказа: steam, topup, voucher, esim, manual (ручная выдача, см. раздел ниже)
account
string
аккаунт получателя, только для Steam
amount_pay_rub
number
сумма заказа, только для Steam
product_id
number
ID товара — для topup / voucher / eSIM / manual (при продлении eSIM по renew_order_id можно не передавать)
fields
object
поля товара из его карточки — для topup / voucher / eSIM / manual; у voucher / eSIM поле email необязательно (пусто — без письма покупателю; непустое должно быть валидным адресом)
payment_method
string
способ оплаты: sbp (синоним acquirer, по умолчанию — СБП) | card — банковская карта, дороже на надбавку к комиссии | crypto — криптовалюта (USDT)
partner_commission_percent
number
партнёрская наценка, опционально
redirect_url
string
URL возврата после оплаты, опционально
webhook_url
string
URL для уведомлений по заказу, опционально
webhook_secret
string
секрет для подписи webhook, опционально (≤512 символов)
idempotency_key
string
ключ идемпотентности, опционально (≤128 символов)
renew_order_id
string
public_id исходного eSIM-заказа для продления, опционально
renew_iccid
string
ICCID eSIM для продления, опционально

Способ оплаты (payment_method)

По умолчанию заказ оплачивается ссылкой эквайринга по СБП (acquirer). Карта (card) — оплата банковской картой: тот же рублёвый рельс, что СБП, но с надстройкой к комиссии (карта дороже, покрывает эквайринг). Криптовалюта (crypto) — оплата в USDT. Передайте нужный payment_method в любом типе заказа (Steam / Topup / Voucher / eSIM / manual):card/crypto возвращают payment.pay_url на соответствующую страницу оплаты (для crypto — с выбором монеты/сети и суммойpayment.amount_usdt). Подтверждение приходит обычным вебхуком о статусе заказа. Если способ временно недоступен — 503 с кодом card_unavailable /crypto_unavailable (без молчаливого отката на СБП).

Steam

POST /api/partner/v1/orders
{
  "type": "steam",
  "account": "my_steam_login_or_url",
  "amount_pay_rub": 1000.00,
  "partner_commission_percent": 4.00,
  "redirect_url": "https://partner.example/return",
  "webhook_url": "https://partner.example/payli/webhook",
  "webhook_secret": "your-random-secret",
  "idempotency_key": "order-10001"
}

Topup

POST /api/partner/v1/orders
{
  "type": "topup",
  "product_id": 681,
  "fields": {
    "Input1": "123456789",
    "Input2": "11"
  },
  "partner_commission_percent": 1.50,
  "redirect_url": "https://partner.example/return",
  "webhook_url": "https://partner.example/payli/webhook",
  "webhook_secret": "your-random-secret",
  "idempotency_key": "order-10002"
}

Voucher

POST /api/partner/v1/orders
{
  "type": "voucher",
  "product_id": 777,
  "fields": {
    "email": "customer@example.com"
  },
  "partner_commission_percent": 2.00,
  "redirect_url": "https://partner.example/return",
  "webhook_url": "https://partner.example/payli/webhook",
  "webhook_secret": "your-random-secret",
  "idempotency_key": "order-10003"
}

Voucher без email:

POST /api/partner/v1/orders
{
  "type": "voucher",
  "product_id": 777,
  "fields": {
    "email": ""
  },
  "partner_commission_percent": 2.00,
  "redirect_url": "https://partner.example/return",
  "webhook_url": "https://partner.example/payli/webhook",
  "webhook_secret": "your-random-secret",
  "idempotency_key": "order-10004"
}

eSIM

POST /api/partner/v1/orders
{
  "type": "esim",
  "product_id": 1042,
  "fields": {
    "email": "customer@example.com"
  },
  "partner_commission_percent": 2.00,
  "redirect_url": "https://partner.example/return",
  "webhook_url": "https://partner.example/payli/webhook",
  "webhook_secret": "your-random-secret",
  "idempotency_key": "order-10005"
}

Продление eSIM

Продлить (top-up) eSIM можно только после того, как её текущий пакет закончится — израсходуется трафик или истечёт срок. Пока пакет активен (или выдан, но ещё не использован), создание заказа-продления вернёт 400 renew_not_available с пояснением (остаток трафика / до какой даты действует). Актуальное состояние — в поле esim.packages и esim.renewable_now ответа заказа.

По исходному заказу:

POST /api/partner/v1/orders
{
  "type": "esim",
  "renew_order_id": "5f44b1b0-2f8d-45a9-82f5-4b0a26cda111",
  "fields": {
    "email": "customer@example.com"
  },
  "partner_commission_percent": 2.00,
  "redirect_url": "https://partner.example/return",
  "webhook_url": "https://partner.example/payli/webhook",
  "webhook_secret": "your-random-secret",
  "idempotency_key": "order-10006"
}

По ICCID:

POST /api/partner/v1/orders
{
  "type": "esim",
  "renew_iccid": "8943108170000000000",
  "product_id": 1042,
  "fields": {
    "email": "customer@example.com"
  },
  "partner_commission_percent": 2.00,
  "redirect_url": "https://partner.example/return",
  "webhook_url": "https://partner.example/payli/webhook",
  "webhook_secret": "your-random-secret",
  "idempotency_key": "order-10007"
}

Ответ

200 OK
{
  "order": {
    "public_id": "8af8e6b2-19f1-48d1-9e3e-67e9e8c0a814",
    "type": "voucher",
    "status": "pending_payment",
    "payment_method": "acquirer",
    "product_id": 777,
    "amount_base_rub": 117.65,
    "partner_commission_percent": 2.00,
    "partner_commission_rub": 2.35,
    "partner_fee_rub": 2.35,
    "amount_pay_rub": 120.00
  },
  "payment": {
    "pay_url": "https://payment.example/pay?id=..."
  }
}

При payment_method: crypto блок payment содержит сумму в USDT (amount_usdt), а pay_url ведёт на страницу оплаты с выбором монеты и сети:

200 OK · payment_method: crypto
{
  "order": {
    "public_id": "8af8e6b2-19f1-48d1-9e3e-67e9e8c0a814",
    "type": "voucher",
    "status": "pending_payment",
    "payment_method": "crypto",
    "product_id": 777,
    "amount_pay_rub": 120.00
  },
  "payment": {
    "pay_url": "https://pay.example/crypto/...",
    "amount_usdt": "1.50"
  }
}

Неоплаченный заказ отменяется через 30 минут (canceled), но отмена не останавливает уже отправленную on-chain транзакцию: если оплата придёт позже, заказ автоматически вернётся в payment_received и уйдёт в выдачу (вебхук order.status).

GETПолучение заказа

GET/api/partner/v1/orders/{public_id}

Возвращает заказ: статус, суммы и результат выдачи. Код ваучера (voucher_code) и данные eSIM (esim_code, esim) появляются после статуса completed.

pending_payment · sbp:

Response
{
  "order": {
    "public_id": "8af8e6b2-19f1-48d1-9e3e-67e9e8c0a814",
    "type": "voucher",
    "status": "pending_payment",
    "payment_method": "acquirer",
    "product_id": 777,
    "amount_pay_rub": 120.00,
    "created_at": "2026-05-06T09:31:00Z"
  },
  "payment": {
    "pay_url": "https://payment.example/pay?id=..."
  }
}

pending_payment · crypto:

Response
{
  "order": {
    "public_id": "8af8e6b2-19f1-48d1-9e3e-67e9e8c0a814",
    "type": "voucher",
    "status": "pending_payment",
    "payment_method": "crypto",
    "product_id": 777,
    "amount_pay_rub": 120.00,
    "created_at": "2026-05-06T09:31:00Z"
  },
  "payment": {
    "pay_url": "https://pay.example/crypto/...",
    "amount_usdt": "1.50"
  }
}

completed · voucher:

Response
{
  "order": {
    "public_id": "8af8e6b2-19f1-48d1-9e3e-67e9e8c0a814",
    "type": "voucher",
    "status": "completed",
    "product_id": 777,
    "amount_pay_rub": 120.00,
    "account": "player@example.com",
    "fields": {
      "login": "player@example.com",
      "server": "eu-west"
    },
    "voucher_code": "ABCD-EFGH-IJKL",
    "created_at": "2026-05-06T09:31:00Z",
    "paid_at": "2026-05-06T09:31:09Z"
  }
}

completed · eSIM:

Response
{
  "order": {
    "public_id": "8af8e6b2-19f1-48d1-9e3e-67e9e8c0a814",
    "type": "esim",
    "status": "completed",
    "product_id": 1042,
    "amount_pay_rub": 390.00,
    "esim_code": "LPA:1$consumer.rsp.world$XXXX",
    "esim": {
      "qr_code": "LPA:1$consumer.rsp.world$XXXX",
      "smdp_address": "consumer.rsp.world",
      "matching_id": "XXXX",
      "iccid": "8943108170000000000",
      "can_renew": true,
      "apple_link": "https://...",
      "android_link": "https://...",
      "sim_status": "Installed",
      "renewable_now": false,
      "renew_policy": "The package can be renewed after the validity period ends or all the data is consumed.",
      "packages": [
        {
          "name": "eSIM, 1GB, 7 Days, Turkiye, Unthrottled",
          "state": "in_use",
          "status": "Active",
          "initial_data_gb": 1,
          "remaining_gb": 0.4,
          "activated": true,
          "activated_at": "2026-07-11 12:00:00",
          "expires_at": "2026-07-18 12:00:00"
        }
      ]
    }
  }
}

Заказ отдаётся вместе с данными, с которыми он был создан: account — аккаунт получателя, fields — поля товара в том виде, в котором вы их прислали. Причина неуспеха в ответе не передаётся: если заказ закончился ошибкой, напишите нам с его public_id — разберём.

Для eSIM объект esim дополнительно содержит живой статус у поставщика: packages (пакеты с объёмом/остатком/сроком и корзиной state: in_use · assigned · completed · revoked), sim_status, renew_policy и renewable_now — можно ли продлить прямо сейчас. Данные подтягиваются в реальном времени; если поставщик недоступен, поля могут отсутствовать (статус заказа при этом не меняется).

GETСписок заказов

GET/api/partner/v1/orders

Список заказов партнёра. Параметры: limit (по умолчанию 50, макс 200), offset.

Response
{
  "orders": [
    {
      "public_id": "8af8e6b2-19f1-48d1-9e3e-67e9e8c0a814",
      "type": "voucher",
      "status": "completed",
      "product_id": 777,
      "amount_pay_rub": 120.00,
      "created_at": "2026-05-06T09:31:00Z",
      "paid_at": "2026-05-06T09:31:09Z"
    }
  ],
  "limit": 50,
  "offset": 0
}

Статусы заказов

pending_payment
status
ожидает оплаты
payment_received
status
оплата получена
processing_payout
status
идёт выдача
awaiting_confirmation
status
только manual: исполнитель выдал, ждём подтверждения покупателя (без ответа — авто через ~30 мин)
dispute
status
только manual: покупатель открыл спор по выдаче; чат продолжается, автоподтверждение не срабатывает
completed
status
выдан
failed
status
ошибка выдачи (оплата получена, товар не выдан)
canceled
status
отменён: не оплачен в срок либо оплата с баланса возвращена после ошибки выдачи
refunded
status
оплата возвращена покупателю
chargeback
status
платёж оспорен плательщиком в банке; к спору в чате ручного заказа не относится
creation_failed
status
не удалось создать оплату

Конечные статусы: completed, failed, canceled, refunded, chargeback, creation_failed — выдача закончена (после completed возможен только переход в refunded / chargeback). Остальные — заказ в работе: ждите вебхук или опрашивайте.

Ручная выдача (type: manual)

Часть товаров выдаёт исполнитель вручную: подписки с активацией на аккаунте, готовые аккаунты, покупки в сторонних магазинах. В каталоге у таких товаров type: "manual". После оплаты по заказу открывается чат с исполнителем: он уточняет данные (логин, код из письма), сообщает о выдаче, а покупатель подтверждает получение или открывает спор. Через API доступны все действия покупателя: чтение и отправка сообщений, подтверждение, открытие и снятие спора. Пишет ли ваш покупатель через ваш интерфейс или вы от его имени — для исполнителя это один участник чата (client).

Как это идёт по шагам

  1. POST /orders с type: "manual" — как обычный заказ. В fields передайте поля из карточки товара (fields в GET /products/{product_id}); чаще всего это только email покупателя.
  2. После оплаты заказ переходит в processing_payout и передаётся исполнителю — с этого момента работает GET …/messages. До оплаты он отвечает 409 chat_not_ready.
  3. Исполнитель пишет в чат. О каждом его сообщении (и о служебных сообщениях чата) приходит вебхук order.message, если задан webhook_url; ответы отправляйте через POST …/messages. Можно и просто опрашивать GET …/messages — не чаще раза в 5 секунд на заказ.
  4. Исполнитель отметил выдачу → статус awaiting_confirmation (вебхук order.status). Дальше три пути: POST …/confirm — заказ завершается; POST …/dispute — статус dispute, диалог продолжается; без ответа заказ подтверждается автоматически примерно через 30 минут.
  5. В споре: POST …/confirm — вопрос решён, заказ завершается; POST …/dispute/withdraw — спор снят, заказ снова в awaiting_confirmation (повторный вебхук этого статуса не приходит — статус есть в ответе запроса и в GET /orders/{public_id}). Если спор решён в пользу исполнителя, заказ завершается completed без вашего подтверждения.
  6. Спор решён в пользу покупателя или исполнитель отменил заказ на любом этапе → failed (вебхук). Деньги автоматически не возвращаются: оплату по СБП верните через POST …/refund (см. «Возврат заказа»), для карты и криптовалюты — через поддержку.

Результат выдачи (данные аккаунта, код, скриншот) приходит текстом в чат — отдельного поля voucher_code у ручных заказов нет. Обычно выдача занимает 5–15 минут, если покупатель отвечает исполнителю; ориентируйтесь на статусы, а не на время.

Задержки. Состояние у исполнителя и новые сообщения сверяются раз в минуту, поэтому статусы awaiting_confirmation / dispute / completed, поле manual_state, флаги chat.can_* и вебхуки могут отставать до минуты. Ваши собственные действия (confirm / dispute / withdraw) отражаются в статусе сразу. GET …/messages отдаёт переписку и состояние напрямую от исполнителя.

Создание ручного заказа

POST /api/partner/v1/orders
{
  "type": "manual",
  "product_id": 12034,
  "fields": { "email": "buyer@example.com" },
  "payment_method": "sbp",
  "redirect_url": "https://partner.example/return",
  "webhook_url": "https://partner.example/payli/webhook",
  "webhook_secret": "your-random-secret",
  "idempotency_key": "order-10008"
}

Ответ — как у остальных заказов: order со статусом pending_payment и payment.pay_url. После оплаты заказ уходит исполнителю. Если у товара есть обязательные поля, а вы их не прислали — 400 invalid_input с перечнем ожидаемых ключей. В account заказа попадает первое несекретное поле из fields (обычно email).

Чтение ручного заказа

GET /orders/{public_id} для ручного заказа дополнительно отдаёт manual_state и блок chat.

Response
{
  "order": {
    "public_id": "f80d95fb-2888-4108-8b6c-79704eb09b92",
    "type": "manual",
    "service": "xbox",
    "status": "awaiting_confirmation",
    "payment_method": "acquirer",
    "created_at": "2026-09-12T09:58:00Z",
    "paid_at": "2026-09-12T09:59:30Z",
    "manual_state": "fulfilled",
    "chat": {
      "available": true,
      "can_confirm": true,
      "can_dispute": true,
      "can_withdraw": false,
      "messages_url": "/api/partner/v1/orders/f80d95fb-2888-4108-8b6c-79704eb09b92/messages",
      "auto_confirm_in": "около 30 минут после выдачи, если покупатель не подтвердил и не открыл спор"
    },
    "product_id": 12034,
    "product_name": "Xbox Game Pass Ultimate — 1 месяц · активация на аккаунте",
    "account": "buyer@example.com",
    "fields": { "email": "buyer@example.com" },
    "amount_base_rub": 1290.00,
    "partner_commission_percent": 0.00,
    "partner_commission_rub": 0.00,
    "partner_fee_rub": 0.00,
    "amount_pay_rub": 1290.00
  }
}
manual_state
string
состояние у исполнителя: created · processing · waiting_customer (ждёт ответа в чате) · fulfilled (выдано) · dispute · completed · cancelled. Пустая строка — до оплаты и в первую минуту после передачи исполнителю.
chat.available
boolean
заказ передан исполнителю; при false чат отвечает 409 chat_not_ready
chat.can_confirm / can_dispute / can_withdraw
boolean
какие из POST …/confirm, …/dispute, …/dispute/withdraw сейчас пройдут; у завершённого заказа всегда false
chat.messages_url
string
путь к переписке
chat.auto_confirm_in
string
подсказка для человека о сроке автоподтверждения; не разбирать программно

Чат с исполнителем

GET/api/partner/v1/orders/{public_id}/messages
Response
{
  "order_public_id": "f80d95fb-2888-4108-8b6c-79704eb09b92",
  "status": "awaiting_confirmation",
  "manual_state": "fulfilled",
  "can_confirm": true,
  "can_dispute": true,
  "can_withdraw": false,
  "stale": false,
  "messages": [
    { "id": "m1", "sender_role": "system", "type": "system", "body": "Исполнитель принял заказ", "created_at": "2026-09-12T10:01:00Z" },
    { "id": "m2", "sender_role": "seller", "sender": "Исполнитель", "type": "text", "body": "Пришлите логин и пароль от аккаунта Microsoft", "created_at": "2026-09-12T10:02:10Z" },
    { "id": "m3", "sender_role": "client", "type": "text", "body": "login@example.com / ********", "created_at": "2026-09-12T10:05:44Z" },
    { "id": "m4", "sender_role": "seller", "sender": "Исполнитель", "type": "text", "body": "Подписка активирована, проверьте", "created_at": "2026-09-12T10:19:30Z" }
  ]
}

Переписка целиком, по времени. sender_role: seller — исполнитель, client — покупатель (ваши сообщения), system — служебные. manual_state и can_* здесь — актуальные на момент запроса. stale: true означает, что исполнитель сейчас недоступен и отдана сохранённая копия переписки. История хранится у нас и доступна после завершения заказа.

POST/api/partner/v1/orders/{public_id}/messages
Request
{ "body": "login@example.com / ********" }

Текст до 4000 символов, длиннее — 400 invalid_input. Ответ — { "message": { … } } с отправленным сообщением. У завершённого заказа — 409 order_closed.

Подтверждение, спор и снятие спора

POST/api/partner/v1/orders/{public_id}/confirm
Response
{ "ok": true, "status": "completing" }

Подтвердить получение. Доступно в awaiting_confirmation и dispute; иначе 409 confirm_failed. completing — подтверждение принято; заказ станет completed в течение минуты (вебхук order.status). Повтор для уже завершённого заказа отвечает 200 со status: completed.

POST/api/partner/v1/orders/{public_id}/dispute
Request · Response
{ "reason": "Подписка не активировалась" }

{ "ok": true, "status": "dispute" }

Открыть спор. reason необязателен (до 4000 символов). Доступно только в awaiting_confirmation; иначе 409 dispute_failed. Пока спор открыт, автоподтверждение не срабатывает.

POST/api/partner/v1/orders/{public_id}/dispute/withdraw
Response
{ "ok": true, "status": "awaiting_confirmation" }

Снять свой спор. Доступно только в dispute; иначе 409 withdraw_failed.

Права: чтение переписки — любым действующим токеном; POST-действия (сообщение, подтверждение, спор) — токеном с любым правом создания заказов, иначе 403 insufficient_scope.

Ошибки чата: 404 order_not_found — заказ не ваш или не существует; 400 not_chat_order — заказ не ручной; 409 chat_not_ready — заказ ещё не оплачен; 409 order_closed — заказ завершён, чат закрыт; 409 message_rejected — исполнитель не принял сообщение; 502 provider_error — исполнитель не ответил: сообщение не отправлено, действие не выполнено — повторите через несколько секунд (при чтении в этом случае приходит сохранённая копия со stale: true); 503 chat_unavailable — у заказа нет чата на нашей стороне, обратитесь в поддержку.

POSTВозврат заказа

POST/api/partner/v1/orders/{public_id}/refund

Возвращает покупателю оплату по заказу, который был оплачен платёжной ссылкой и закончился ошибкой выдачи. Возврат идёт на полную сумму платежа; комиссия эквайринга (fee.rub, fee.percent, по умолчанию 3 %) удерживается с вашего партнёрского баланса.

Условия

  • Токен с правом orders_refund; заказ принадлежит вам.
  • Заказ в статусе failed (409 invalid_state иначе).
  • На балансе хватает на комиссию возврата (409 insufficient_balance иначе; возврат не выполняется).
  • Платёж проведён эквайером с refund-API: СБП. Карта и СБП через эквайер без refund-API (409 not_refundable_acquirer_order) и криптовалюта (409 not_refundable_crypto_order) возвращаются через поддержку.

Повторный вызов для заказа в статусе refunded возвращает { "order": { … } } без fee; параллельный повтор — 409 refund_already_attempted. Отказ провайдера — 409 refund_provider_failed (можно повторить), неизвестный результат — 409 refund_status_unknown (в поддержку с public_id).

Request
{
  "reason": "manual_refund"
}
Response
{
  "order": {
    "public_id": "5f44b1b0-2f8d-45a9-82f5-4b0a26cda111",
    "status": "refunded"
  },
  "fee": {
    "rub": 30.00,
    "percent": 3.00
  }
}

GETБаланс

GET/api/partner/v1/balance

Возвращает текущий баланс партнёра и последние операции. Параметр limit — число операций (по умолчанию 50, максимум 200); применённое значение отдаётся в transactions_limit.

Response
{
  "balance_rub": 1520.45,
  "transactions": [
    {
      "id": 1912,
      "amount_rub": -97.50,
      "tx_type": "order_debit",
      "order_public_id": "7a85c2c1-3e9f-4ba2-91g6-5c1b27deb222",
      "created_at": "2026-05-06T09:12:44Z"
    }
  ],
  "transactions_limit": 50
}

Типы операций (tx_type)

invoice_topup
tx_type
пополнение баланса
invoice_refund
tx_type
списание при возврате пополнения
invoice_chargeback
tx_type
удержание по chargeback
invoice_chargeback_release
tx_type
снятие удержания
order_debit
tx_type
списание по заказу
order_debit_refund
tx_type
возврат списания по заказу
order_refund_fee
tx_type
комиссия при возврате заказа
accrual
tx_type
начисление
withdrawal
tx_type
вывод средств
adjustment
tx_type
корректировка

Вебхуки

Если в запросе создания заказа передан webhook_url, мы отправляем на него POST-уведомления о смене статуса и о новых сообщениях в чате ручного заказа. webhook_secret необязателен: если задан, каждое уведомление подписано.

Требования к webhook_url

Только https, порт 443 или 8443, публичный хост (частные и локальные адреса отклоняются), длина до 2048 символов; иначе 400 invalid_webhook_url.

События

order.status
event
смена статуса заказа: payment_received · awaiting_confirmation · dispute · completed · failed · canceled · refunded · chargeback · creation_failed
order.message
event
новое сообщение в чате ручного заказа от исполнителя (sender_role: seller) или служебное (system); ваши сообщения (client) событием не дублируются. Тело сообщения — в объекте message, message.message_id совпадает с id в GET …/messages

Статус processing_payout отдельным событием не приходит: он наступает сразу после payment_received. По каждому статусу событие order.status отправляется один раз за жизнь заказа: если статус повторился (после снятия спора заказ снова awaiting_confirmation), второго уведомления нет — актуальное состояние берите из ответа действия или GET /orders/{public_id}.

Payload · order.status

{
  "event": "order.status",
  "entity": "order",
  "public_id": "f80d95fb-2888-4108-8b6c-79704eb09b92",
  "order_public_id": "f80d95fb-2888-4108-8b6c-79704eb09b92",
  "status": "completed",
  "amount_rub": 500.00,
  "create_type": "api",
  "attempt": 1,
  "ts": "2026-05-21T07:09:43Z"
}

Payload · order.message

{
  "event": "order.message",
  "entity": "order",
  "public_id": "f80d95fb-2888-4108-8b6c-79704eb09b92",
  "order_public_id": "f80d95fb-2888-4108-8b6c-79704eb09b92",
  "amount_rub": 1290.00,
  "create_type": "api",
  "attempt": 1,
  "ts": "2026-09-12T10:19:31Z",
  "message": {
    "message_id": "m4",
    "sender_role": "seller",
    "sender": "Исполнитель",
    "type": "text",
    "body": "Подписка активирована, проверьте",
    "created_at": "2026-09-12T10:19:30Z"
  }
}
event
string
тип события
entity / public_id
string
что изменилось и его идентификатор (order_public_id — дубль для заказов)
status
string
новый статус; у order.message отсутствует
amount_rub
number
сумма в рублях с 2 знаками (500.00), не в копейках
create_type
string
канал создания заказа: api · widget · bot
attempt / ts
number / string
номер попытки доставки (с 1) и время этой попытки (RFC3339 UTC); у повтора они другие, поэтому другая и подпись
message
object
только order.message: message_id, sender_role, sender, type, body, created_at

Заголовки и подпись

Content-Type: application/json
X-Payli-Event-Id: 12345
X-Payli-Signature: sha256=<hmac>

X-Payli-Signature = sha256=<hex HMAC-SHA256(тело как получено, webhook_secret)>, hex в нижнем регистре; сравнивайте за константное время и до разбора тела. Если webhook_secret не передан — заголовка нет. X-Payli-Event-Id одинаков у всех попыток одного события.

Доставка и обработка

  • Доставлено = любой ответ 2xx в течение 8 секунд. Обрабатывайте асинхронно и отвечайте сразу.
  • Иначе повтор с растущей паузой: 30 с, 1, 2, 4, 8, 16, 32 мин — всего до 8 попыток, около часа. После этого событие больше не отправляется — сверяйте состояние через GET /orders/{public_id}.
  • Вебхук может прийти повторно — дедуплицируйте по X-Payli-Event-Id. Порядок доставки не гарантируется: сообщения сортируйте по message.created_at, статус сверяйте по GET.
  • Уведомления формируются по опросу состояния раз в 30 секунд; по ручным заказам состояние исполнителя сверяется раз в минуту, так что событие может прийти с задержкой до 1–2 минут. При быстрой смене статусов промежуточное событие может не прийти — конечные статусы приходят всегда.
  • Возврат покупателя на redirect_url не подтверждает оплату — подтверждение приходит вебхуком.
  • Для криптовалютных платежей статус меняется только после подтверждения платежа провайдером и нашей сверки суммы.

Ошибки

Ошибки возвращаются в JSON: { "error": "<code>", "message": "<optional>" }.

HTTPerrorКогда возникаетЧто делать
400invalid_jsonтело не JSON или в POST /orders передано неизвестное полеисправить тело запроса
400invalid_inputполя не прошли проверку: не те обязательные поля товара, тип товара не совпадает с type, пустой или длиннее 4000 символов текст сообщения; подробности в messageисправить поля по message и карточке товара
400invalid_typeнеизвестный type заказаsteam · topup · voucher · esim · manual
400invalid_product_idproduct_id не число или не передан там, где обязателенвзять id из каталога
400invalid_category_idcategory_id в пути не числовзять id из /categories
400invalid_public_idpublic_id в пути не UUIDпроверить идентификатор заказа
400invalid_payment_methodнеизвестный payment_methodsbp (acquirer) · card · crypto · balance
400invalid_partner_commission_percentpartner_commission_percent вне допустимого диапазонапроверить наценку
400invalid_total_commission_percentSteam: суммарная комиссия с вашей наценкой вне допустимого диапазонауменьшить partner_commission_percent
400amount_too_largeSteam: amount_pay_rub больше 1 000 000 ₽уменьшить сумму
400steam_login_invalidSteam: логин не найденпроверить account
400invalid_redirect_urlredirect_url не http(s)-URL или длиннее 2048 символовпроверить URL
400invalid_webhook_urlwebhook_url не https, порт не 443/8443, непубличный хост или длиннее 2048 символовhttps://host[:443|8443]/path на публичном домене
400invalid_webhook_secretwebhook_secret длиннее 512 символовсократить секрет
400invalid_idempotency_keyidempotency_key длиннее 128 символовсократить ключ
400renew_not_availableпродление eSIM запрошено, но текущий пакет ещё не закончился (трафик не израсходован и срок не истёк) либо прошло больше 30 дней после его окончанияпродлевать после окончания пакета и в течение 30 дней; смотреть esim.packages / esim.renewable_now
400renew_not_supportedeSIM не поддерживает продлениеоформить новую eSIM
400renew_not_resolvableне удалось определить eSIM по renew_iccid / renew_order_idпроверить идентификатор
400not_chat_orderчат запрошен у заказа не ручной выдачичат есть только у type: manual
401unauthorizedтокен не передан, неверен или отозванпроверить Authorization: Bearer
403insufficient_scopeу токена нет права на действие: создание заказа (нужен scope создания для выбранного payment_method) или POST-действие в чате ручного заказазапросить расширение прав токена
403forbiddenу токена нет права orders_refund (возврат) или прав на инвойсызапросить расширение прав токена
404order_not_foundзаказ не существует или принадлежит другому партнёрупроверить public_id
404product_not_foundтовар не найден или скрытпроверить product_id по каталогу
404category_not_foundкатегория не найденапроверить category_id
405method_not_allowedметод не поддерживается этим путёмпроверить метод (GET/POST)
409request_in_progressзапрос с тем же idempotency_key ещё выполняетсяповторить после Retry-After
409insufficient_balanceна балансе партнёра не хватает: на оплату заказа с баланса или на комиссию возвратапополнить баланс
409invalid_stateвозврат: заказ не в статусе failed; инвойс: статус не позволяет операциюпроверить статус
409chat_not_readyручной заказ ещё не оплачен и не передан исполнителюдождаться processing_payout
409order_closedручной заказ уже завершён: чат и действия закрытыповтор confirm у completed-заказа отвечает 200
409confirm_failedисполнитель ещё не отметил выдачу — подтверждать нечегодождаться awaiting_confirmation (chat.can_confirm)
409dispute_failedспор нельзя открыть: выдача не отмечена или спор уже открытсверить chat.can_dispute
409withdraw_failedпо заказу нет открытого спорасверить chat.can_withdraw
409message_rejectedисполнитель не принял сообщение: чат по заказу закрытсмотреть статус заказа
409refund_not_supportedплатёж проведён провайдером без refund-APIвозврат через поддержку
409refund_already_attemptedвозврат по заказу уже запрошендождаться статуса refunded или обратиться в поддержку
409refund_provider_failedпровайдер отказал в возвратеповторить позже или обратиться в поддержку
409refund_status_unknownрезультат возврата у провайдера неизвестенобратиться в поддержку с public_id
409not_refundable_acquirer_orderзаказ оплачен через эквайер без refund-API (СБП или карта)возврат через поддержку
409not_refundable_crypto_orderзаказ оплачен криптовалютойвозврат через поддержку
413payload_too_largeтело запроса больше лимита (1 МБ для заказов, 32 КБ для сообщений чата)сократить запрос
422invalid_amountSteam: зачисляемая сумма вне min_rub…max_rub сервисаизменить amount_pay_rub
429rate_limitedпревышен лимит запросов (GET 600/мин, POST 60/мин на токен)повторить после Retry-After
429too_many_concurrent_requestsбольше 8 одновременных запросов на токенповторить после Retry-After
500server_errorвнутренняя ошибка (также коды failed_to_*)повторить; если повторяется — в поддержку с public_id
502provider_errorисполнитель или поставщик не ответил: сообщение не отправлено, действие не выполнено, история не загруженаповторить через несколько секунд
502provider_bad_responseпоставщик вернул непонятный ответ при создании заказаповторить тот же запрос с тем же idempotency_key
502payment_url_missingплатёж создан, но провайдер не вернул pay_urlповторить тот же запрос с тем же idempotency_key
503product_unavailableтовара нет у поставщика: закончился, снят с продажи, у ручной выдачи нет свободных исполнителей (в части сценариев приходит как 400 или 409)повторить позже или выбрать другой товар
503service_unavailableсервис (Steam) временно недоступенповторить позже
503card_unavailableоплата картой запрошена, но провайдер карт недоступениспользовать sbp или повторить позже
503crypto_unavailableоплата криптовалютой запрошена, но провайдер недоступениспользовать sbp или повторить позже
503chat_unavailableу заказа нет чата на нашей стороне (ошибка настройки, повторы не помогут)обратиться в поддержку
503fx_rate_unavailableнет курса валюты для расчёта ценыповторить позже
503commission_unavailableвременно недоступны правила комиссийповторить позже
503payment_init_recovery_pendingзаказ создан, но pay_url ещё дозаписываетсяповторить тот же запрос с тем же idempotency_key через пару секунд
503idempotency_unavailableвременный сбой слоя идемпотентностиповторить позже
503server_busyперегрузка сервераповторить после Retry-After