Docs

Integration docs

Everything you need to connect your app or website to Gamwall: offerwall, postbacks, signatures and APIs.

Getting started

Three steps from sign-up to your first paid conversion. Everything below goes into detail.

  1. Create a placement — your app or website on Placements. You get a placement ID (15 letters/numbers) and choose your currency name and rate.
  2. Set your postback URL — on the same placement page. We call it every time one of your users completes an offer, so you can credit them. See Postback setup.
  3. Show the offerwall — open the offerwall link in your app, or embed it on your site, with your user's ID.

Offerwall link

Open this URL in a browser or WebView. Everything loads from your placement ID (15 letters/numbers, on Placements) — offers, currency, postback. Add your own user's ID.

URL
https://gamwall.com/wall/wgvd372dty32dvb?user_id=USER_123
ParameterDescriptionExample
/wall/{placement}Your placement ID (in the path)wgvd372dty32dvb
user_id requiredYour user's unique ID — comes back as {user_id}USER_123
sub1, sub2 optionalAnything you want to track (traffic source, campaign…). Only added when you send them; they come back as {sub1} / {sub2}.facebook

iFrame embed

Embed the offerwall inside your website.

HTML
<iframe src="https://gamwall.com/wall/wgvd372dty32dvb?user_id=USER_123"
        width="100%" height="800" frameborder="0"
        style="border:none;border-radius:16px"></iframe>

Postback setup

Set a postback URL on your placement. We call it server-to-server on every conversion and every chargeback, replacing the macros below.

Postbacks come from our server, not the user's browser — ad blockers can't stop them. Always check the request on your server before you credit a reward, and reject a click_id + goal_id you already processed.
URL
https://yourwebsite.com/postback.php?user_id={user_id}&offer={offer_name}&payout={payout}&reward={currency_amount}&click_id={click_id}&status={status}&placement={placement_id}&sub1={sub1}&goal_id={goal_id}
MacroDescriptionExample
{user_id}Your user's ID from the link (also {subid1})USER_123
{sub1}Optional Sub ID 1 you added (also {subid2})facebook
{sub2}Optional Sub ID 2 you added (also {subid3})banner_a
{placement_id}The placement the click came fromwgvd372dty32dvb
{offer_id}Offer IDowshgdsw732evew623
{offer_name}Completed offer nameCoin Master
{payout}Your payout in USD0.75
{currency_amount}Reward in your currency75
{currency_name}Your currency nameCoins
{click_id}Unique click ID — use it for duplicate checksclk_73264dery237eg
{conversion_id}Unique conversion ID (number)93822
{status}approved or chargebackapproved
{goal_id}Multi-step goal ID (empty for single-step)12
{goal_title}Multi-step goal nameReach level 10
{step_number}Multi-step sequence number2
{ip_address}User IP at click time203.0.113.7
{country}User country (2 letters)US
{signature}Optional HMAC-SHA256 signature — see Securing postbacksa3f1c9…

{goal_id}, {goal_title} and {step_number} are only sent for multi-step offers (e.g. Install → Reach level 10 → Reach level 50). For normal single-step offers they are empty.

Securing postbacks optional

Anyone who guesses your postback URL could send a fake postback to credit themselves. To stop this, we can sign every postback with a secret key that only you and Gamwall know. A forged postback won't have a valid signature, so you reject it. If you don't add {signature}, postbacks keep working as before.

Your secret key is on the placement's page under Keys. Each placement has its own key. Never share it or put it in browser/app code.

1 — Add the signature macro

URL
https://yourwebsite.com/postback.php?click_id={click_id}&user_id={user_id}&sub1={sub1}&offer_id={offer_id}&payout={payout}&reward={currency_amount}&status={status}&goal_id={goal_id}&sig={signature}

2 — How the signature is built

HMAC-SHA256 over these values joined by |, in this exact order, using your placement's secret key:

Code
click_id | user_id | sub1 | offer_id | payout | currency_amount | status | goal_id

The order and values must match exactly — including goal_id (an empty string for single-step offers).

3 — Verify it on your server (PHP)

PHP
<?php
$secret = 'YOUR_SECRET_KEY';

$base = implode('|', [
    $_GET['click_id'] ?? '',
    $_GET['user_id'] ?? '',
    $_GET['sub1'] ?? '',
    $_GET['offer_id'] ?? '',
    $_GET['payout'] ?? '',
    $_GET['reward'] ?? '',
    $_GET['status'] ?? '',
    $_GET['goal_id'] ?? '',
]);
$expected = hash_hmac('sha256', $base, $secret);

if (!hash_equals($expected, $_GET['sig'] ?? '')) {
    http_response_code(403);
    exit('invalid signature');
}
// Signature OK — safe to credit the user.

Test it before going live: on your placement page click Test postback. If your URL has {signature}, the test carries a real, correctly signed value.

Sample code

Plain PHP

PHP
<?php
// postback.php — receives conversion postbacks from Gamwall
$user_id       = $_GET['user_id'] ?? '';
$reward        = (float)($_GET['reward'] ?? 0);
$conversion_id = ($_GET['click_id'] ?? '') . ':' . ($_GET['goal_id'] ?? '');
$status        = strtolower($_GET['status'] ?? '');

if ($user_id === '' || $conversion_id === '') {
    http_response_code(400);
    exit(json_encode(['success' => false, 'message' => 'Missing parameters']));
}

// 1) Duplicate check — always by conversion_id
$existing = db_find_conversion($conversion_id);   // your own lookup
if ($existing && $existing['status'] === $status) {
    exit(json_encode(['success' => false, 'message' => 'Duplicate transaction']));
}

// 2) Credit or take back
if ($status === 'approved')   credit_user($user_id, $reward);
if ($status === 'chargeback') deduct_user($user_id, $reward);

// 3) Save the conversion
save_conversion($conversion_id, $user_id, $reward, $status);
echo json_encode(['success' => true, 'message' => 'Reward added successfully']);

Laravel

Code
// routes/web.php
Route::get('/postback/gamwall', [PostbackController::class, 'gamwall']);

// app/Http/Controllers/PostbackController.php
public function gamwall(Request $request)
{
    $userId = $request->query('user_id');
    $reward = (float) $request->query('reward', 0);
    $convId = $request->query('click_id') . ':' . $request->query('goal_id', '');
    $status = strtolower($request->query('status', ''));

    if (!$userId || !$convId) {
        return response()->json(['success' => false, 'message' => 'Missing parameters'], 400);
    }
    $existing = Conversion::where('conversion_id', $convId)->first();
    if ($existing && $existing->status === $status) {
        return response()->json(['success' => false, 'message' => 'Duplicate transaction']);
    }
    $user = User::findOrFail($userId);
    $status === 'chargeback' ? $user->decrement('balance', $reward) : $user->increment('balance', $reward);

    Conversion::updateOrCreate(['conversion_id' => $convId], ['user_id' => $userId, 'reward' => $reward, 'status' => $status]);
    return response()->json(['success' => true, 'message' => 'Reward added successfully']);
}
Key duplicate checks on {click_id} + {goal_id}, never on user + offer — multi-step offers send several postbacks per user. A chargeback reverses an earlier approved conversion, so your endpoint must be able to take coins back.

Response examples

Return HTTP 200 for anything you handled. Any 2xx counts as delivered; other codes are retried.

JSON
{
  "success": true,
  "message": "Reward added successfully"
}
JSON
{
  "success": false,
  "message": "Duplicate transaction"
}

Stats API

Read your own clicks, conversions and revenue from your server — no login, just your API key from Settings. Read-only: it can never change your tracking, postbacks or payouts.

Code
GET https://gamwall.com/api/stats?api_key=YOUR_API_KEY&range=7d
ParameterRequiredDescription
api_keyYesYour API key
rangeNotoday (default), yesterday, 7d, 30d, month or all
offerNoOnly this offer (offer ID)
placementNoOnly this placement (placement ID)

Response

JSON
{
  "success": true,
  "range": "7d",
  "date_from": "2026-09-24",
  "date_to": "2026-09-30",
  "stats": {
    "clicks": 512,
    "approved_conversions": 38,
    "pending_conversions": 6,
    "reversed_conversions": 1,
    "revenue": 94.60,
    "cvr_percent": 7.42,
    "epc": 0.1848
  },
  "by_offer": [
    { "offer_id": "owshgdsw732evew623", "name": "Audible - IT - CPE", "clicks": 120, "conversions": 14, "revenue": 41.30 }
  ]
}

by_offer lists your top 10 offers by revenue and is left out when you ask for one offer. Days are Bangladesh days (Asia/Dhaka, 12:00 AM → 12:00 AM). Revenue counts approved conversions only. Errors: 401 missing/invalid key · 403 account inactive or API disabled.

Offers Feed API

Pull every active offer for one placement into your own backend instead of using the hosted offerwall. The shape follows the common VortexWall-style feed. Find the Feed API key on the placement page — it's separate from your postback secret.

Code
GET https://gamwall.com/api/feed/wgvd372dty32dvb?api_key=YOUR_FEED_KEY&country=US
ParameterRequiredDescription
/api/feed/{placement}YesYour placement ID (in the path)
api_keyYesThat placement's Feed API key
deviceNoandroid, ios or desktop
countryNoComma-separated ISO codes, e.g. US,CA

Response

JSON
{
  "success": true,
  "placement": "wgvd372dty32dvb",
  "count": 1,
  "data": [
    {
      "id": "owshgdsw732evew623",
      "name": "Audible - IT - CPE - INCENT",
      "description": { "en": "..." },
      "payout": 1.50,
      "reward": 150,
      "currency": "Coins",
      "events": [ { "eventId": "1", "action": { "en": "Complete offer" }, "payout": 1.50, "reward": 150 } ],
      "multiEvent": false,
      "icon": "https://…/icon.png",
      "category": "Entertainment",
      "country": ["IT"],
      "device": [],
      "dailyCap": null,
      "fastpay": false,
      "url": "https://gamwall.com/api/offers/click?offerId=owshgdsw732evew623&userId=[USER_ID]&placementId=wgvd372dty32dvb"
    }
  ]
}

Replace [USER_ID] in each url with your user's ID. An empty country or device list means no restriction. Offers you blocked never appear. Errors: 401 invalid placement/key · 403 placement inactive or feed disabled.

FastPay offers

Most offers are paid NET-30: a month's earnings are due 30 days after the month ends. FastPay offers are paid weekly: a week runs Saturday → Friday and is due right when it ends.

FastPay offers live on their own FastPay page. Tracking, postbacks, signatures and caps work exactly the same — only the payment timing changes. On Payments you can filter NET-30 and FastPay payouts; earnings are never counted in both.

Best practices

  • Validate postbacks on your server
  • Reject duplicate conversion IDs
  • Use HTTPS only
  • Keep a log of every postback
  • Check payout amounts
  • Handle chargebacks (take coins back)
  • Don't put an iframe inside an iframe
  • Use a mobile-friendly layout