Developer Portal & API Docs
Complete integration architecture for iframe offerwalls, real-time postback webhooks, REST API feeds, and multi-event tracking.
Introduction
Welcome to the WateenX Developer Architecture. Our high-throughput monetization infrastructure allows digital publishers, gaming studios, and GPT rewards platforms to integrate interactive offerwalls and programmatic REST feeds seamlessly.
Our platform supports two primary integration avenues depending on your application requirements:
1. Hosted Offerwall (iFrame)
Zero-backend setup. Embed our responsive web app into your web view or open it in a modal with user attribution tracking.
2. Server-to-Server REST API
Pull raw JSON offer feeds programmatically to render native in-game offerwalls, native mobile cards, and customized reward studios.
Authentication & Security
Each registered property is provisioned with a cryptographically generated API Key and Secret Key. All API endpoints and webhook verification mechanisms rely on these credentials.
Secret Key in client-side applications, mobile APKs, or public GitHub repositories. Use it strictly on your backend servers to verify postback signatures or query API feeds.
IP Whitelisting (Optional)
For enhanced protection against compromised credentials, you can configure allowed outbound server IP addresses inside your property settings. If enabled, any API calls originating outside your designated IP whitelist will be rejected with HTTP 403 Forbidden.
Hosted Offerwall & iFrame
The hosted offerwall provides a responsive user interface with built-in device filtering, localized translations, offer sorting, and immediate transaction tracking.
Direct URL Format
https://wateenx.com/offerwall/pub_live_xxxxxxxxxxxxxxxxxxxx/[USER_ID]
Replace [USER_ID] with your application's unique user identifier (e.g. database ID, username, or sub-account identifier). This value is preserved across all clicks and passed back in webhook callbacks as {subId}.
HTML iFrame Embedding Code
<!-- WateenX Responsive Offerwall Frame -->
<iframe
src="https://wateenx.com/offerwall/pub_live_xxxxxxxxxxxxxxxxxxxx/USER_ID_HERE"
width="100%"
height="900px"
frameborder="0"
scrolling="yes"
style="border: none; border-radius: 16px; box-shadow: 0 10px 30px rgba(0,0,0,0.06);">
</iframe>
Server-to-Server Postback Webhooks
A postback is an asynchronous, server-to-server HTTP request sent automatically by WateenX to your callback script whenever a user finishes an offer or survey.
Supported Macro Parameter Tokens
You can embed any of the following macros in your postback URL. Our dispatch engine replaces each token with live conversion parameters:
| Token | Type | Description | Example |
|---|---|---|---|
| {subId} | string | The User ID you originally passed in the tracking URL. | usr_98421 |
| {transId} | string | Global unique transaction identifier used for idempotency and deduplication. | TX_784920194 |
| {reward} | float | The rounded virtual points amount to credit to the user's account balance. | 250.00 |
| {payout} | float | The publisher's cash revenue in USD ($). | 1.4500 |
| {status} | integer | 1 = Verified Conversion (credit user), 2 = Chargeback/Reversal (debit user). |
1 |
| {signature} | string | Cryptographic MD5 verification hash generated using your secret key. | d41d8cd98f00b204... |
| {offer_id} | string | Unique identifier of the completed advertiser offer. | 1042 |
| {offer_name} | string | Clean title of the completed campaign or survey. | Raid: Shadow Legends |
| {userIp} | string | IP address of the end-user at the time of completion. | 192.0.2.1 |
| {country} | string | ISO 2-letter uppercase country code (e.g. US, GB, DE). | US |
| {event_id} | string | Multi-step goal ID for tiered progression campaigns. | lvl_10 |
200 OK and a plain text response body containing 1 or OK. If your server returns an error or times out, our retry cron automatically re-attempts delivery with exponential backoff up to 10 times.
Signature Verification
To guarantee that incoming webhooks are authentic and sent by WateenX (and not spoofed by malicious third parties), you must verify the {signature} parameter using your secret key.
Includes payout and transaction status for comprehensive verification.
md5(subId + transId + reward + payout + status + secret_key)
Legacy signature format supported for backward compatibility.
md5(subId + transId + reward + secret_key)
Multi-Language Verification Snippets
<?php
// Your property secret key
$SECRET_KEY = "sec_live_xxxxxxxxxxxxxxxxxxxxxxxx";
// Receive GET or POST parameters
$subId = $_REQUEST['subId'] ?? '';
$transId = $_REQUEST['transId'] ?? '';
$reward = $_REQUEST['reward'] ?? '';
$payout = $_REQUEST['payout'] ?? '';
$status = $_REQUEST['status'] ?? '';
$signature = $_REQUEST['signature'] ?? '';
// Compute expected V2 MD5 signature
$expectedSig = md5($subId . $transId . $reward . $payout . $status . $SECRET_KEY);
if (hash_equals($expectedSig, $signature)) {
// Signature is valid! Check if transaction already credited
if ($status == 1) {
// Credit user $subId with $reward points
} elseif ($status == 2) {
// Reversal / Chargeback: deduct points
}
echo "OK";
} else {
http_response_code(403);
echo "INVALID_SIGNATURE";
}
const express = require('express');
const crypto = require('crypto');
const app = express();
const SECRET_KEY = 'sec_live_xxxxxxxxxxxxxxxxxxxxxxxx';
app.get('/api/postback', (req, res) => {
const { subId, transId, reward, payout, status, signature } = req.query;
// Calculate V2 hash
const payload = `\${subId}\${transId}\${reward}\${payout}\${status}\${SECRET_KEY}`;
const expected = crypto.createHash('md5').update(payload).digest('hex');
if (expected.toLowerCase() === (signature || '').toLowerCase()) {
// Credit user
return res.status(200).send('OK');
}
return res.status(403).send('INVALID_SIGNATURE');
});
from flask import Flask, request, abort
import hashlib
app = Flask(__name__)
SECRET_KEY = "sec_live_xxxxxxxxxxxxxxxxxxxxxxxx"
@app.route('/api/postback', methods=['GET', 'POST'])
def handle_postback():
sub_id = request.args.get('subId', '')
trans_id = request.args.get('transId', '')
reward = request.args.get('reward', '')
payout = request.args.get('payout', '')
status = request.args.get('status', '')
signature = request.args.get('signature', '')
# Calculate V2 hash
payload = f"{sub_id}{trans_id}{reward}{payout}{status}{SECRET_KEY}"
expected = hashlib.md5(payload.encode('utf-8')).hexdigest()
if expected.lower() == signature.lower():
# Credit user
return "OK", 200
return "INVALID_SIGNATURE", 403
REST API Offers Feed
For publishers creating custom native mobile apps or tailored reward lobbies, query our real-time offer inventory programmatically via our JSON REST endpoint.
Query Parameters
| Parameter | Status | Type | Description |
|---|---|---|---|
| user_id | Required | string | Unique identifier of your player/user for click attribution. |
| ip | Optional | string | Client's remote IP address to detect geo-location targeting. |
| user_agent | Optional | string | Browser or client User-Agent string to filter mobile/desktop targeting. |
| device | Optional | string | Device filter: all, mobile, or desktop. |
| os | Optional | string | Operating system filter: all, android, ios, windows. |
| category | Optional | string | Category filter: games, surveys, apps, free-trials. |
| min_payout | Optional | float | Only return campaigns with a publisher payout greater than or equal to this USD value. |
| limit | Optional | integer | Max offers returned per request (Default: 50, Max: 100). |
Multi-Language API Request Examples
curl -X GET "https://wateenx.com/api/v1/offers?user_id=usr_12345&device=mobile&limit=30" \
-H "X-API-Key: pub_live_xxxxxxxxxxxxxxxxxxxx" \
-H "X-API-Secret: sec_live_xxxxxxxxxxxxxxxxxxxxxxxx"
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://wateenx.com/api/v1/offers?user_id=usr_12345&limit=25",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-API-Key: pub_live_xxxxxxxxxxxxxxxxxxxx",
"X-API-Secret: sec_live_xxxxxxxxxxxxxxxxxxxxxxxx",
"Accept: application/json"
]
]);
$response = curl_exec($ch);
$data = json_decode($response, true);
curl_close($ch);
const response = await fetch('https://wateenx.com/api/v1/offers?user_id=usr_12345&limit=25', {
method: 'GET',
headers: {
'X-API-Key': 'pub_live_xxxxxxxxxxxxxxxxxxxx',
'X-API-Secret': 'sec_live_xxxxxxxxxxxxxxxxxxxxxxxx',
'Accept': 'application/json'
}
});
const result = await response.json();
console.log(result.data);
import requests
headers = {
'X-API-Key': 'pub_live_xxxxxxxxxxxxxxxxxxxx',
'X-API-Secret': 'sec_live_xxxxxxxxxxxxxxxxxxxxxxxx'
}
params = {
'user_id': 'usr_12345',
'limit': 25
}
res = requests.get('https://wateenx.com/api/v1/offers', headers=headers, params=params)
data = res.json()
Standard JSON Response Example
{
"success": true,
"total_offers": 48,
"page": 1,
"limit": 25,
"data": [
{
"id": "1492",
"name": "Raid: Shadow Legends",
"description": "Install the game, open two sacred shards within 14 days.",
"instructions": "New users only. Reach Level 10 and open shards.",
"category": "Games",
"payout": 28.5000,
"reward": 28500.00,
"currency_name": "Points",
"image": "https://wateenx.com/assets/img/offers/raid.png",
"os": "android",
"countries": ["US", "CA", "GB", "DE"],
"click_url": "https://wateenx.com/click/a849fbc8921e..."
}
]
}
Interactive Postback URL Builder
Use this real-time builder to construct a formatted callback URL with all necessary conversion macros. Copy the result and paste it into your property settings in the Web Properties portal.