Developer Documentation

AoyTasks Integration Guide

Connect AoyTasks to your website, credit members for completed activities, or advertise your own CPA campaign.

Offerwall PTC API Shortlink API Offer & Survey API S2S Postback Android / iOS React Native CPA Advertising
ℹ️

Create an account on AoyTasks first. Publishers register and verify an app under My Apps; advertisers use the CPA Advertising workspace.


Getting Started

Add your Website

Before integrating our offerwall or APIs, register your website in the dashboard. Once registered, you'll receive an API KEY and a SECRET KEY required for the next steps.

Login to your AoyTasks account.
Open My Apps from the sidebar, then click Add New App to register your website or mobile app.
Set your App Name, URL, and Application Type (platform), then proceed to the next step.
Configure your currency: set Currency Name in plural form (e.g. Points, Tokens, Coins), Currency Round (decimal places, up to 5), and Exchange Rate (how many units of your currency a user earns per $1 USD).
Enter your HTTPS Postback URL — completed events are sent to this URL so your server can authenticate and credit your users.
Open My Apps, click Verify ownership, and complete one of the verification options to approve your website automatically.

Integration

Integrate Offerwall

Our offerwall displays website visits, videos, tasks, and supported offers or surveys. Its layout adapts automatically to any screen size.

Click My Apps in the sidebar.
Retrieve your API Key and Secret Key from your websites list, or click Edit on any app to copy the full offerwall integration code.

Website Integration

Use JavaScript to open the offerwall in a new tab, or embed it directly in your approved HTTPS website using an iFrame.

JavaScript Integration

window.open("https://aoytasks.com/offerwall/[API_KEY]/[USER_ID]", "_blank", "noopener");

iFrame Integration

<iframe scrolling="yes" frameborder="0"
  src="https://aoytasks.com/offerwall/[API_KEY]/[USER_ID]"></iframe>
⚠️

Replace [API_KEY] with the app API key from My Apps and [USER_ID] with your own stable user identifier. Keep the app Secret Key on your server.

PTC API Integration

Fetch PTC and video campaigns from AoyTasks and enabled partners to display them in your own UI. Open the returned url when the user clicks Start — no second API request is needed.

Endpoint

curl -X GET "https://aoytasks.com/api/v1/publisher/ptc?user_id=[USER_ID]&user_ip=[USER_IP]" \
  -H "Authorization: Bearer [BEARER_TOKEN]" \
  -H "User-UA: [USER_AGENT]"

JSON response

{
    "status": 200,
    "message": "success",
    "data": [
        {
            "id": "[STABLE_ITEM_ID]",
            "source": "native",
            "provider": "AoyTasks",
            "category": "ptc",
            "title": "Visit and earn rewards!",
            "description": "View this website to earn your reward.",
            "image": "",
            "reward": "80.00000",
            "payout": "0.08000000",
            "currency_name": "Points",
            "url": "https://aoytasks.com/publisher-api/launch/[VISITOR_LINK_FROM_RESPONSE]",
            "duration": 15,
            "ad_type": "iframe"
        },
        {
            "id": "[STABLE_VIDEO_ID]",
            "source": "makeyoutask",
            "provider": "MakeYouTask",
            "category": "video",
            "title": "Watch video",
            "description": "View this website to earn your reward.",
            "image": "",
            "reward": "80.00000",
            "payout": "0.08000000",
            "currency_name": "Points",
            "url": "https://aoytasks.com/publisher-api/launch/[VISITOR_LINK_FROM_RESPONSE]",
            "duration": 30,
            "ad_type": "video"
        }
    ],
    "meta": {
        "page": 1,
        "per_page": 20,
        "total": 2,
        "has_more": false,
        "url_expires_in": 600
    }
}

PHP example

function requestWithFileGetContents($url, $token) {
    $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';
    $options = [
        'http' => [
            'header' => "Authorization: Bearer $token\r\nUser-UA: $userAgent\r\nAccept: application/json\r\n",
        ]
    ];
    return file_get_contents($url, false, stream_context_create($options));
}

function requestWithCurl($url, $token) {
    $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER     => [
            "Authorization: Bearer $token",
            "User-UA: $userAgent",
            "Accept: application/json"
        ],
    ]);

    $response = curl_exec($ch);
    if (curl_errno($ch)) $response = false;
    curl_close($ch);

    return $response;
}

$url   = 'https://aoytasks.com/api/v1/publisher/ptc?user_id=[USER_ID]&user_ip=[USER_IP]';
$token = '[BEARER_TOKEN]';

$response = requestWithFileGetContents($url, $token) ?: requestWithCurl($url, $token);

if ($response) {
    $data = json_decode($response, true);

    if (isset($data['status']) && $data['status'] == 200) {
        foreach ($data['data'] as $ptc) {
            echo $ptc['title'] . " — " . $ptc['reward'] . "\n";
        }
    } else {
        echo $data['message'] ?? 'Error';
    }
} else {
    echo "Request Failed";
}
ℹ️

Replace [BEARER_TOKEN] with your Bearer token (generate it in My Apps → Edit → Offerwall Integration), [USER_ID] with the user's unique identifier on your site, and [USER_IP] with the user's IP address.

Offer API Integration

Fetch hosted offerwalls, approved AoyTasks CPA offers, and individual partner offers to display them in your own UI. Open the returned url when the user clicks Start — no second API request is needed.

Endpoint

curl -X GET "https://aoytasks.com/api/v1/publisher/offers?user_id=[USER_ID]&user_ip=[USER_IP]" \
  -H "Authorization: Bearer [BEARER_TOKEN]" \
  -H "User-UA: [USER_AGENT]"

JSON response

{
    "status": 200,
    "message": "success",
    "data": [
        {
            "id": "[STABLE_ITEM_ID]",
            "source": "aoytasks_cpa",
            "provider": "AoyTasks CPA",
            "category": "offers",
            "title": "Download and try this app",
            "description": "Create an account and complete the required step.",
            "image": "",
            "reward": "80.00000",
            "payout": "0.08000000",
            "currency_name": "Points",
            "url": "https://aoytasks.com/publisher-api/launch/[VISITOR_LINK_FROM_RESPONSE]",
            "cpa_type": "offer",
            "goals": [
                {
                    "id": "register",
                    "name": "Create an account",
                    "reward": "80.00000",
                    "payout": "0.08000000"
                }
            ],
            "devices": [
                "desktop",
                "android",
                "ios"
            ],
            "estimated_minutes": 0
        }
    ],
    "meta": {
        "page": 1,
        "per_page": 20,
        "total": 1,
        "has_more": false,
        "url_expires_in": 600
    }
}

PHP example

$url   = 'https://aoytasks.com/api/v1/publisher/offers?user_id=[USER_ID]&user_ip=[USER_IP]';
$token = '[BEARER_TOKEN]';

$response = requestWithFileGetContents($url, $token) ?: requestWithCurl($url, $token);

if ($response) {
    $data = json_decode($response, true);

    if (isset($data['status']) && $data['status'] == 200) {
        foreach ($data['data'] as $offer) {
            echo $offer['title'] . " — " . $offer['reward'] . "\n";
        }
    } else {
        echo $data['message'] ?? 'Error';
    }
} else {
    echo "Request Failed";
}
ℹ️

Replace [BEARER_TOKEN] with your Bearer token (generate it in My Apps → Edit → Offerwall Integration), [USER_ID] with the user's unique identifier on your site, and [USER_IP] with the user's IP address.

Survey API Integration

Fetch approved AoyTasks CPA surveys and individual partner surveys to display them in your own UI. Open the returned url when the user clicks Start — no second API request is needed.

Endpoint

curl -X GET "https://aoytasks.com/api/v1/publisher/surveys?user_id=[USER_ID]&user_ip=[USER_IP]" \
  -H "Authorization: Bearer [BEARER_TOKEN]" \
  -H "User-UA: [USER_AGENT]"

JSON response

{
    "status": 200,
    "message": "success",
    "data": [
        {
            "id": "[STABLE_ITEM_ID]",
            "source": "aoytasks_cpa",
            "provider": "AoyTasks CPA",
            "category": "surveys",
            "title": "Share your shopping habits",
            "description": "Answer a few questions about your shopping habits.",
            "image": "",
            "reward": "80.00000",
            "payout": "0.08000000",
            "currency_name": "Points",
            "url": "https://aoytasks.com/publisher-api/launch/[VISITOR_LINK_FROM_RESPONSE]",
            "cpa_type": "survey",
            "goals": [
                {
                    "id": "complete",
                    "name": "Complete the survey",
                    "reward": "80.00000",
                    "payout": "0.08000000"
                }
            ],
            "devices": [
                "desktop",
                "android",
                "ios"
            ],
            "estimated_minutes": 0
        }
    ],
    "meta": {
        "page": 1,
        "per_page": 20,
        "total": 1,
        "has_more": false,
        "url_expires_in": 600
    }
}

PHP example

$url   = 'https://aoytasks.com/api/v1/publisher/surveys?user_id=[USER_ID]&user_ip=[USER_IP]';
$token = '[BEARER_TOKEN]';

$response = requestWithFileGetContents($url, $token) ?: requestWithCurl($url, $token);

if ($response) {
    $data = json_decode($response, true);

    if (isset($data['status']) && $data['status'] == 200) {
        foreach ($data['data'] as $survey) {
            echo $survey['title'] . " — " . $survey['reward'] . "\n";
        }
    } else {
        echo $data['message'] ?? 'Error';
    }
} else {
    echo "Request Failed";
}
ℹ️

Replace [BEARER_TOKEN] with your Bearer token (generate it in My Apps → Edit → Offerwall Integration), [USER_ID] with the user's unique identifier on your site, and [USER_IP] with the user's IP address.

Android Integration

Open the URL in the device browser, or embed it in a WebView inside your Android app.

Offerwall URL

https://aoytasks.com/offerwall/[API_KEY]/[USER_ID]

WebView Example

WebView myWebView = new WebView(activityContext);
setContentView(myWebView);

WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

myWebView.loadUrl("https://aoytasks.com/offerwall/[API_KEY]/[USER_ID]");
⚠️

Replace [API_KEY] with the app API key from My Apps and [USER_ID] with your own stable user identifier. Keep the app Secret Key on your server.

iOS Integration

Open the URL in Safari, or use WKWebView inside your iOS app.

Offerwall URL

https://aoytasks.com/offerwall/[API_KEY]/[USER_ID]

WebView Example

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate {
    var webView: WKWebView!

    override func loadView() {
        let configuration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: configuration)
        webView.uiDelegate = self
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        guard let url = URL(string: "https://aoytasks.com/offerwall/[API_KEY]/[USER_ID]") else { return }
        webView.load(URLRequest(url: url))
    }
}
⚠️

Replace [API_KEY] with the app API key from My Apps and [USER_ID] with your own stable user identifier. Keep the app Secret Key on your server.

React Native

Use Linking to open the offerwall in the device browser, or embed it using react-native-webview.

import { Linking } from 'react-native';
Linking.openURL('https://aoytasks.com/offerwall/[API_KEY]/[USER_ID]');
// Install react-native-webview for your application platform.
import { WebView } from 'react-native-webview';
return <WebView source={{ uri: 'https://aoytasks.com/offerwall/[API_KEY]/[USER_ID]' }} />;
⚠️

Replace [API_KEY] with the app API key from My Apps and [USER_ID] with your own stable user identifier. Keep the app Secret Key on your server.

Offerwall Parameters

Replace these placeholders with your approved app credentials and the signed-in member's exact identifier.

ParameterDescriptionValue
[API_KEY]Unique API code provided when you registered your websiteApp API key from My Apps
[USER_ID]Unique identifier code of the user on your site1–64 ASCII letters or digits, with single _ . @ - separators inside the identifier
[USER_IP]Public IPv4 or IPv6 address of the user (for Publisher API requests)Visitor's public IP address
[BEARER_TOKEN]Private API token generated in My Apps → Edit → Offerwall IntegrationAuthorization: Bearer [BEARER_TOKEN] header

Faucet Scripts

Ready-Made Website Scripts

Follow the steps below to connect AoyTasks to VieFaucet 4.3, VieFaucet 4.4, or CryptoFaucet / ClaimBits.

VieFaucet 4.3 Integration

Four quick steps to integrate the AoyTasks offerwall into VieFaucet 4.3.

Step 1 — Open application/controllers/wh.php and add this before the last closing bracket (}):

⚠️

Enter your publisher app Secret Key under the $secret variable. Without it, postbacks will not credit users.

public function aoytasks()
{
    $secret  = "";  // YOUR SECRET KEY
    $hold    = 3;   // Hold days (0 = instant)
    $minHold = 0.5; // Rewards below this are not held

    $userId        = isset($_POST['subId'])     ? $this->db->escape_str($_POST['subId'])     : null;
    $transactionId = isset($_POST['transId'])   ? $this->db->escape_str($_POST['transId'])   : null;
    $reward        = isset($_POST['reward'])    ? $this->db->escape_str($_POST['reward'])    : null;
    $action        = isset($_POST['status'])    ? $this->db->escape_str($_POST['status'])    : null;
    $debug         = isset($_POST['debug'])     ? $this->db->escape_str($_POST['debug'])     : "0";
    $userIp        = isset($_POST['userIp'])    ? $this->db->escape_str($_POST['userIp'])    : "0.0.0.0";
    $signature     = isset($_POST['signature']) ? $this->db->escape_str($_POST['signature']) : null;

    $expected = hash_hmac('sha256', ($_POST['transId'] ?? '') . ($_POST['subId'] ?? '') . ($_POST['reward'] ?? ''), $secret);
    if (!is_string($signature) || !hash_equals($expected, $signature)) {
        echo "ERROR: Signature doesn't match";
        return;
    }

    if ($debug == 1) {
        echo "ok";
        return;
    }

    $reward = $reward * $this->data['settings']['currency_rate'];
    $trans  = $this->m_offerwall->getTransaction($transactionId, 'aoytasks');

    if ($action == 2) {
        $this->m_offerwall->reduceUserBalance($userId, abs($reward));
        $this->m_offerwall->insertTransaction($userId, 'AoyTasks', $userIp, $reward, $transactionId, 1, time());
        echo "ok";
    } else {
        if (!$trans) {
            $hold = ($reward > $minHold) ? 3 : 0;
            if ($hold == 0) {
                $offerId = $this->m_offerwall->insertTransaction($userId, 'AoyTasks', $userIp, $reward, $transactionId, 2, time());
                $this->m_offerwall->updateUserBalance($userId, $reward);
                $this->m_core->addNotification($userId, currency($reward, $this->data['settings']['currency_rate']) . " from AoyTasks Offer #$offerId was credited.", 1);
                $user = $this->m_core->get_user_from_id($userId);
                $this->m_core->addExp($user['id'], $this->data['settings']['offerwall_exp_reward']);
                if (($user['exp'] + $this->data['settings']['offerwall_exp_reward']) >= ($user['level'] + 1) * 100) {
                    $this->m_core->levelUp($user['id']);
                }
            } else {
                $availableAt = time() + $hold * 86400;
                $offerId = $this->m_offerwall->insertTransaction($userId, 'AoyTasks', $userIp, $reward, $transactionId, 0, $availableAt);
                $this->m_core->addNotification($userId, "Your AoyTasks Offer #$offerId is pending approval.", 0);
            }
            echo "ok";
        } else {
            echo "DUP";
        }
    }
}

Step 2 — Open application/controllers/offerwall.php and add before the last }:

public function aoytasks()
{
    $api_key = ""; // YOUR API KEY
    $this->data['page']   = 'AoyTasks Offerwall';
    $this->data['iframe'] = '<iframe style="width:100%;height:800px;border:0;" scrolling="yes" frameborder="0"
        src="https://aoytasks.com/offerwall/' . $api_key . '/' . $this->data['user']['id'] . '"></iframe>';
    $this->data['wait']   = 3; // Hold days
    $this->render('offerwall', $this->data);
}

Step 3 — Add a menu link in application/views/user_template/template.php:

<li><a href="<?= site_url('offerwall/aoytasks') ?>" key="t-aoytasks">AoyTasks</a></li>

Step 4 — Open application/config/config.php, find $config['csrf_exclude_uris'] and add:

'wh/aoytasks',
🔗

Set your Postback URL in the AoyTasks dashboard to: https://yourdomain.com/wh/aoytasks

VieFaucet 4.4 Integration

Integration for VieFaucet 4.4 follows the same steps as 4.3 with a minor difference in the notification helper function name.

Step 1 — Open application/controllers/wh.php and add this function:

public function aoytasks()
{
    $secret  = "";  // YOUR SECRET KEY
    $hold    = 3;
    $minHold = 0.5;

    $userId        = isset($_POST['subId'])     ? $this->db->escape_str($_POST['subId'])     : null;
    $transactionId = isset($_POST['transId'])   ? $this->db->escape_str($_POST['transId'])   : null;
    $reward        = isset($_POST['reward'])    ? $this->db->escape_str($_POST['reward'])    : null;
    $action        = isset($_POST['status'])    ? $this->db->escape_str($_POST['status'])    : null;
    $debug         = isset($_POST['debug'])     ? $this->db->escape_str($_POST['debug'])     : "0";
    $userIp        = isset($_POST['userIp'])    ? $this->db->escape_str($_POST['userIp'])    : "0.0.0.0";
    $signature     = isset($_POST['signature']) ? $this->db->escape_str($_POST['signature']) : null;

    $expected = hash_hmac('sha256', ($_POST['transId'] ?? '') . ($_POST['subId'] ?? '') . ($_POST['reward'] ?? ''), $secret);
    if (!is_string($signature) || !hash_equals($expected, $signature)) {
        echo "ERROR: Signature doesn't match";
        return;
    }

    if ($debug == 1) {
        echo "ok";
        return;
    }

    $reward = $reward * $this->data['settings']['currency_rate'];
    $trans  = $this->m_offerwall->getTransaction($transactionId, 'AoyTasks');

    if ($action == 2) {
        $this->m_offerwall->reduceUserBalance($userId, abs($reward));
        $this->m_offerwall->insertTransaction($userId, 'AoyTasks', $userIp, $reward, $transactionId, 1, time());
        echo "ok";
    } else {
        if (!$trans) {
            $hold = ($reward > $minHold) ? 3 : 0;
            if ($hold == 0) {
                $offerId = $this->m_offerwall->insertTransaction($userId, 'AoyTasks', $userIp, $reward, $transactionId, 2, time());
                $this->m_offerwall->updateUserBalance($userId, $reward);
                // Note: 4.4 uses currencyDisplay() instead of currency()
                $this->m_core->addNotification($userId, currencyDisplay($reward, $this->data['settings']) . " from AoyTasks Offer #$offerId was credited.", 1);
                $user = $this->m_core->getUserFromId($userId);
                $this->m_core->addExp($user['id'], $this->data['settings']['offerwall_exp_reward']);
                if (($user['exp'] + $this->data['settings']['offerwall_exp_reward']) >= ($user['level'] + 1) * 100) {
                    $this->m_core->levelUp($user['id']);
                }
            } else {
                $availableAt = time() + $hold * 86400;
                $offerId = $this->m_offerwall->insertTransaction($userId, 'AoyTasks', $userIp, $reward, $transactionId, 0, $availableAt);
                $this->m_core->addNotification($userId, "Your AoyTasks Offer #$offerId is pending approval.", 0);
            }
            echo "ok";
        } else {
            echo "DUP";
        }
    }
}

Steps 2, 3 & 4 — Identical to VieFaucet 4.3. See the section above.

🔗

Postback URL: https://yourdomain.com/wh/aoytasks

CryptoFaucet / ClaimBits Integration

Create the file system/gateways/aoytasks.php and configure your publisher app Secret Key:

<?php
define('BASEPATH', true);
require('../init.php');

$secret = "YOUR_SECRET_KEY";

$userId    = $_POST['subId']     ?? null;
$transId   = $_POST['transId']   ?? null;
$reward    = $_POST['reward']    ?? null;
$status    = $_POST['status']    ?? null;
$debug     = $_POST['debug']     ?? "0";
$signature = $_POST['signature'] ?? null;
$userIp    = $_POST['userIp']    ?? "0.0.0.0";

$expected = hash_hmac('sha256', (string) $transId . (string) $userId . (string) $reward, $secret);
if (!is_string($signature) || !hash_equals($expected, $signature)) {
    echo "ERROR: Signature doesn't match";
    exit;
}

if ($debug == 1) {
    echo "ok";
    exit;
}

if ($status == 2) {
    // Reversal / Chargeback — subtract reward
    // Your reversal logic here
} else {
    // Credit reward to user
    // Your crediting logic here
}

echo "ok";
📌

Currency must match your site balance unit in your publisher app settings.
Postback URL: https://yourdomain.com/system/gateways/aoytasks.php


S2S Postback

S2S Postback

When a user completes an action, AoyTasks sends an HTTPS POST request with a URL-encoded body to your registered Postback URL. Verify its signature before crediting the user.

Postback Parameters

ParameterDescriptionExample
subIdUnique identifier code of the user who completed the action on your platform.user123
transIdUnique identification code of the transaction made by your user.XX-12345678
offer_nameName of the completed offer.AoyTasks - Register and Earn
offer_typeCompletion type (ptc, video, task, shortlink, offer, or survey); test deliveries use test.ptc
rewardAmount of your virtual currency to be credited to your user.1.25
reward_nameThe name of your currency set when you registered your website.Points
reward_valueAmount of your virtual currency credited for $1 worth of payout (Exchange Rate).1000.00
payoutPublisher payout in USD.0.100000
userIpThe user's IP address who completed the action.192.168.1.0
countryCountry (ISO2 form) where the completion came from.US
status1 = credit   2 = reversal / chargeback1
debugCheck if this is a test or live postback call.0 (live) / 1 (test)
signatureHMAC-SHA256 signature authenticated with your app Secret Key.64 lowercase hexadecimal characters
ℹ️

Rewards and payouts are nonnegative decimal strings. For status=2, reverse the matching original credit once. A test postback (debug=1) must never change a balance.

Postback Security

Always verify the signature parameter and sender IP to confirm the postback originates from AoyTasks servers, and match subId to the exact identifier of an existing user on your site.

Server IPs to Allowlist

Accept requests only from our server IPv4 or IPv6 address over HTTPS:

187.127.209.238 2a02:4780:5e:494e::1

Signature Formula

Calculate hash_hmac('sha256', $transId . $subId . $reward, $secretKey) using the received string values in that exact order, then compare with signature using hash_equals:

hash_hmac('sha256', $transId . $subId . $reward, $secretKey)
<?php
$secret    = ""; // Your Secret Key from My Apps

$subId     = $_POST['subId']     ?? '';
$transId   = $_POST['transId']   ?? '';
$reward    = $_POST['reward']    ?? '';
$signature = $_POST['signature'] ?? '';

$expected = hash_hmac('sha256', $transId . $subId . $reward, $secret);
if (!is_string($signature) || !hash_equals($expected, strtolower($signature))) {
    http_response_code(400);
    echo "ERROR: Signature doesn't match";
    exit;
}
?>
⏱️

Delivery uses a 15-second total timeout and a 5-second connection timeout, with up to 12 attempts. Record (transId, status) with a unique database constraint to prevent duplicate credits.

Respond to Postback

Return an HTTP 2xx response (for example outputting ok) after the authenticated event has been recorded and its reward applied atomically. A duplicate authenticated event should also return 2xx without applying the reward again.

http_response_code(200);
echo "ok";

Postback Example

Below is a complete PHP postback example that verifies the sender IP and HMAC-SHA256 signature, acknowledges test postbacks (debug=1) without changing balances, deduplicates events by (transId, status), and processes both credits (status=1) and reversals (status=2):

<?php
$secret = ""; // Your Secret Key from My Apps

// Verify direct connection IP from AoyTasks servers
$allowed_ips = ['187.127.209.238', '2a02:4780:5e:494e::1'];
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
if (!in_array($ip, $allowed_ips, true)) {
    http_response_code(403);
    echo "ERROR: Invalid source";
    exit;
}

// Read postback parameters
$userId     = (string) ($_POST['subId']       ?? '');
$transId    = (string) ($_POST['transId']     ?? '');
$reward     = (string) ($_POST['reward']      ?? '');
$rewardName = (string) ($_POST['reward_name'] ?? '');
$offerName  = (string) ($_POST['offer_name']  ?? '');
$offerType  = (string) ($_POST['offer_type']  ?? '');
$payout     = (string) ($_POST['payout']      ?? '0');
$userIp     = (string) ($_POST['userIp']      ?? '0.0.0.0');
$country    = (string) ($_POST['country']     ?? '');
$status     = (int)    ($_POST['status']      ?? 1);
$debug      = (int)    ($_POST['debug']       ?? 0);
$signature  = (string) ($_POST['signature']   ?? '');

// Validate HMAC-SHA256 signature
$expected = hash_hmac('sha256', $transId . $userId . $reward, $secret);
if (!hash_equals($expected, strtolower($signature))) {
    http_response_code(400);
    echo "ERROR: Signature doesn't match";
    exit;
}

// Acknowledge test postbacks without changing balances
if ($debug === 1) {
    http_response_code(200);
    echo "ok";
    exit;
}

// Handle reversal (status = 2) or credit (status = 1)
if ($status === 2) {
    $rewardAmount = -abs((float) $reward);
} else {
    $rewardAmount = abs((float) $reward);
}

// Prevent duplicates — check if (transId, status) already exists in your database
if (isNewTransaction($transId, $status)) {
    processTransaction($userId, $rewardAmount, $transId, $status);
}

http_response_code(200);
echo "ok";
?>

Use Send Test Postback in your app settings to test your endpoint without crediting a user.


CPA Advertising

CPA Advertising — Overview

CPA means Cost Per Action. You pay only when your backend confirms a real action — such as creating an account or completing a purchase. Opening a page alone does not earn a CPA reward.

ℹ️

To get started, open Advertiser → CPA Advertising → CPA Balance and transfer at least $10.00 from your Purchase Balance. A minimum CPA balance of $10.00 is required to create or resume a campaign.

⚠️

Choose the right integration: An advertiser sends conversions to AoyTasks using a CPA campaign secret and click_id. A publisher receives rewards from AoyTasks using an app Secret Key and transId. These credentials are not interchangeable.

How It Works

Fund your CPA Balance, create a campaign, and submit it for review.
After approval, matching users see your campaign in Offers or Surveys across eligible publisher apps.
When a user clicks, AoyTasks records the click and redirects to your HTTPS destination URL with a unique 32-character click_id.
Your server stores that click_id with the user's account or order, then verifies the required action.
Your backend or measurement provider sends an authenticated S2S postback to https://aoytasks.com/api/v1/cpa/postback.
AoyTasks validates the secret, attribution, caps, and budget. An accepted event debits your CPA Balance once and queues the publisher reward.

Campaign Fields & Click Tracking

Step 1 — Campaign Details

FieldWhat to enterWho sees it
Internal name / noteRequired name up to 128 characters. Optional private note up to 5,000 characters.You and administrators.
Offerwall categoryOffers or Surveys.Matching offerwall category.
Destination URL Public HTTPS URL (up to 2,048 characters, port 443). If {click_id} is omitted, AoyTasks appends ?click_id=....

Supported destination macros:
{click_id} — Unique 32-character lowercase hex token (valid for 30 days).
{sub_id} — Publisher's user identifier.
{campaign_id} — Campaign UUID.
{ip_address} / {country_code} — Click-time IP address and ISO2 country code.
Users visit this URL.
Public title / descriptionRequired title up to 128 characters; description up to 250 characters explaining eligibility and steps.Users and publishers.
Offer image / icon URLOptional upload (250×250 px, JPG/PNG/GIF, up to 500 KB) or public HTTPS square icon URL.Users and publishers.

Example Destination URL

https://your-site.example/signup?click_id={click_id}&member={sub_id}&campaign={campaign_id}&ip={ip_address}&cc={country_code}

Postback / S2S Integration

Endpoint: https://aoytasks.com/api/v1/cpa/postback. Send over HTTPS from your backend or measurement provider (MMP). A browser pixel or page visit does not confirm a conversion.

Method A — Secret Header (Recommended for your own backend)

Copy your secret from Campaign → Integration and send it in the X-Postback-Secret HTTP header. No sender IP allowlist is required for Method A.

curl --get "https://aoytasks.com/api/v1/cpa/postback" \
  --data-urlencode "click_id=SAVED_32_HEX_CLICK_ID" \
  --data-urlencode "event=register" \
  --header "X-Postback-Secret: YOUR_CPA_SECRET"

Method B — Secret Query/Body Parameter (For MMPs)

If your measurement provider cannot send custom HTTP headers, pass secret=YOUR_CPA_SECRET and configure the provider's sending IPv4/IPv6 addresses or CIDRs in Campaign → Integration → Advertiser IP allowlist (up to 100 entries).

https://aoytasks.com/api/v1/cpa/postback?click_id=SAVED_CLICK_ID&event=register&secret=YOUR_CPA_SECRET

Postback Parameters

ParameterRequirementDescription
click_idRequiredExact saved 32-character lowercase hexadecimal token from the click.
eventRequiredExact configured event name (e.g. register, first_purchase).
statusOptionalDefaults to approved. Send rejected to log a nonbillable rejection, or reversed (alias chargeback) to refund a paid conversion.
payoutDynamic onlyPositive decimal USD within your campaign's configured min/max range (ignored for fixed-payout events).
secretMethod B only40-character hexadecimal CPA secret (requires Advertiser IP allowlist).
ip_addressOptionalUser's public conversion-time IP for optional VPN/proxy and country comparison checks.
country_codeOptionalUppercase 2-letter ISO country code at conversion time for country comparison against the click country.

Reversing a Paid Conversion (Chargeback)

curl --get "https://aoytasks.com/api/v1/cpa/postback" \
  --data-urlencode "click_id=ORIGINAL_SAVED_CLICK_ID" \
  --data-urlencode "event=first_purchase" \
  --data-urlencode "status=reversed" \
  --header "X-Postback-Secret: YOUR_CPA_SECRET"

Measurement Providers (MMPs)

When using a measurement provider, pass {click_id} into your provider's passthrough parameter on the destination URL, then map that saved token back to click_id in the provider's callback configuration (AppsFlyer, Adjust, Branch).

Secret Keys & IP Allowlist

Every CPA postback is authenticated with a 40-character lowercase hexadecimal secret key found in Campaign → Integration:

Secret TypeScopeNotes
Campaign SecretOne campaignAuthenticates postbacks only for that specific campaign. Rotating it does not affect other campaigns.
Global SecretAll your CPA campaignsAuthenticates postbacks across all campaigns in your advertiser account.

When using secret= in the query/body (Method B), the sending server's IPv4/IPv6 address or CIDR range must be listed in your Advertiser IP allowlist (up to 100 entries; /0 catch-all ranges are not permitted).

Events & Payouts

Add 1–50 events per campaign. Event names start with a lowercase letter and use lowercase letters, digits, and underscores (up to 64 characters). Each click_id + event combination can be approved once.

EventLabelExample Gross PayoutWhen to send
registerCreate an account$0.10After the account meets your stated requirements.
reach_level_10Reach level 10$0.50After your server confirms the user reached level 10.
first_purchaseMake your first purchase$2.00After a qualifying payment is confirmed.

Fixed Payout: Uses the saved event price (with optional Tier 1 / Tier 2 / Tier 3 regional overrides).
Dynamic Payout: Pass payout on each approval as a positive USD decimal string (up to 8 decimal places, e.g. 1.50000000) within the campaign's saved min/max range.

Caps & Budget Management

Purchase Balance and CPA Balance are separate. Transfers into CPA Balance are one-way (minimum $10.00) and cannot be reversed.

ControlCountsWhen reached
Daily CapApproved events per day (0 = unlimited)Further approvals return HTTP 429 until the next day (UTC).
Lifetime CapTotal approved events (0 = unlimited)Campaign status becomes Completed. Reversals do not reopen cap slots.
CPA BalanceMust cover each gross event payoutInsufficient funds reject approval and pause the campaign. Fund and click Resume manually.

Devices & Countries

Choose All devices or select specific platforms (Desktop, Android, iOS). For countries, choose Worldwide, allow selected countries, or block selected countries. Current minimum gross payouts by tier:

TierMinimum Gross Payout
Tier 1$0.00500000
Tier 2$0.00200000
Tier 3$0.00100000

Platform Fees

Approval debits the gross payout from your CPA Balance. The platform fee comes out of that gross amount (not added on top), and the publisher receives the remainder. Reversals (status=reversed) refund the original gross charge into your CPA Balance.

Gross payout bandCurrent fee
Up to $1.00000000 20%
Above $1.00000000, up to $5.00000000 15%
Above $5.00000000, up to $20.00000000 10%
Above $20.00000000 7%

Workspace & Campaign Status

StatusMeaningNew approvals?
PendingAwaiting admin review.No.
ActiveApproved and running.Yes, subject to all checks.
PausedStopped manually or for insufficient funding.No; fund if needed (≥ $10.00) and resume.
CompletedLifetime cap reached.No.
RejectedAdmin rejected campaign.No; review reason or contact support.

Postback Response Codes

HTTPMeaningNext action
200Accepted event, logged rejection, or reversal.Inspect JSON action; a logged rejection is not a paid approval.
400 / 413 / 426Invalid input, oversized request, or non-HTTPS.Use exact endpoint, scalar parameters, and form-encoded POST or GET query.
401No authentication provided.Send X-Postback-Secret header or secret parameter.
403Wrong secret, unapproved sender IP, or failed network/country check.Check secret scope, Advertiser IP allowlist, and conversion IP/country values.
404Unknown click_id.Ensure {click_id} is in your destination URL and returned unchanged.
409Duplicate event, expired click (30 days), inactive campaign, or insufficient balance.Inspect reason in Postback Log.
422Unknown event name or invalid dynamic payout.Match exact configured event name and decimal payout limits.
429Rate limit (120 req/min) or conversion cap reached.Back off or check daily/lifetime caps.
500 / 503Temporary verification or processing issue.Retain event and retry with backoff using the same click_id and event.

Troubleshooting

Confirm the campaign status is Active, your CPA Balance covers the event payout, and daily/lifetime caps are not full.
Check that the real 32-character click_id was saved with the user's account/order and not sent as a literal macro string.
Confirm your backend sent the exact configured event name and valid CPA secret (plus IP allowlist if using Method B).
Inspect the response and Postback Log in your CPA workspace.

Before Launch Checklist

  • Public title, description, devices, and countries match your actual offer requirements.
  • {click_id} attribution is saved in your database across signup, redirects, and payment.
  • Your backend verifies the completed action before sending the exact configured event name.
  • CPA secrets remain server-side, and any Method B sender IPs are added to your Advertiser IP allowlist.
  • Retries use the same click_id and event so duplicate protection prevents double charges.

Brand

Brand Assets

Download the official AoyTasks logos and AT icon for your website, app, or integration.

Download all assets ZIP
AoyTasks horizontal logo with white and gold lettering
Dark backgrounds

Horizontal logo

White and gold lettering for dark headers and navigation.

AoyTasks horizontal logo with navy and gold lettering
Light backgrounds

Horizontal logo

Navy and bright gold lettering for light headers and navigation.

AoyTasks gold AT monogram icon with violet accent
Light or dark backgrounds

AT icon

The standalone badge for app icons, favicons, and compact spaces.

AoyTasks stacked logo with white and gold lettering
Dark backgrounds

Stacked logo

The AT icon above the wordmark for centered layouts.

AoyTasks stacked logo with navy and gold lettering
Light backgrounds

Stacked logo

The centered logo with lettering suited to light surfaces.

AoyTasks wordmark for dark backgrounds
AoyTasks wordmark for light backgrounds
Two background variants

Wordmark

The AoyTasks name without the icon, supplied as scalable SVGs.

All files have transparent backgrounds; the preview backgrounds are not part of the artwork. Keep the original colors and aspect ratio. Use SVG for crisp website logos and the AT icon at favicon sizes. The complete ZIP includes the supplied PNG sizes and usage notes.