Правила размещения рекламы (откроются в новой вкладке)
/ DEVELOPERS
Кабинет

PIXORADS / DEVELOPER DOCUMENTATION

SDK и API Pixora Ads для разработчиков

Монетизация площадок и отслеживание результатов веб-кампаний: инструкции, рабочие примеры кода и диагностика в одном месте.

PIXORADS / DATA FLOW01 — 06
  1. 01Ваша площадка
  2. 02Ваш сервер
  3. 03PixorAds API
  4. 04Объявление
  5. 05Проверенное действие
  6. 06Доход площадки

Ключ остаётся на вашем сервере. PixorAds проверяет завершённое действие до начисления дохода площадке.

01 / НАЧАЛО РАБОТЫ

Как устроена монетизация

#

Выберите форматы при подключении площадки и передайте их на модерацию. Статика и видео — виды креатива; native, interstitial и rewarded — сценарии показа. Отдельного метода showVideo() нет: сервер подбирает подходящий креатив.

МетодГде появляется рекламаНаграда зрителю
showNative()Карточка со статикой или видео в вашем контейнереНет
showInterstitial()Экран поверх вашего Mini App; закрытие доступно сразуНет
showRewarded()Экран поверх Mini App после добровольного нажатияПосле подтверждённого просмотра; внутренний бонус — через ваш сервер

В Mini App реклама работает внутри интерфейса партнёра. Переход по рекламной кнопке добровольный; после закрытия рекламы пользователь возвращается к вашему экрану. В ботах основной формат — сообщение после полезного ответа с оплатой за переход; в каналах — рекламный пост с CPM или CPC. Кнопка ведёт к рекламодателю. JavaScript SDK предназначен для Mini App, а не сообщений.

Доход площадки и бонус зрителю — разные вещи. Для монетизации без наград выберите native или interstitial. Обычный показ учитывается после видимости не менее 50% креатива в течение непрерывной секунды в активном окне; видео должно воспроизводиться. Итог подтверждает сервер с учётом лимитов, бюджета и доступности кампании.

Для новой интеграции используйте SDK 1.8.1: init() и выбранный метод показа. Старые create()/mount() сохранены для совместимости.

02 / НАЧАЛО РАБОТЫ

Быстрый старт

#
  1. Откройте «Монетизация → Рекламная сеть» и выберите Mini App, бота или публичный канал.
  2. Укажите название, Telegram-ссылку и описание с тематикой и аудиторией. Для Mini App используйте ссылку бота или прямую ссылку t.me/bot/appname. Выберите native, interstitial и/или rewarded до модерации. Место размещения опишите в тексте: отдельного поля для него нет.
  3. Подтвердите управление: токеном бота для ботов/Mini Apps; правами администратора для канала. Проверка токена подтверждает управление ботом, а место рекламы проверяет модератор.
  4. Для Mini App и бота после одобрения создайте API-ключ и храните его только на сервере. Для автоматических постов в канале отдельный сервер и API-ключ не нужны: сохраните настройки публикаций и проверьте права бота.
  5. Запустите тест ниже, подключите свой сервер и SDK либо подготовьте объявление в кабинете. Реальные объявления доступны при активной площадке и подходящем спросе; подключение не гарантирует загрузку рекламы или доход.
03 / НАЧАЛО РАБОТЫ

Посмотреть на примере

#

Демонстрационный @pixorAds_networkbot показывает весь путь пользователя: открытие Mini App, запрос объявления через сервер и показ выбранного формата поверх интерфейса Mini App. Его можно открыть до подключения собственной площадки.

  1. Откройте бота и запустите Mini App. Демонстрационный сервер подтверждает Telegram-сессию через /api/v1/ad-network/demo/session.
  2. SDK обращается к /api/v1/ad-network/demo/offer на том же origin. Секретный ключ площадки остаётся только на сервере.
  3. Если подходящего оплаченного объявления нет, демонстрационное приложение показывает ознакомительное видео. Это собственный пустой экран площадки, не рекламный просмотр: за него не списываются средства и не начисляются награды или доход.
Демо: запуск SDK после проверки Telegram
// Demo only: run after loading pixorads-publisher.js inside Telegram.const session = await fetch("/api/v1/ad-network/demo/session", {  method: "POST",  credentials: "same-origin",  headers: { "Content-Type": "application/json" },  body: JSON.stringify({ init_data: window.Telegram.WebApp.initData })});if (!session.ok) throw new Error("Telegram session could not be verified");const { csrf_token, publisher_id } = await session.json();const placement = window.PixorAdsPublisher.init({  element: document.getElementById("pixorads"),  endpoint: "/api/v1/ad-network/demo/offer",  csrfToken: csrf_token,  publisherId: publisher_id,  language: "ru"});await placement.showNative();
04 / ИНТЕГРАЦИЯ

Mini App · JavaScript / React

#

Добавьте скрипт один раз в HTML. В endpoint укажите адрес своего сервера на том же origin. API-ключ в браузер не передаётся. До init() передайте Telegram.WebApp.initData на свой backend: он должен проверить подпись и срок действия, создать сессию, а при cookie-авторизации вернуть CSRF-токен для параметра csrfToken. Публичный publisherId возьмите в карточке площадки. Примеры ниже — native без награды; для других сценариев откройте «Методы показа». В React передайте CSRF-токен пропсом и вызывайте destroy() при удалении компонента.

HTML
<!-- Render this page AFTER your backend verifies the Telegram session. --><!-- Your backend inserts its session CSRF token into this meta tag. --><meta name="csrf-token" content="YOUR_SESSION_CSRF_TOKEN"><script src="https://pixora-ads.com/sdk/pixorads-publisher.js"></script><div id="pixorads"></div><script type="module">  const placement = window.PixorAdsPublisher.init({    element: document.getElementById("pixorads"),    endpoint: "/api/pixorads/offer",    csrfToken: document.querySelector('meta[name="csrf-token"]').content,    publisherId: "YOUR_PUBLIC_MINIAPP_PUBLISHER_ID",    trackAudience: false,    personalized: false,    language: "ru"  });  const state = await placement.showNative();  if (state.status === "error") console.warn(state.code);  // empty: no ad available. Continue the app; do not retry in a loop.  // On screen removal: placement.destroy();</script>
05 / ИНТЕГРАЦИЯ

Методы показа

#
МетодГде появляется рекламаНаграда зрителю
showNative()Карточка со статикой или видео в вашем контейнереНет
showInterstitial()Экран поверх вашего Mini App; закрытие доступно сразуНет
showRewarded()Экран поверх Mini App после добровольного нажатияПосле подтверждённого просмотра; внутренний бонус — через ваш сервер

Выберите один пример ниже. Скрипт SDK уже должен быть загружен, а ваш сервер — проверить Telegram-сессию. Замените publisherId на публичный ID площадки; csrfTokenFromYourSession — CSRF-токен вашей сессии, не API-ключ. /api/pixorads/offer — маршрут, который вы создаёте на своём сервере.

native
// Prerequisites: SDK loaded, your session verified, <div id="ad-slot"></div>.const ads = window.PixorAdsPublisher.init({  publisherId: "YOUR_PUBLIC_MINIAPP_PUBLISHER_ID",  endpoint: "/api/pixorads/offer",  csrfToken: csrfTokenFromYourSession,  element: document.getElementById("ad-slot"),  language: "ru",  trackAudience: false, // Enable explicitly if you measure app activity.  personalized: false});const state = await ads.showNative();if (state.status === "empty") {  // No matching ad. Continue your app normally; try later.} else if (state.status === "error") {  console.warn("Ad unavailable:", state.code);}// ready means rendered, NOT a paid impression.// Keep ads alive while the card is visible.// When removing this screen: ads.destroy();

Что возвращают методы

ВызовРезультат
init(options)Создаёт контроллер; рекламу не показывает. Ошибки параметров выбрасывает сразу. По умолчанию включает trackAudience.
showNative()Promise<PublisherState>: ready, empty или error с code. ready означает отрисовку карточки, не оплату показа.
showInterstitial() / showRewarded()Promise завершается при закрытии окна. Ошибки и no_fill отклоняют Promise — используйте try/catch. Досрочное закрытие: completed:false.
getState()Последнее событие SDK. Не финансовый статус и не баланс.
trackVisit()Promise<{recorded:boolean}>. Нет publisherId, подписанных Telegram-данных, есть test:true или ошибка сети — recorded:false.
destroy()Отменяет запрос, удаляет карточку/окно и слушатели. Контроллер больше не используйте; при новом экране создайте новый.
PublisherShowResult
{  shown: true,              // Viewer handshake completed; NOT proof of payment  completed: false,         // true only for completed rewarded viewing  impression_confirmed: true // Ordinary viewer confirmation, when available  // receipt, session_id: present when supplied by the viewer  // test:true => {shown:false, completed:false, test:true}; no overlay or payout}

Одновременно открывается только одно рекламное окно. Не запускайте showNative() и полноэкранный метод параллельно на одном контроллере. При no_fill продолжайте работу приложения; не подменяйте обещанную награду обычной рекламой. После показа не вызывайте destroy() до закрытия окна или удаления экрана.

06 / ИНТЕГРАЦИЯ

Награды и подтверждение

#

Для showNative() и showInterstitial() этот раздел не нужен: пользовательскую награду выдавать не требуется. В rewarded PixorAds подтверждает просмотр; монеты, жизни или другой дополнительный бонус вашего приложения начисляет ваш backend.

  1. Получите receipt из результата showRewarded() после закрытия окна. Это непрозрачное подтверждение, а не сумма награды.
  2. Передайте receipt своему авторизованному серверу. Он вызывает reward/verify с ключом этой площадки и сверяет telegram_id с пользователем своей сессии.
  3. Одной транзакцией сохраните уникальный receipt_id и выдайте настроенный на сервере бонус. При повторной отправке верните прежний результат без второго начисления.
reward/verify · только ваш backend
// Inside YOUR authenticated, CSRF-protected reward route.// req.user.telegramId must come from a verified session, never the request body.const response = await fetch("https://pixora-ads.com/api/v1/ad-network/publisher-api/reward/verify", {  method: "POST",  headers: {"Content-Type": "application/json", "X-PixorAds-Key": process.env.PIXORADS_PUBLISHER_KEY},  body: JSON.stringify({receipt: req.body.receipt}),  signal: AbortSignal.timeout(8000)});if (!response.ok) throw new Error("Reward not verified");const proof = await response.json();if (!proof.rewarded || String(proof.telegram_id) !== String(req.user.telegramId)) {  throw new Error("Wrong viewer");}// YOUR database transaction (required; not implemented by this snippet):// 1. Insert (receipt_id, your_user_id) into a ledger with UNIQUE(receipt_id).// 2. On a new row, grant YOUR server-configured internal bonus.// 3. On duplicate, return the existing result for the same user.// Commit both operations together, then return 2xx to the browser.// Never take a reward amount from req.body or credit proof.reward as app coins.

Ответ: rewarded, receipt_id, session_id, publisher_id, telegram_id, operation_id, reward, currency, completed_at. Receipt действует 7 дней и привязан к площадке. Проверка не переводит деньги. При недоступности сервера повторяйте отправку того же receipt; не заставляйте пользователя смотреть рекламу заново.

Когда нужен onReward

onReward({receipt, session_id}) вызывается сразу после подтверждения просмотра, пока рекламное окно ещё открыто. Это альтернатива обработке receipt после закрытия. SDK не ждёт завершения вашего async callback и не повторяет его при ошибке: обработайте ошибку и повторную отправку сами. Если используете оба пути, единая проверка receipt_id на сервере обязательна. События onEvent и переход по CTA не разрешают начислять бонус.

Суммы API — целые внутренние единицы: XTR / 1000 = ★; RUB / 1000 = ₽; USD / 1 000 000 = $. Например, reward:70 при currency:XTR — это 0,07 ★. В offer viewer_reward/viewer_currency — награда зрителю; reward и publisher_amount — суммы в валюте кампании. publisher_income — оценка дохода площадки в USD, окончательная сумма фиксируется после подтверждения; ни одна из них не задаёт число монет в вашем приложении.

07 / ИНТЕГРАЦИЯ

Сервер и API-ключ

#

Ваш backend авторизует пользователя, ограничивает частоту запросов и запрашивает объявление у PixorAds. Ответ передаётся виджету как JSON. Для одного логического запроса используйте один Idempotency-Key при повторных попытках, для нового объявления — новый ключ.

Серверный запрос
curl https://pixora-ads.com/api/v1/ad-network/publisher-api/offer \  -H "X-PixorAds-Key: $PIXORADS_PUBLISHER_KEY" \  -H "Idempotency-Key: unique-logical-request-id" \  -H "Content-Type: application/json" \  -d '{"language":"ru","format":"native"}'
Node.js / Express
// Node.js 22+ / Express. Keep this code on YOUR SERVER.// app, requireYourSession, verifyYourCsrf and yourRateLimit// belong to your app. Implement them before exposing the route.import { randomUUID } from "node:crypto";app.post("/api/pixorads/offer", requireYourSession,  verifyYourCsrf, yourRateLimit, async (req, res) => {    res.set("Cache-Control", "no-store");    const language = req.body?.language ?? "en";    const context_token = req.body?.context_token ?? "";    // Legacy create().mount() omits format; preserve the API's auto default.    const format = req.body?.format ?? "auto";    if (!["ru", "en"].includes(language)) return res.status(400).json({error:{code:"invalid_language"}});    if (typeof context_token !== "string" || context_token.length > 2048) return res.status(400).json({error:{code:"invalid_viewer_context"}});    if (!["auto", "native", "interstitial", "rewarded"].includes(format)) return res.status(400).json({error:{code:"invalid_format"}});    // Reuse this ID if you retry this upstream request.    const requestId = randomUUID();    try {      const response = await fetch(        "https://pixora-ads.com/api/v1/ad-network/publisher-api/offer",        {          method: "POST",          headers: {            "Content-Type": "application/json",            "X-PixorAds-Key": process.env.PIXORADS_PUBLISHER_KEY,            "Idempotency-Key": requestId          },          body: JSON.stringify({ language, context_token, format }),          signal: AbortSignal.timeout(8000)        }      );      const retryAfter = response.headers.get("Retry-After");      if (retryAfter) res.set("Retry-After", retryAfter);      const payload = await response.json();      // Preserve structured error.code so the SDK can show useful diagnostics.      res.status(response.status).json(payload);    } catch {      res.status(503).json({ error: { code: "upstream_unavailable" } });    }  });

При замене или отзыве ключа старый ключ и созданные им ссылки перестают работать. Обновите переменную окружения и создайте новые размещения. Условия начатого сеанса сохраняются, но новые действия просмотра проверяют текущий статус и версию ключа.

08 / ИНТЕГРАЦИЯ

Боты · реклама в переписке

#

Основной формат для ботов — реклама после полезного ответа с оплатой за подтверждённый переход. Токен BotFather остаётся на сервере владельца. Отдельная регистрация зрителя не нужна.

Инструкция, SDK и бесплатная тестовая отправка ↗

Настройки, согласование объявлений, ставки и история дохода — в карточке бота, раздел «Реклама в переписке». Просмотры с наградой остаются дополнительным форматом с отдельной интеграцией.

09 / ИНТЕГРАЦИЯ

Каналы · CPM и CPC

#

Добавьте публичный канал; ваш аккаунт и бот PixorAds должны быть администраторами. После модерации проверьте права на публикацию и удаление постов. В настройках канала выберите оплату просмотров (CPM, по умолчанию) или подтверждённых переходов (CPC). Задайте минимальный доход и лимит результата на пост. Автопубликация или согласование доступны в обоих режимах.

CPM оплачивает счётчик Telegram за первые 24 часа, включая пересылки. Это не уникальный охват или досмотр. CPC оплачивает подтверждение перехода кнопкой на коротком экране без регистрации; просмотры, предпросмотры и повторные переходы одному рекламодателю в каналах за 24 часа бесплатны. Отпечаток браузера — сочетание IP и User-Agent, а не доказательство уникального человека. Награды читателю нет.

Расчёт после 24 часов, затем удержание по условиям кампании. Курс, сумма, оплаченные просмотры или переходы и срок освобождения дохода видны в истории постов. Ставки и доли каналов регулируются отдельно от Mini App; действующие условия показаны в разделе дохода площадок.

10 / ИНТЕГРАЦИЯ

Оффервол · задания и бонусы

#

Демо-витрина · SDK 1.3.2

Попробуйте 10 типов заданий без регистрации площадки. Отдельный DemoClient возвращает учебный каталог и имитирует проверку в памяти браузера. Он не обращается к финансовому API, не выдаёт receipt и не подтверждает реальные награды. Это демонстрация интерфейса, а не тест вашей серверной интеграции.

Открыть демо-витрину →
JavaScript · DemoClient
// Load /sdk/pixorads-offerwall.js first.const demo = new PixorAdsOfferwall.DemoClient();const { items } = await demo.catalog();const attempt = await demo.start(items[0].id, "demo-1");await demo.check(attempt.id); // demo_completed; paid=false; no receiptdemo.reset();

Offerwall 1.3 · Подключение, тест без списаний, бонусы и диагностика — в одном кабинете.

Открытие задания и отчёты · SDK 1.3

После start вызовите client.open(attemptId) и откройте возвращённый url. Этот шаг включает наблюдение за реакцией или голосом и создаёт защищённую ссылку для сайта. Исходный URL рекламодателя для проверки не подходит. Для бота можно открыть hosted_url: пользователь продолжит ту же попытку на готовом экране.

Отчёт: client.report(id), submitReport(id, {version, body, images, draft}, key); ответы о товаре — {version, answers}. Скриншоты — uploadReportImage(id, base64), до 3 изображений. Обжалование — appeal(id, {version, reason}, key). Используйте один ключ при повторе того же запроса. report_updated сообщает статус и срок, но никогда не разрешает выдачу бонуса. Начисляйте только по reward_eligible с проверкой на сервере.

Один каталог заданий: готовый экран, компонент Mini App и API для собственного интерфейса или Telegram-бота. Поддерживаются подписки на публичные каналы и вступления в группы. Для проверки бот PixorAds должен быть администратором целевого чата. Также доступны первый запуск бота и действия в Mini Apps с подтверждением сервера рекламодателя. Для них требуется успешный тест интеграции. Также доступны реакции в публичных группах, неанонимные опросы PixorAds, новые Premium-бусты, переходы на сайты, сёрфинг и задания с отчётами, включая маркетплейсы. Доступность сайтов зависит от настроек сервиса. Отдельные форматы покупок и многоэтапные задания пока не поддерживаются.

1. Подготовьте площадку

В разделе «Мои площадки» добавьте площадку, подтвердите управление и дождитесь модерации. В блоке «Задания и бонусы» выберите награду, настройте уведомления и включите приём заданий. Партнёрский трафик получает только кампании, для которых рекламодатель явно включил этот источник.

Какие задания показывать

В настройках Offerwall выберите «Типы заданий»: например, только подписки, действия в Mini Apps или задания с отчётом. По умолчанию выбраны все 10 поддерживаемых типов. Если снять все отметки, новые задания не будут предлагаться. Наличие предложений также зависит от кампаний, настроек сервиса и пользователя.

Выбор применяется на сервере ко всем способам подключения: готовому экрану, SDK, компоненту и API для бота. Следующее обновление каталога учтёт настройки без изменения кода интеграции. Начатые задания остаются в «Моём прогрессе»: их можно выполнить, проверить и получить согласованную награду, даже если тип больше не принимается.

Ответ client.catalog() содержит серверный список options.task_types, доступные items и history начатых заданий. В старых ответах поле может отсутствовать. Не отбирайте history по options.task_types и не передавайте собственный список в Client, connect или start: настройки меняет только владелец площадки в кабинете.

  • Награда PixorAds: пользователь получает денежную награду после регистрации; площадка — долю комиссии платформы. Стартовая доля: 50% комиссии.
  • Награда площадки: пользователь получает ваши монеты или доступ, а площадка — долю цены результата. Стартовая доля: 80%. Вы самостоятельно начисляете внутренние бонусы.

Доли настраиваются и фиксируются для задания при старте. Доход площадки учитывается в USD по зафиксированному курсу и удерживается после окончательной проверки (по умолчанию 24 часа). Срок сохранения подписки показывается отдельно. Подтверждение действия ещё не означает доступность денег к выводу.

Реферальные начисления по заданиям оплачиваются из оставшейся доли платформы после выплаты паблишеру. Они не уменьшают согласованную награду пользователя или доход площадки.

2. Выберите подключение

Перед включением откройте «Монетизация → Offerwall → Подключение». Сохраните настройки, создайте учебное задание и завершите его. Событие содержит test=true, user_id=null и нулевой денежный доход. Его нельзя начислять реальному пользователю. При изменении настроек тест нужно повторить.

С webhook тест приходит на сохранённый адрес с обычной HMAC-подписью. Без webhook получите GET /publisher-api/tests. Сервер подтверждает обработку через POST /publisher-api/tests/{conversion_id}/ack с X-PixorAds-Key. HTTP 2xx сам по себе не подтверждает начисление бонуса. Учебное событие доступно 24 часа.

Готовый экран: скопируйте Telegram-ссылку из настроек оффервола. Она подходит для Mini Apps, ботов и постов каналов. Источник сохраняется; площадка не становится реферером автоматически.

HTML
<script src="https://pixora-ads.com/sdk/pixorads-offerwall.js"></script><pixorads-task publisher-id="YOUR_PUBLISHER_UUID" theme="light"></pixorads-task>

Компонент подключается внутри Telegram Mini App с подписанным initData. Используется идентификатор бота, подтверждённого для площадки. API-ключ в браузер передавать нельзя. Цветовая тема — light/dark; высота — CSS-переменная --pixorads-offerwall-height.

JavaScript
const client = new PixorAdsOfferwall.Client({ publisherId: "YOUR_PUBLISHER_UUID", telegramInitData: Telegram.WebApp.initData });// Show terms and obtain consent before connect().const { items, history, options } = await client.connect({ accepted: true });// items already honor the publisher's task_types on the server.// Show an empty state when items is empty; always render history separately.// Call only when the user chooses a task from items.async function startSelectedTask(campaignId, retryKey) {  const task = await client.start(campaignId, retryKey);  const destination = await client.open(task.id);  return { task, url: destination.url };}// Open the returned protected URL; offer a separate Check button.async function checkTask(attemptId) {  return client.check(attemptId);}// Do not grant a reward based on a JavaScript event.

База API — https://pixora-ads.com/api/v1/offerwall: добавляйте к ней сокращённые пути /viewer/... и /publisher-api/... из этого раздела. В Client({baseUrl}) передавайте только HTTPS-origin, например https://pixora-ads.com, без пути, query или hash.

При уходе с экрана вызовите client.disconnect(): запросы отменятся с кодом disconnected, viewer-токен будет удалён. Перед новой работой получите согласие и подключитесь заново. После потери ответа перечитайте историю; повторяйте start или отправку отчёта с исходным ключом, поскольку сервер мог уже сохранить запрос. Автоматического повтора в SDK нет.

3. API для бота

Готовые примеры: команды /bonus и /bonusbalance, кнопки выполнения и проверки, повторная сверка после перезапуска, тест подключения и защита от повторных бонусов. Работают через опрос API, без публичного webhook.

В начале каждого файла — команда запуска и переменные окружения. В примерах бонусы записываются в отдельный SQLite-баланс. Для вашей игровой валюты перенесите начисление и UNIQUE(conversion_id) в одну транзакцию вашей БД; ACK отправляйте только после её фиксации. Не запускайте второй polling-процесс поверх работающего бота: перенесите обработчики в его приложение.

Сервер бота использует отдельный ключ площадки в заголовке X-PixorAds-Key. Сначала запросите сессию по Telegram ID. Если verified=false, покажите verification_url: пользователь один раз подтверждает Telegram-аккаунт и условия на готовом экране. Нельзя подставлять произвольный ID и получать за него деньги. Подтверждение действительно сутки; серверные запросы этот срок не продлевают.

Python · httpx
import os, httpxBASE = "https://pixora-ads.com/api/v1/offerwall"KEY = os.environ["PIXORADS_KEY"]async def get_tasks(telegram_user_id):    async with httpx.AsyncClient(timeout=20) as api:        r = await api.post(BASE + "/publisher-api/session",            headers={"X-PixorAds-Key": KEY},            json={"telegram_id": telegram_user_id})        r.raise_for_status()        session = r.json()        if not session["verified"]:            return session  # Show verification_url as a button.        token = session["viewer_token"]        r = await api.get(BASE + "/viewer/catalog",            headers={"Authorization": "Bearer " + token})        r.raise_for_status()        return {"verified": True, "token": token, **r.json()}# Call only after the user selects a task.async def start_task(token, campaign_id, retry_key):    async with httpx.AsyncClient(timeout=20) as api:        r = await api.post(BASE + "/viewer/start",            headers={"Authorization": "Bearer " + token,                     "Idempotency-Key": retry_key},            json={"campaign_id": campaign_id})        r.raise_for_status()        return r.json()# Send title, reward and conditions. POST /viewer/attempts/{id}/open# with the viewer token and use its url; for reports use hosted_url.# A separate Check callback POSTs /viewer/attempts/{task_id}/check.# Keep tokens on your server and bind callbacks to the same user.# Store retry_key before the request and reuse it on retries.# If items is empty, continue the ordinary bot flow.

У пользователя один отдельный слот коротких заданий и до пяти одновременно взятых заданий с отчётом: карты, маркетплейсы и расширенные задания учитываются суммарно. Проверка отчёта и ожидание доставки не занимают лимит. Уже взятые работы, вернувшиеся на доработку или из доставки, сохраняются. Пока лимит достигнут, новые выдачи недоступны. Каталог не резервирует бюджет, повторный запуск той же кампании на другой площадке не создаёт вторую выплату.

При старте обрабатывайте HTTP 409 с кодом task_assignment_limit: достигнут лимит заданий с отчётом. task_quick_assignment_limit означает занятый слот короткого задания. Покажите понятное сообщение и сохраните карточку; не переключайте пользователя на другое выполнение автоматически. Эти ошибки не создают новую выдачу или резерв. После освобождения места повторите старт. При сетевой ошибке повторяйте тот же ключ команды.

4. Начисляйте бонус только на сервере

Настройте публичный HTTPS webhook. Секрет подписи находится в настройках оффервола. Подпись X-PixorAds-Signature = HMAC-SHA256(secret, timestamp + '.' + исходные байты тела); timestamp — X-PixorAds-Timestamp. Проверяйте подпись постоянным временем и допустимое отклонение времени (например 5 минут). Не пересобирайте JSON перед проверкой.

  • completed — действие обнаружено, идёт удержание подписки. Ранний бонус допустим только при заранее включённом режиме advance;
  • qualified — окончательная проверка пройдена: можно один раз начислить внутренние бонусы;
  • revoked — проверка удержания не пройдена, выплаты нет;
  • paid — доход площадки освобождён из удержания.

Перед начислением запросите GET /publisher-api/rewards/{conversion_id}. Сверьте telegram_id, reward_mode=partner, test=false и reward_eligible=true. Начислите reward_units из этого ответа один раз. После фиксации своей транзакции отправьте POST /publisher-api/rewards/{conversion_id}/ack с {reference: 'идентификатор вашего начисления'}. Повторяйте ACK с тем же reference при сетевой ошибке. Это подтверждение отражается у пользователя и в аналитике; движение денег PixorAds оно не запускает.

5. Гибкие бонусы

Можно задать фиксированное число бонусов либо курс «бонусов за $1 дохода площадки». Количество округляется вниз, применяется ограничение минимума и максимума. Акционный множитель действует до указанного срока. Всё фиксируется при старте; цена рекламодателя и денежное распределение не меняются. Предварительный бонус в каталоге может измениться до старта при смене настроек или курса.

По умолчанию бонус выдаётся после окончательной проверки. В режиме advance площадка выдаёт свой бонус после первой проверки на собственный риск: если пользователь не сохранит подписку, доход площадки отменится. PixorAds не списывает уже использованные внутренние бонусы. Денежную награду PixorAds и освобождение дохода это не ускоряет.

Ключ начисления — conversion_id. Сохраняйте его и награду в одной транзакции своей БД с UNIQUE-ограничением. event_id защищает от повторной обработки события. Уведомления могут приходить повторно и не по порядку. Отвечайте 2xx только после сохранения. До 12 попыток доставки; причины ошибок и ручной повтор — в кабинете площадки.

Если используете receipt из окончательного результата, передайте его своему серверу: POST /publisher-api/reward/verify с ключом площадки. Сверьте telegram_id и conversion_id с пользователем своей системы. Receipt не заменяет защиту от повторного начисления. Без webhook периодически проверяйте историю и окончательные результаты.

Рекламодателю: запуск бота и действия в Mini Apps

Создайте кампанию на запуск бота или Mini App. В настройках откройте мастер Offerwall 1.2: действие → подключение → тест → запуск. Укажите точное условие, серверное название события, срок выполнения и период проверки. Для ботов оплачивается только первый запуск; в Mini App можно разрешить существующих пользователей. Каждый результат оплачивается один раз.

После сохранения серверной цели кампания исключается из обычной выдачи. После теста выберите «Только партнёры» в источниках. Бюджет, модерация и согласованная цена кампании продолжают действовать. Цель и сроки задаются в черновике до отправки на модерацию. Для изменения одобренных условий создайте новую кампанию.

Ссылка содержит start=px_… для бота или startapp=px_… для Mini App. Привяжите токен к Telegram ID из настоящего обновления бота либо проверенного initData. Не доверяйте ID и факту выполнения из браузера. Открытие ссылки и проверка initData сами по себе не подтверждают выполнение цели.

POST /api/v1/offerwall/actions/postback
{  "campaign_id": "CAMPAIGN_UUID",  "attempt_token": "px_ATTEMPT_TOKEN",  "event_id": "your-stable-event-id",  "telegram_id": 123456789,  "event_name": "tutorial_complete",  "occurred_at": "2026-10-06T10:05:00Z",  "first_seen_at": "2026-10-06T10:01:00Z",  "status": "completed",  "reason": null}

Подпись: X-PixorAds-Signature = hex(HMAC-SHA256(secret, timestamp + '.' + rawBody)); X-PixorAds-Timestamp — Unix-время в секундах, допуск 5 минут. secret берётся из мастера кампании и хранится только на сервере. На повторной отправке сохраняйте тело и event_id; обновляйте timestamp и подпись. Повтор не создаёт новую выплату; другой запрос с тем же event_id возвращает 409.

first_seen_at — исходное время первого появления аккаунта в вашем сервисе, а не время перехода по рекламе. Не обнуляйте историю при удалении аккаунта. Для новых пользователей оно должно быть не раньше начала задания. occurred_at — время выполнения; обе даты обязательны с часовым поясом. Подтверждение должно поступить до срока выполнения. Подпись удостоверяет отправителя: корректность истории и цели остаётся обязанностью рекламодателя.

Для отказа передайте status=rejected, для отмены ранее подтверждённого результата — revoked. Обязателен reason: existing_user, conditions_not_met, fraud или user_cancelled. Отмена возможна до окончательного расчёта, включая период проверки. После расчёта возвращается result_final — финансовая корректировка требует обращения в поддержку. Повторно подтвердить отклонённую попытку нельзя.

HTTP 200: проверьте accepted и reason; это ответ обработки, а не обещание оплаты. Подтверждённый результат проверяется фоновым обработчиком. Диагностика мастера показывает состояние выполнения и дохода площадки отдельно. Неверная подпись — HTTP 401, неверный формат — 422, частые запросы — 429. При сетевой ошибке или 5xx повторите сохранённое событие из своей очереди.

Кнопка «Создать тест» выдаёт отдельный токен на час, привязанный к вашему Telegram ID. Проверки те же, но резервирования, начислений и уведомления о награде нет. Для положительного теста используйте тестовые даты после его создания; в реальной интеграции — только историю вашей базы. Изменение настроек или ключа требует нового теста. Старый ключ после замены недействителен сразу, в том числе для начатых заданий.

Скачать серверный пример Python: подпись, проверка initData, отправка события

Статистика и ограничения

Передайте placement при создании Client или атрибут placement в компоненте; в API — при запросе сессии. Допустимы латинские буквы, цифры, _ и -, до 40 символов. Виджет отмечает видимость карточки при отображении не менее 50%. В собственном интерфейсе вызовите client.visible([campaignId]) после фактического показа; не вызывайте его при загрузке каталога. В ботах видимость сообщения неизвестна — этот счётчик остаётся пустым.

Обращение привязано к конкретному выполнению: POST /viewer/attempts/{id}/ticket, тело {message: 'описание'}, либо client.support(id, message). Ответ появляется в history[].ticket. Паблишер видит обращения своей площадки; оператор отвечает в админке «Рекламная сеть → Обращения Offerwall».

Кабинет показывает начатые задания, повторные проверки, подтверждённые результаты, отмены, расходы рекламодателя и доход площадки. Период относится к дате начала задания. Загрузка каталога не считается показом рекламы, уникальным охватом или оплачиваемым действием. В расчёт оплаты входят только окончательно подтверждённые результаты.

11 / ИНТЕГРАЦИЯ

Аудитория и таргетинг

#

Измерения включаются через init({publisherId, trackAudience:true}); у init() это значение по умолчанию. Укажите false, если измерения не нужны. trackVisit() использует подписанный Telegram initData не старше часа. Инициализация только в рекламном блоке измеряет его посетителей, а не всю аудиторию приложения.

Вызывайте trackVisit() при значимых возвращениях в приложение, без частого опроса. Повторные люди исключаются сервером. recorded:false означает, что наблюдение не записано; это не ошибка рекламного показа. trackAudience:false отключает автоматическую отправку, но не запрещает явный вызов trackVisit().

Боты отправляют реальную активность через POST /api/v1/ad-network/publisher-api/activity с {telegram_id} и серверным X-PixorAds-Key. Это данные партнёра, не доказательство оплаченного просмотра. Каналы обновляют подписчиков в кабинете после проверки прав администратора; подписчики и рекламный охват — разные показатели.

Показываем отдельно активность за 24 часа / 7 / 30 дней, уникальных зрителей, видимые показы и завершённые просмотры. Прогноз требует 7 полных UTC-дней измерений каждой выбранной площадки; для фильтров без подходящей истории прогноз не подставляется. Аудитории измеренных площадок дедуплицируются; подписчики каналов не суммируются. Группы меньше 20 человек скрыты рекламодателю.

Расскажите пользователям об измерениях. Используйте personalized:true только после разрешения на использование существующей анкеты PixorAds. Не подменяйте подписанные initData данными initDataUnsafe. Наблюдения хранятся с HMAC-идентификатором до 90 дней.

12 / СПРАВОЧНИК

Тест подключения

#

Ниже загружается настоящий SDK с test: true. Никакие объявления не запрашиваются, деньги и статистика не меняются. Нажмите кнопку внутри карточки. Такой же режим можно включить на своей странице; endpoint для него не требуется.

Test mode
window.PixorAdsPublisher.mount({  element: document.getElementById("pixorads"),  language: "ru",  test: true});
13 / СПРАВОЧНИК

Настройки и события SDK

#
ПараметрНазначение и значение по умолчанию
publisherIdПубличный UUID Mini App. Нужен для встроенного просмотра и измерений; не секретный ключ.
endpointВаш same-origin POST /offer; обязателен при test:false. SDK отправляет language, format и доступный context_token.
elementОбязателен для showNative() и create(). Для init() с полноэкранными методами можно не указывать.
csrfTokenТокен вашей cookie-сессии. Передаётся вашему endpoint заголовком X-CSRF-Token.
languageru — русский, en — английский (по умолчанию). Задаёт язык интерфейса SDK и подбора кампаний: выбранный язык или «Все языки». Не переводит текст или видео. Передайте текущий язык приложения.
timeoutMs1000–30000 мс, по умолчанию 10000. Общий лимит получения объявления; запуск iframe имеет отдельный лимит 20 секунд.
testfalse. При true нет запросов рекламы/учёта, оплат и наград. Native рисует тестовую карточку; полноэкранные методы не открывают окно.
trackAudienceinit(): true; create()/mount(): false. Автоматический trackVisit() при создании. Указывайте явно согласно вашим настройкам измерений.
personalizedfalse. Доступ к существующей анкете PixorAds только с разрешения пользователя; SDK сам не показывает запрос согласия.
embeddedinit() всегда включает. В legacy create()/mount() по умолчанию false: кнопка rewarded ведёт в отдельный PixorAds.
onRewardCallback {receipt, session_id}; ваш backend должен проверить receipt. SDK не ждёт и не повторяет callback.
onEventloading, ready, empty, error, opened, completed, closed, impression_reported, test_clicked, destroyed. UI-события, не финансовые гарантии.

Новые интеграции: init() → выбранный метод → destroy() при удалении экрана. Legacy create() требует element; mount() использует auto-выбор формата и возвращает Promise состояния. PixorAdsPublisher.mount(options) — сокращённый вызов без доступного контроллера; для управления жизненным циклом используйте init() или create().

Среда запуска и CSP

Для живого embedded-показа нужен HTTPS и запуск внутри Telegram с подписанным initData не старше часа. В обычном браузере используйте test:true; initDataUnsafe не подтверждает личность. Истёкшие данные обновляются новым запуском Mini App, а не изменением auth_date.

В Content-Security-Policy разрешите https://pixora-ads.com для script-src, frame-src и connect-src; для медиа карточки — img-src и media-src. Сохраните необходимые разрешения вашего приложения. Если CSP ограничивает стили, проверьте совместимость: SDK задаёт inline-стили карточки и оверлея. API-ключ никогда не передаётся в браузер.

TypeScript: сохраните .d.ts в папку, включённую в tsconfig, и используйте window.PixorAdsPublisher. Это типы глобального скрипта, не npm-модуль. Официального npm-пакета пока нет.

Скачать TypeScript-типы
14 / СПРАВОЧНИК

Справочник Publisher API

#
POST/api/v1/ad-network/publisher-api/offer

Запросите карточку, полноэкранную рекламу или просмотр с наградой со своего сервера. Ключ площадки нельзя передавать в браузер или Mini App.

АВТОРИЗАЦИЯX-PixorAds-KeyСекретный ключ площадки
ЗАГОЛОВКИContent-Type: application/jsonIdempotency-Key: …
ТЕЛО JSON{ "language": "ru" | "en", "format": "native" | "interstitial" | "rewarded" }language: по умолчанию en; format: auto (legacy). Передавайте context_token SDK без изменений, если он указан.
ОТВЕТЫ200 · 401 · 409 · 422 · 429Подробности в разделе ошибок
Серверный запрос
curl https://pixora-ads.com/api/v1/ad-network/publisher-api/offer \  -H "X-PixorAds-Key: $PIXORADS_PUBLISHER_KEY" \  -H "Idempotency-Key: unique-logical-request-id" \  -H "Content-Type: application/json" \  -d '{"language":"ru","format":"native"}'

ЛОКАЛЬНЫЙ КОНСТРУКТОР

Соберите запрос

ru — русский, en — английский. Язык используется для интерфейса SDK и подбора кампаний, включая «Все языки». Текст и видео не переводятся. Передайте язык вашего приложения; по умолчанию en. Пример создаётся без отправки запроса.

Пример ответа

Ниже сокращённый пример rewarded. Возвращайте SDK полный JSON сервера без изменения URL, формата и полей учёта. Для native/interstitial billing = confirmed_impression и есть impression_url. reward и publisher_amount — целые внутренние единицы: XTR и RUB делите на 1000, USD — на 1 000 000. Награда зрителю: viewer_reward/viewer_currency. Оценка дохода площадки в USD: publisher_income.

200 · rewarded · excerpt
{  "source": "pixorads",  "placement_id": "<placement UUID>",  "title": "<advertisement title>",  "text": "<plain text>",  "disclosure": "Реклама · Ad · PixorAds",  "url": "https://t.me/pixoradsbot?startapp=net_<32 hex characters>",  "expires_at": "<ISO 8601 timestamp>",  "format": "rewarded",  "billing": "completed_rewarded_session",  "currency": "XTR",  "reward": 70,  "publisher_amount": 1}// No suitable demand: { "source": "none", "monetag_enabled": false }// Rewarded response excerpt, not a complete offer to return from your backend.// Example: 70 XTR minor units = 0.07 Stars; 1 = 0.001 Stars.// Ordinary: billing:"confirmed_impression", reward:0, impression_url present.// Forward the FULL upstream JSON unchanged; never build it from this excerpt.

Обычное размещение действует 5 минут, rewarded — 24 часа; ориентируйтесь на expires_at. Idempotency-Key — до 80 символов: один на логический запрос. Для rewarded повтор возвращает прежний ответ. Для обычного объявления повтор уже выданного запроса даёт placement_already_issued: запросите новое размещение с новым ключом. Повторы не должны создавать цикл запросов.

15 / СПРАВОЧНИК

Ошибки и диагностика

#
КодЧто проверить
same_origin_backend_requiredendpoint должен вести на ваш сервер, а не прямо на API PixorAds
authentication_required / 401 / 403Сессию пользователя, CSRF и действующий серверный API-ключ
publisher_unavailable / 409Модерацию, паузу, блокировку и доступность сети
invalid_publisher_keyКлюч от этой площадки; не отозван ли он
placement_expired / 410Создайте новое размещение с новым Idempotency-Key
rate_limited / 429Ограничьте повторы; для Mini App — до 60 запросов в минуту на площадку, для bot CPC — до 120; также есть лимит по IP
timeout / network_errorДоступность своего endpoint, HTTPS, CSP connect-src и тайм-аут
invalid_adПередавайте JSON API без подмены URL; не возвращайте HTML страницы входа
no_fill / source: noneНет подходящих объявлений. Сохраните пустое состояние, попробуйте позже
publisher_format_unavailableВыбранный формат не заявлен площадкой. Сверьте native/interstitial/rewarded с её настройками.
viewer_in_progressДождитесь закрытия предыдущего окна; не запускайте методы параллельно. После destroy() создайте новый контроллер.
placement_already_issuedОбычное размещение уже выдано. Запросите новое с новым Idempotency-Key.
verified_viewer_requiredНужны publisherId и действительные Telegram.WebApp.initData. Анонимный пиксель больше не подтверждает оплаченный показ; используйте текущий SDK.
impression_unconfirmedСервер не подтвердил показ. Не считайте локальную отрисовку доходом; проверьте статус площадки и свежесть Telegram-сессии.
16 / СПРАВОЧНИК

Статистика и поддержка

#

В карточке площадки показаны выданные сеансы, подтверждённые завершения, доход на удержании и начисленный доход. Обычные подтверждённые показы учитываются отдельно от завершений rewarded; запрос offer, отрисовка карточки или клик сами по себе не подтверждают доход. Доход начисляется в USD. Для Mini App: 80% в действующую акцию, затем 70%; для новых кампаний каналов: 90%, затем 88%; для CPC в ботах — отдельный тариф. Текущие ставки показаны в разделе дохода площадок. Для обычной рекламы — от оплаченного показа; для Rewarded — после награды зрителю. Для каналов цена и доля фиксируются при создании кампании, курс — при резервировании поста. Для Mini App условия фиксируются при выдаче размещения, сумма USD — при подтверждении. Старые RUB и Stars сохраняются отдельно; вывод USD — только криптовалютными методами. Ставки зависят от аукциона и доступной рекламы. При ограничениях выплата дохода может оставаться на проверке.

Для обращения укажите ID площадки, время ошибки, HTTP-статус и код. Не присылайте API-ключ или токен бота.

17 / РЕКЛАМОДАТЕЛЯМ

Форматы рекламной сети

#

Выберите форматы при подключении площадки и передайте их на модерацию. Статика и видео — виды креатива; native, interstitial и rewarded — сценарии показа. Отдельного метода showVideo() нет: сервер подбирает подходящий креатив.

МетодГде появляется рекламаНаграда зрителю
showNative()Карточка со статикой или видео в вашем контейнереНет
showInterstitial()Экран поверх вашего Mini App; закрытие доступно сразуНет
showRewarded()Экран поверх Mini App после добровольного нажатияПосле подтверждённого просмотра; внутренний бонус — через ваш сервер

В Mini App реклама работает внутри интерфейса партнёра. Переход по рекламной кнопке добровольный; после закрытия рекламы пользователь возвращается к вашему экрану. В ботах основной формат — сообщение после полезного ответа с оплатой за переход; в каналах — рекламный пост с CPM или CPC. Кнопка ведёт к рекламодателю. JavaScript SDK предназначен для Mini App, а не сообщений.

Доход площадки и бонус зрителю — разные вещи. Для монетизации без наград выберите native или interstitial. Обычный показ учитывается после видимости не менее 50% креатива в течение непрерывной секунды в активном окне; видео должно воспроизводиться. Итог подтверждает сервер с учётом лимитов, бюджета и доступности кампании.

Для новой интеграции используйте SDK 1.8.1: init() и выбранный метод показа. Старые create()/mount() сохранены для совместимости.

18 / РЕКЛАМОДАТЕЛЯМ

Pixor Pixel

#
PIXOR PIXEL / SIGNAL LAYER

От рекламного клика до действия на сайте

Pixel запоминает анонимный px_click и показывает, какие действия совершает посетитель после перехода. Привязка к кампании доступна при создании веб-кампании и в её настройках.

01Создайте PixelКабинет → Пиксели и события. Добавьте и подтвердите HTTPS-домен.
02Установите кодВставьте скрипт на сайт. В test-режиме проверьте PageView и нужное событие в журнале.
03Свяжите с кампаниейПродвигать → Новая кампания → Веб-трафик → шаг «Аудитория». Выберите Pixel в отдельном блоке. Для существующей кампании откройте её настройки.
04Проверьте и включите LiveПроверьте test-события, затем откройте подтверждённый HTTPS-сайт через настоящий переход из веб-кампании: он создаст px_click. Результат подтвердите подписанным серверным postback.
CAMPAIGN API

Привязка без смены ключа

В интерфейсе выбор сохраняется сразу. При автоматизации используйте внутренний UUID id из GET /api/v1/pixels; публичный pixel_id вида px_… нужен только для скрипта. Передайте null, чтобы отключить Pixel. Доступ есть только владельцу кампании.

PUT /api/v1/campaigns/{campaign_id}/attribution/pixel
{ "pixel_id": "<pixel UUID>" }
Установка на сайт
<script>  window.PixorAdsPixel = window.PixorAdsPixel || { q: [] };  window.PixorAdsPixel.track = window.PixorAdsPixel.track || function (name, options) {    window.PixorAdsPixel.q.push([name, options]);  };  window.PixorAdsPixel.consent = window.PixorAdsPixel.consent || function (value) {    window.PixorAdsPixel.q.push(["consent", value]);  };</script><script async data-consent="required" src="https://pixora-ads.com/sdk/pixorads-pixel.js?pixel_id=px_your_id"></script><script>// Вызовите из обработчика согласия вашей CMP, не автоматически:function onAnalyticsConsentChanged(granted) {  window.PixorAdsPixel.consent(granted ? "granted" : "denied");}  // Только после успешного ответа сервера на заявку:  // window.PixorAdsPixel.track("Lead", { eventId: acceptedLead.event_id });</script>

Подключите обработчик согласия из своей CMP: до согласия этот код не собирает события. Браузерные события помогают анализировать воронку; подписанный postback с тем же event_id подтверждает конверсию для аналитики и не меняет оплату. Прямая ссылка на сайт не создаёт px_click. Ключ подписи храните только на backend.

19 / ПАРТНЁРАМ

Партнёрские постбеки

#

Передавайте достижения рефералов в Keitaro, Binom v2 или свой сервер. Это исходящая аналитика: она не меняет выплаты и не заменяет Offerwall webhook или серверное подтверждение Pixel.

1. Подключите трекер

Партнёры → Ссылки → Постбеки: выберите трекер, вставьте его публичный HTTPS endpoint, добавьте цели и сохранённые ссылки. Посмотрите сформированный запрос, проверьте доставку и включите подключение. Один трекер можно использовать для нескольких ссылок; у каждой ссылки одно подключение.

Открыть партнёрские ссылки →

2. Сохраните ID клика трекера

Ссылка в предложении трекера
# Keitarohttps://pixora-ads.com/api/v1/referrals/track/YOUR_LINK_CODE?tracker_click_id={subid}# Binomhttps://pixora-ads.com/api/v1/referrals/track/YOUR_LINK_CODE?tracker_click_id={clickid}

Скопируйте свой link code из сохранённой ссылки; макрос заменит трекер при переходе. tracker_click_id — внешний идентификатор (до 128 символов), click_id — отдельный внутренний ID Pixora. Промежуточная ссылка сохраняет внешний ID и открывает выбранный сайт, бота или Mini App. Прямая Telegram-ссылка с фиксированными sub_id не передаёт динамический ID клика трекера.

3. Выберите цели и суммы

СобытиеУсловие
Завершена регистрация
registration
Один раз после подтверждения почты или проверки в Telegram и принятия обязательных условий.
Выполнено 5–15 заданий
tasks
Настраиваемый порог оплаченных заданий; отдельные цели для 5, 10 и 15.
Заработана сумма
earnings
Подтверждённый заработок на заданиях в выбранной валюте, один раз на цель.
Пополнен баланс
deposit
Первое или каждое фактическое пополнение от выбранной суммы.
Начислен партнёрский доход
commission
Подтверждённое доступное вознаграждение рефовода.

До 24 целей на подключение. amount — сумма события, payout — доход партнёра: пополнение реферала на 1 000 ₽ не становится доходом рефовода. Денежный payout по умолчанию формирует только commission. Валюты не смешиваются; Stars не переводятся в рубли или доллары. В API настроек amount_minor — строка целого числа: RUB и XTR используют 1 000 единиц, USD — 1 000 000; в исходящем postback amount и payout уже десятичные строки в своей валюте.

Keitaro получает стабильный tid для каждой цели и события; повтор не должен добавлять вторую конверсию. В Binom выделите отдельные event1…event24 и одну валюту дохода RUB или USD. Адаптер передаёт абсолютные значения событий и накопленного дохода, disable_upsell=1 и disable_postback=1. Не складывайте их повторно правилами своего трекера.

Свой endpoint: GET или POST

GET · пример URL
https://tracker.example/pixora?click={tracker_click_id}&goal={goal_id}&event={event}&amount={amount}&currency={currency}&payout={payout}&payout_currency={payout_currency}

Макросы разрешены только в query-значениях: tracker_click_id, click_id, event_id, goal_id, event, link_id, sub_id_1…sub_id_5, amount, currency, payout, payout_currency, occurred_at. Записывайте их в фигурных скобках. Имена status, goal и amount_minor макросами не являются. event_id и tracker_click_id добавляются и к пользовательскому GET, даже если не указаны в шаблоне.

POST отправляет фиксированный JSON с этими полями, schema_version=1, test_mode, event_type и corrects_event_id. Это не произвольный шаблон тела. Сохраняйте event_id с UNIQUE-ограничением в той же транзакции, что и результат обработки; на повтор отвечайте 2xx. Корректировка event_type=correction ссылается на исходное событие через corrects_event_id. Учебные test_mode=true события не начисляйте реальным пользователям.

Доставка, повторы и журнал

Предпросмотр не отправляет запрос. Тест доставки использует синтетический px_test_… ID; HTTP 2xx подтверждает только ответ endpoint, а не конверсию в трекере. Для полной проверки пройдите свою ссылку из трекера и достигните выбранной цели. Журнал показывает событие, статус и причину ошибки без раскрытия секретных параметров.

Сетевые ошибки, 429 и 5xx повторяются с задержкой, до 8 автоматических попыток за цикл. Другие 4xx и перенаправления останавливают доставку. Ручной повтор использует прежний event_id, URL и данные. Неуспешное событие блокирует более новые события этого внешнего клика: восстановите endpoint и повторите его. Изменение настроек действует на будущие переходы и не переотправляет историю. Первоначальная реферальная привязка сохраняется.

API управления: /api/v1/referrals/postbacks — только для авторизованного владельца. GET — список, POST — создание; /{id}: GET и PUT; /{id}/events — журнал; /preview и /{id}/preview — просмотр запроса; /{id}/test и /events/{event_id}/retry — явная доставка. Создание, сохранение, тест и повтор требуют Idempotency-Key (1–96 символов); обновление требует актуальную version. Ключ площадки X-PixorAds-Key здесь не используется.