API v4.4 Кабинет паблишераКабинет
📡 Руководство по интеграции для паблишеров

FastCoins Publisher API
Документация

Всё, что нужно для интеграции PTC-рекламы на своём сайте, — уведомления Postback S2S и полная справка по API.

Postback S2S PTC API Аутентификация Bearer Token Примеры PHP Бесплатно и открыто
Обзор

FastCoins — это PTC-сеть (Paid-To-Click) для паблишеров. Размести нашу рекламу на своём сайте, твои пользователи получают токены за её просмотр, а ты автоматически получаешь долю дохода.

📡
Postback (S2S)
Твой сервер получает уведомление по HTTP GET, когда пользователь досматривает рекламу. Идеально для автоматического начисления наград без клиентского кода.
🔌
PTC API
Получай доступные объявления программно и показывай их в собственном интерфейсе. Встраивать виджет не нужно.
🪙
Свои токены
Настрой своё название токена и курс конвертации. Награды автоматически конвертируются и отправляются через postback.
💰
Раздел дохода
Ты сам задаёшь процент выплаты пользователю. Остальное — твой доход паблишера; вывод ежемесячно (с 1 по 3 число).
🚀
Начало работы

Создай аккаунт паблишера, подтверди владение доменом и получи API-доступы после проверки.

  • 1
    Создай аккаунт паблишера на FastCoins.com/publisher_dashboard. Понадобятся название сайта и URL.
  • 2
    Добавь домен во вкладке Domains. У каждого домена свои API Key, Secret Key, Bearer Token, настройки токена и URL postback.
  • 3
    Укажи свой postback URL — endpoint на твоём сервере, который принимает уведомления о наградах (см. раздел Postback ниже).
  • 4
    Сгенерируй Bearer Token во вкладке Domains. Он нужен для аутентификации вызовов PTC API.
  • 5
    Отправь тестовый postback из вкладки Domains, чтобы убедиться, что твой endpoint отвечает правильно, прежде чем запускаться вживую.
ℹ️
Выводы: баланс паблишера можно выводить только с 1-го по 3-е число каждого месяца. Планируй денежный поток с учётом этого.
📬
Интеграция через Postback (S2S)

Сервер-к-серверу уведомление, которое отправляется на твой сайт, когда пользователь досматривает рекламу, — так ты можешь начислять награды автоматически, без клиентского кода.

🔐 Требования безопасности

⚠️
Всегда проверяй IP источника и подпись, прежде чем начислять награду. Никогда не начисляй только по параметрам.
  • Разрешённые IP сервера: 62.171.140.250, 2a02:c207:2329:8601::1 — проверяй это только по $_SERVER['REMOTE_ADDR']. Это прямой вызов сервер-к-серверу, а не запрос браузера, между нами нет нашего прокси/CDN; заголовок вроде X-Forwarded-For подделать тривиально, поэтому для этой проверки ему доверять нельзя.
  • userIp обязателен, это не просто справочное поле, — отклоняй callback, если он отсутствует или не является корректным IP. Мы всегда резолвим и отправляем реальный IP просмотревшего рекламу (через Cloudflare на нашей стороне) именно для того, чтобы ты мог опираться на него при антифроде, лимитах по IP и проверках дубликатов пользователей, — endpoint, который его игнорирует, полностью теряет этот сигнал.
  • Обязательный HTTP-ответ: ровно ok — строчными, без пробелов, без HTML, HTTP 200
  • Алгоритм подписи (рекомендуемый): signature_sha256 = HMAC-SHA256(subId + transId + reward, secret_key)secret_key это ключ HMAC, он не дописывается к сообщению. userIp в нём не участвует.
  • Алгоритм подписи (старый, по-прежнему отправляется в каждом callback): signature = MD5(subId + transId + reward + secret_key) — значения склеены без разделителей. Сохранён бессрочно для интеграций, созданных до появления signature_sha256; менять ничего не нужно, если ты уже проверяешь эту подпись.
  • Нужно больше 8 знаков после запятой? Каждый callback также несёт reward_precise (10 знаков) со своей подписью signature_sha256_precise = HMAC-SHA256(subId + transId + reward_precise, secret_key) — полностью опционально и аддитивно, считается так же, просто по более точной строке. reward/signature_sha256/signature отправляются ровно как раньше, используешь ты это или нет.
  • Защита от дублей: всегда проверяй transId в своей БД перед начислением

📋 Параметры postback (GET)

Твой postback URL получает эти параметры по HTTP GET.

Параметр Тип Обязательный Описание
subIdstringОБЯЗАТЕЛЬНОУникальный ID пользователя в твоей системе — значение, которое ты передал в вызове виджета/API
transIdstringОБЯЗАТЕЛЬНОУникальный ID транзакции — всегда проверяй его, чтобы не начислять дважды
rewardfloatОБЯЗАТЕЛЬНОНаграда в твоей токен-валюте (уже сконвертирована по настроенному token_rate), с 8 знаками после запятой
reward_precisefloatОпциональноТа же награда, что и reward, но с 10 знаками после запятой вместо 8 — используй, когда 8 знаков тебе не хватает
reward_namestringОБЯЗАТЕЛЬНОНазвание токена, настроенное для твоего домена (напр. POINTS, COINS)
reward_valuefloatОБЯЗАТЕЛЬНОТо же, что reward — добавлено для совместимости с bitcotasks
offer_namestringОпциональноЗаголовок просмотренной рекламы — удобно для логов
offer_typestringОпциональноВсегда ptc для просмотров рекламы FastCoins
payoutfloatОпциональноТо же, что reward — добавлено для совместимости со сторонними системами
userIpstringОБЯЗАТЕЛЬНОРеальный IP-адрес пользователя, выполнившего оффер, резолвится через Cloudflare на нашей стороне до отправки этого callback, — отклоняй callback, если он отсутствует или не проходит FILTER_VALIDATE_IP. Используй для антифрода, лимитов по IP, выявления дубликатов пользователей, аудита конверсий и аналитики.
statusintegerОБЯЗАТЕЛЬНО1 = Начислить награду  |  2 = Возврат (вычесть награду)
signature_sha256stringОБЯЗАТЕЛЬНОHMAC-SHA256 от subId + transId + reward, где ключом служит secret_key — рекомендуем для новых интеграций
signature_sha256_precisestringОпциональноHMAC-SHA256 от subId + transId + reward_precise, где ключом служит secret_key — проверяй эту подпись вместо signature_sha256, только если читаешь и reward_precise
signaturestringОБЯЗАТЕЛЬНОСтарый: MD5 от subId + transId + reward + secret_key, склеенных (без разделителей). По-прежнему отправляется в каждом callback без изменений — сохранён для интеграций, созданных до появления signature_sha256.
testintegerОпционально1 = тестовый postback из кабинета — реальные награды не начисляй

🧮 Пример: построение и проверка подписанного URL

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

example
Secret Key (example only, never a real one): demo_secret_do_not_use_9f8e7d6c

Parameters for this conversion:
  subId   = user_12345
  transId = txn_987654321
  reward  = 0.50
  status  = 1
  userIp  = 127.0.0.1

signature_sha256 = HMAC-SHA256(subId + transId + reward, secret_key)
                  = HMAC-SHA256("user_12345" . "txn_987654321" . "0.50", demo_secret_do_not_use_9f8e7d6c)
                  = HMAC-SHA256("user_12345txn_9876543210.50", demo_secret_do_not_use_9f8e7d6c)
                  = df3eafaa3e8cf4fe8fb40c7bed633f34bc7b964bca58d2d691314771a042d59c

signature (legacy) = MD5(subId + transId + reward + secret_key)
                    = MD5("user_12345" . "txn_987654321" . "0.50" . "demo_secret_do_not_use_9f8e7d6c")
                    = MD5("user_12345txn_9876543210.50demo_secret_do_not_use_9f8e7d6c")
                    = d1eb68e41cbd5770de9384c5be8ebb39

Resulting callback URL:
https://yoursite.com/postback.php?subId=user_12345&transId=txn_987654321&reward=0.50&status=1&userIp=127.0.0.1&signature=d1eb68e41cbd5770de9384c5be8ebb39&signature_sha256=df3eafaa3e8cf4fe8fb40c7bed633f34bc7b964bca58d2d691314771a042d59c
⚠️
Никогда не используй этот примерный секрет для реальных задач — он публичный, напечатан в этой документации. Считай подписи своим настоящим Secret Key из вкладки Domains и никогда не вставляй настоящий ключ где-либо публично (чаты, документация, открытые репозитории) — относись к нему как к паролю. Этот пример также опускает reward_name, reward_value, offer_name, offer_type, payout и test ради краткости — в реальном callback есть все они, см. таблицу выше.

📐 Опционально: точность 10 знаков (reward_precise)

Тот же секрет, тот же callback — просто награда с большей точностью, чем вмещают 8 знаков reward. Чисто аддитивно: пропусти, если 8 знаков покрывают твой случай.

example-precise
Same secret key and subId/transId as above, but the underlying reward this
time carries more precision:

  reward          = 0.12345679   (8 decimals, rounded)
  reward_precise  = 0.1234567890 (10 decimals)

signature_sha256_precise = HMAC-SHA256(subId + transId + reward_precise, secret_key)
                          = HMAC-SHA256("user_12345" . "txn_987654321" . "0.1234567890", demo_secret_do_not_use_9f8e7d6c)
                          = 219d2101a528b8585161bd26c3bb80c5de8a6741d60d2f1778eb805a05f7a707

💻 Реализация на PHP — postback.php

Сохрани это на своём сервере, укажи свой Secret Key из вкладки Domains, затем вставь полный URL в поле Postback URL своего домена.

postback.php
// ── 1. YOUR SECRET KEY (from Domains tab → Secret Key) ─────
$secret = "";  // ← paste your secret key here

// ── 2. IP VALIDATION (callback source) ──────────────────────
// REMOTE_ADDR only — this call comes straight from our server to
// yours, no browser and no proxy of ours in between, so it's the
// one value here that can't be spoofed by whoever is calling you.
// X-Forwarded-For (or any other header) is attacker-controlled and
// must never be trusted for this check.
$allowed_ips = ['62.171.140.250', '2a02:c207:2329:8601::1'];
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
if (!in_array($ip, $allowed_ips, true)) {
    echo "ERROR: Invalid source IP";
    exit;
}

// ── 3. COLLECT PARAMETERS ───────────────────────────────────
$userId    = $_GET['subId']     ?? null;
$transId   = $_GET['transId']   ?? null;
$status    = $_GET['status']    ?? null;
$isTest    = isset($_GET['test']) && $_GET['test'] == 1;
$userIp    = $_GET['userIp']   ?? null;  // real IP of the ad viewer — required, see step 4

// ── 3b. DYNAMIC PRECISION ────────────────────────────────────
// Prefer reward_precise (10 decimals) when the callback carries it;
// fall back to the standard reward (8 decimals) otherwise. Whichever
// pair is picked, it's verified against its own matching signature in
// step 6 — if that signature is valid, the postback is accepted.
$hasPrecise = isset($_GET['reward_precise'], $_GET['signature_sha256_precise']);
$reward    = $hasPrecise ? $_GET['reward_precise']           : ($_GET['reward'] ?? null);
$signature = $hasPrecise ? $_GET['signature_sha256_precise'] : ($_GET['signature_sha256'] ?? null);

// ── 4. VALIDATE USER IP (required) ──────────────────────────
// userIp is mandatory — this is the real IP of the person who
// completed the offer, already resolved through Cloudflare on our
// end. Reject the callback outright rather than silently accepting
// one without it, since your fraud detection / IP-limit / duplicate-
// user checks depend on this value actually being present and valid.
if (!$userIp || !filter_var($userIp, FILTER_VALIDATE_IP)) {
    echo "ERROR: Invalid user IP";
    exit;
}

// ── 5. VALIDATE REQUIRED PARAMS ─────────────────────────────
if (!$userId || !$transId || $reward === null || !$signature) {
    echo "ERROR: Missing parameters";
    exit;
}

// ── 6. VERIFY SIGNATURE ─────────────────────────────────────
// Only subId + transId + reward go into this hash — userIp is NOT
// part of it. $secret is the HMAC key, not concatenated into the
// message. Don't add userIp here unless a different provider's docs
// explicitly say their signature scheme includes it.
$expected = hash_hmac('sha256', $userId . $transId . $reward, $secret);
if (!hash_equals($expected, $signature)) {
    echo "ERROR: Signature mismatch";
    exit;
}

// ── 7. HANDLE CHARGEBACK (status = 2) ───────────────────────
if ((int)$status === 2) {
    $reward = -abs((float)$reward);  // negative = deduct
}

// ── 8. TEST CALLBACK ─────────────────────────────────────────
// Authenticated and validated like any other callback, but must not
// touch a real balance.
if ($isTest) {
    echo "ok";
    exit;
}

// ── 9. PREVENT DUPLICATES, CREDIT REWARD & STORE USER IP ──────
// Replace with your actual DB logic.
if (!isTransactionProcessed($transId)) {
    creditUserReward($userId, $reward, $transId);
    // If your credit function only takes these 3 args, store $userIp
    // with the conversion separately, e.g.:
    //   saveConversionIp($transId, $userId, $userIp);
}

// ── 10. REQUIRED RESPONSE ───────────────────────────────────
echo "ok";  // MUST return exactly this, nothing else

🕓 Старая проверка — MD5

💡
Уже проверяешь signature через MD5? Он по-прежнему приходит в каждом callback, полностью без изменений, — этот блок чисто для справки. Действий не требуется. Новым интеграциям лучше использовать signature_sha256 выше.
postback-legacy.php
$signature = $_GET['signature'] ?? null;
$expected  = md5($userId . $transId . $reward . $secret);
if (!hash_equals($expected, $signature)) {
    echo "ERROR: Signature mismatch";
    exit;
}
// ...same IP check, userIp check, and crediting logic as the main example above.

🔀 Схема обработки callback

  • 1
    Callback получен
  • 2
    Сверь REMOTE_ADDR с белым списком IP
  • 3
    Прочитай параметры, включая userIp
  • 4
    Проверь userIp — отклони, если отсутствует или не является корректным IP
  • 5
    Проверь остальные обязательные параметры
  • 6
    Проверь подпись
  • 7
    Проверь status — при 2 проведи как возврат
  • 8
    Если test=1, верни ok, ничего не начисляя
  • 9
    Сверь transId со своей БД, чтобы не начислять дубли
  • 10
    Начисли или отмени награду и сохрани userIp вместе с конверсией
  • 11
    Верни ok

Возможные ответы:

  • ok — callback обработан (или признан тестовым)
  • ERROR: Invalid source IP
  • ERROR: Invalid user IP
  • ERROR: Missing parameters
  • ERROR: Signature mismatch
Обязательный ответ: верни HTTP 200 с телом ровно ok — без пробелов, без переводов строки, без HTML.
⚠️
Неудавшиеся postback можно отправить повторно из вкладки Postback Logs в твоём кабинете. Всегда делай endpoint идемпотентным — безопасным при многократных вызовах с тем же transId.
💡
Сначала протестируй: воспользуйся кнопкой Test Postback во вкладке Domains, чтобы проверить свой endpoint до запуска. Тестовые postback содержат test=1 — награды за них не начисляй.
🔌
PTC API — получение рекламы программно

Запрашивай доступную PTC-рекламу через REST API и отрисовывай её в собственном интерфейсе. Встраивать виджет не нужно.

🌐 Endpoint

GET https://FastCoins.com/api/[API_KEY]/[USER_ID]/[USER_IP]/[DEVICE]
СегментОписание
API_KEYAPI Key твоего домена — находится во вкладке Domains твоего кабинета паблишера
USER_IDУникальный идентификатор пользователя в твоей системе. Возвращается как subId в postback
USER_IPРеальный IP-адрес пользователя — используется для таргетинга рекламы и защиты от фрода. Передавай настоящий IP клиента
DEVICEРовно desktop или mobile — третьего значения нет. Планшеты (iPad, Android-планшеты) считаются mobile. Реальное устройство посетителя обязательно, как только у какого-либо рекламодателя появится кампания с таргетингом по устройствам: ты вызываешь этот API со своего сервера, User-Agent твоего сервера — не устройство посетителя, мы не можем определить его за тебя, — ты обязан определить и передать его сам. Всё, что не desktop/mobile (включая буквальное "tablet"), считается как отсутствие значения — приводи к mobile самостоятельно. Запрос без этого параметра или с опечаткой в таком случае получает HTTP 400.
⚠️
Критическое изменение: если твоя интеграция ещё не отправляет [DEVICE], добавь его сейчас. Сейчас он молча игнорируется, но как только таргетинг по устройствам заработает, начнёт возвращаться HTTP 400 — не жди, пока это сломает твой фид.

🔑 Аутентификация — Bearer Token

⚠️
Каждый запрос к API требует Bearer Token в заголовке Authorization. Генерируй его для каждого домена во вкладке Domains (кнопка 🔄 рядом с "Bearer Token").
Authorization: Bearer [YOUR_BEARER_TOKEN]
ℹ️
Если у домена не настроен Bearer Token, аутентификация пропускается. Для продакшена всегда задавай токен.

💻 Пример PHP

get-ads.php
// ── YOUR CREDENTIALS (from Domains tab) ─────────────────────
$apiKey      = 'YOUR_API_KEY';
$bearerToken = 'YOUR_BEARER_TOKEN';

// ── USER DATA ────────────────────────────────────────────────
$userId = $_SESSION['user_id'];  // your user's unique ID
// REMOTE_ADDR by default — it's the one value here that can't be
// spoofed by the visitor. Only read a proxy header instead (e.g.
// CF-Connecting-IP) if your own server sits behind a reverse proxy
// you control and trust — never a client-supplied header like
// X-Forwarded-For, which the visitor's own browser can set to
// anything.
$userIp = $_SERVER['REMOTE_ADDR'] ?? '';

// Required once any advertiser runs a device-targeted campaign — this
// script call happens during the visitor's own page load, so THIS
// server's incoming User-Agent is theirs. Don't skip this: a call from a
// background job/cron with no real visitor attached has no correct value
// to send here.
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
$device    = preg_match('/Mobi|Android|iPhone|iPod|iPad|BlackBerry|IEMobile|Opera Mini/i', $userAgent)
    ? 'mobile' : 'desktop';

// ── BUILD URL ────────────────────────────────────────────────
$url = 'https://FastCoins.com/api/' . $apiKey
     . '/' . urlencode($userId)
     . '/' . urlencode($userIp)
     . '/' . $device;

// ── CURL REQUEST ─────────────────────────────────────────────
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 10,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $bearerToken,
        'Accept: application/json',
    ],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);

// ── HANDLE RESPONSE ──────────────────────────────────────────
if ($httpCode === 200 && $data['status'] === '200') {
    foreach ($data['data'] as $ad) {
        // $ad['url'] already contains the user subId encoded
        echo '<a href="' . htmlspecialchars($ad['url']) . '" target="_blank">';
        echo htmlspecialchars($ad['title']);
        echo ' — ' . $ad['reward'] . ' ' . $ad['currency_name'];
        echo '</a><br>';
    }
} else {
    echo 'No ads available.';
}

📦 Формат ответа

Успешные ответы возвращают HTTP 200 с такой JSON-структурой:

{ "status": "200", "message": "success", "data": [ { "id": "123", "image": "https://FastCoins.com/banners/ad.png", "title": "Visit Our Site & Earn", "description": "Watch this ad for 30 seconds", "duration": "30", "reward": "100.0000", "currency_name": "Coins", "url": "https://FastCoins.com/view/abc123", "boosted_campaign": false, "ad_type": "Iframe" } ] }
ПолеТипОписание
idstringУникальный идентификатор объявления
imagestringПолный URL баннера объявления — может быть пустым
titlestringЗаголовок для показа — покажи его своим пользователям
descriptionstringКраткое описание объявления
durationstringТребуемое время просмотра в секундах: 2, 30 или 60
rewardfloatСумма награды в токен-валюте твоего домена (уже сконвертирована)
currency_namestringНазвание токена, настроенное для твоего домена (напр. COINS, USDT)
urlstringПеренаправляй пользователя сюда для просмотра рекламы. Postback срабатывает автоматически по завершении. subId пользователя уже закодирован в URL.
boosted_campaignbooleanЯвляется ли объявление продвигаемым — стоит выделять такие в своём интерфейсе
ad_typestringIframe = проигрывается внутри фрейма  |  Redirect = пользователь переходит на страницу рекламодателя

⚠️ Коды ошибок

Ошибки используют ту же JSON-структуру с полем статуса, отличным от 200.

HTTPstatusПричина и решение
401401Неверный API key — проверь сегмент API_KEY в URL, либо отсутствует Bearer Token, когда домен его требует
403403Bearer Token не совпадает — сгенерируй заново и обнови во вкладке Domains
400400Неверный формат USER_ID — только буквы и цифры (a-z, 0-9, _, -, .), максимум 255 символов
400400Сегмент DEVICE отсутствует или неверен — возвращается только после включения таргетинга по устройствам. Должен быть ровно desktop или mobile
500500Внутренняя ошибка сервера — в поле message детали для отладки. Если повторяется, напиши в поддержку.
🔄
Схема интеграции

Полный путь: от вызова API до начисления награды на вашем сайте.

📡 Схема API + Postback

Твой сайт вызывает
GET /api/…
Пользователь кликает по url объявления
Пользователь смотрит рекламу на FastCoins.com
FastCoins отправляет
GET postback.php
Проверка и начисление награды
Возврат ok

🧩 Встраиваемый виджет (альтернатива)

Если не хочешь использовать API, вставь виджет как iframe — он сам делает всё, со стилями, изолированными от остальной страницы.

widget-embed.php
<iframe src="https://fastcoins.click/widget-embed.php?api_key=YOUR_API_KEY&sub_id={USER_ID}"
    style="width:100%;height:640px;border:none;" loading="lazy"></iframe>
ℹ️
Замени YOUR_API_KEY на API Key своего домена и {USER_ID} на ID текущего пользователя (рендерится на сервере). Виджет показывает доступные объявления и задания прямо на странице и автоматически отправляет postback по завершении. Поменяй 640px в style, чтобы сделать iframe выше или ниже под свой макет.
⚠️
Один уникальный sub_id (= {USER_ID}) на реального пользователя — никаких суффиксов для размножения. Каждый твой пользователь должен идентифицироваться одним стабильным id. Формат выбираешь ты — непрозрачный id, логин, email (напр. ABD01230A23, [email protected]) — но одному реальному человеку соответствует ровно один id, навсегда.

Не допускается: брать базовый id и дописывать числовой суффикс, превращая одного реального человека в нескольких "пользователей". Детекция не зависит от разделителя — она отрезает завершающие -, _ или . с цифрами и считает остаток личностью пользователя. Любая из этих пар отклоняется:
  • 123-1 & 123-2
  • ABC_1 & ABC_2
  • A23-23 & A23-24
  • order.1 & order.2
Сплошной id без разделителя — одна уникальная личность, он никогда не разделяется (ABD01230A23, 1001, [email protected] — всё это допустимо).

При обнаружении шаблона API всё равно отвечает ok, но с сообщением, что такой id не разрешён, и награда не начисляется; попытка логируется как фрод.
Задания (CPA) — для рекламодателей

Создай задание (напр. "зарегистрируйся на моём сайте"), пополни счёт на N выполнений и подтверждай каждое подписанным сервер-к-сервер postback. Пользователю автоматически начисляется награда в момент прихода твоего postback — без ручной модерации и без задержек платформы.

📡 Как это работает

Ты создаёшь задание
/create-task
Пользователь открывает твой URL с cka_cid
Пользователь выполняет действие
Твой сервер вызывает наш postback
Пользователь мгновенно получает награду

1) URL postback

GET https://fastcoins.click/webhooks/task-postback.php?cka_cid={CLICK_ID}&sign={SIGN}
  • cka_cid — click id, который мы дописали к твоей целевой ссылке, когда пользователь начал (your-url?cka_cid=…). Верни его без изменений.
  • signhash_hmac('sha256', $cka_cid, $task_secret) (hex в нижнем регистре). Секрет каждого задания показан в Create Task → My Tasks.

2) Подпись

// PHP
$sign = hash_hmac('sha256', $cka_cid, $task_secret);

// Node.js
const sign = crypto.createHmac('sha256', taskSecret).update(ckaCid).digest('hex');

# Python
import hmac, hashlib
sign = hmac.new(task_secret.encode(), cka_cid.encode(), hashlib.sha256).hexdigest()
ℹ️
Только твои серверные IP из белого списка могут вызывать postback (настраивается на задание). Любой другой IP получает 403, даже с верной подписью. Это плюс HMAC — вся модель подлинности. Береги свой секрет.
⚠️
Начисление по твоему postback происходит немедленно и окончательно — чарджбэков нет. Выполнение засчитывается в момент проверки подписи твоего postback, потому что твой postback и ЕСТЬ доказательство, что пользователь сделал работу. Убедись, что собственные антифрод-проверки выполняются до вызова postback: после отправки его не отменить. Вызывай его только для выполнений, в которых уверен.

3) Опциональный аналитический пиксель

Поставь это на страницу конверсии для собственной аналитики. Он никогда не начисляет — postback выше единственное, что начисляет.

<img src="https://fastcoins.click/task-pixel.php?cid={CLICK_ID}" width="1" height="1" alt="">
💡
Лучшие практики

Рекомендации для надёжной, безопасной и доходной интеграции.

⚡ Производительность

  • Кэшируй ответы API минимум на 60 секунд на пользователя. Не дёргай API при каждой загрузке страницы — объявления меняются максимум раз в несколько минут.
  • Передавай реальный IP пользователя. По умолчанию используй REMOTE_ADDR — это единственное значение, которое посетитель не может подделать. Читай прокси-заголовок (напр. CF-Connecting-IP) только если твой сервер стоит за обратным прокси, который ты контролируешь и которому доверяешь; никогда не доверяй клиентским заголовкам вроде X-Forwarded-For. Неверные IP снижают качество таргетинга.
  • Ставь таймаут 10 секунд на cURL-вызовы, чтобы медленный ответ нашего API не тормозил загрузку страниц.

🔒 Безопасность

  • Никогда не раскрывай свой Secret Key в клиентском коде и публичных репозиториях. Он используется только на сервере для проверки подписей.
  • Всегда сверяй transId со своей базой перед начислением — это защищает от двойных наград из-за случайных повторных отправок postback.
  • Проверяй IP источника перед обработкой любого postback. Принимай запросы только от 62.171.140.250 или 2a02:c207:2329:8601::1.
  • Используй HTTPS для своего postback endpoint. HTTP-endpoints могут блокироваться.
  • Отправляй один уникальный sub_id на реального пользователя. Не добавляй числовые суффиксы к базовому id (123-1/123-2, ABC_1/ABC_2, order.1/order.2) — любой разделитель (- _ .) распознаётся как фрод, и запрос отклоняется без начисления. См. правило выше.

💰 Доход

  • Продвинутые объявления (boosted_campaign: true) платят больше — выделяй их в интерфейсе, чтобы поднять кликабельность.
  • Длинная реклама (60 с) платит заметно больше короткой (2 с). Ставь её в приоритет при высокой вовлечённости пользователей.
  • Балансируй долю пользователя — выше выплата привлекает больше активных пользователей; ниже выплата — больше твоя маржа.
  • Выводы открыты с 1 по 3 число каждого месяца — отметь в календаре.

🐛 Отладка

  • Используй кнопку Test Postback во вкладке Domains, чтобы убедиться, что endpoint возвращает ровно ok с HTTP 200.
  • Загляни во вкладку Postback Logs — там полные HTTP-ответы каждой попытки postback: коды статусов и ответы сервера.
  • Неудавшиеся postback можно отправить повторно по одному или пакетно из вкладки логов. Данные никогда не теряются безвозвратно.
  • Если подпись всё время не сходится: для signature_sha256 проверь, что secret_key передаётся как ключ HMAC (не дописывается к сообщению) и что ты хэшируешь subId + transId + reward без разделителей; для старого signature — что склеиваешь subId + transId + reward + secret без разделителей. В обоих случаях убедись, что reward в точности совпадает со строкой из GET-параметра (без округления).
  • Если проверяешь signature_sha256_precise: хэш считается по reward_precise, а не по reward — перепутать поля с чужой подписью здесь самая частая ошибка.

Готов начать зарабатывать?

Создай аккаунт паблишера меньше чем за 2 минуты и подтверди свой домен, чтобы начать.

Открыть кабинет паблишера →
✓ Скопировано в буфер обмена