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.
- Create a placement — your app or website on Placements. You get a placement ID (15 letters/numbers) and choose your currency name and rate.
- 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.
- 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.
https://gamwall.com/wall/wgvd372dty32dvb?user_id=USER_123
| Parameter | Description | Example |
|---|---|---|
/wall/{placement} | Your placement ID (in the path) | wgvd372dty32dvb |
user_id required | Your user's unique ID — comes back as {user_id} | USER_123 |
sub1, sub2 optional | Anything you want to track (traffic source, campaign…). Only added when you send them; they come back as {sub1} / {sub2}. |
iFrame embed
Embed the offerwall inside your website.
<iframe src="https://gamwall.com/wall/wgvd372dty32dvb?user_id=USER_123"
width="100%" height="800" frameborder="0"
style="border:none;border-radius:16px"></iframe>Direct offer links
Promote one offer anywhere (button, banner, social post). Make the link on Offers → Promote. A link always needs a placement — that's where the conversion and postback go. Sub IDs are optional.
https://gamwall.com/api/offers/click?offerId=owshgdsw732evew623&userId=USER_123&placementId=wgvd372dty32dvb&sub1=facebook
| Parameter | Required | What it is |
|---|---|---|
offerId | Yes | The offer's ID (18 characters) — copy it from Offers |
placementId | Yes | Your placement's ID (15 characters) — no placement, no click |
userId | Recommended | Your user's ID — comes back in the postback as {user_id} |
sub1, sub2 | Optional | Your own tracking values — added only when you send them |
Every click gets its own click ID starting with clk_ followed by 14 random letters and numbers (e.g. clk_73264dery237eg) — it comes back as {click_id}.
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.
click_id + goal_id you already processed.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}| Macro | Description | Example |
|---|---|---|
{user_id} | Your user's ID from the link (also {subid1}) | USER_123 |
{sub1} | Optional Sub ID 1 you added (also {subid2}) | |
{sub2} | Optional Sub ID 2 you added (also {subid3}) | banner_a |
{placement_id} | The placement the click came from | wgvd372dty32dvb |
{offer_id} | Offer ID | owshgdsw732evew623 |
{offer_name} | Completed offer name | Coin Master |
{payout} | Your payout in USD | 0.75 |
{currency_amount} | Reward in your currency | 75 |
{currency_name} | Your currency name | Coins |
{click_id} | Unique click ID — use it for duplicate checks | clk_73264dery237eg |
{conversion_id} | Unique conversion ID (number) | 93822 |
{status} | approved or chargeback | approved |
{goal_id} | Multi-step goal ID (empty for single-step) | 12 |
{goal_title} | Multi-step goal name | Reach level 10 |
{step_number} | Multi-step sequence number | 2 |
{ip_address} | User IP at click time | 203.0.113.7 |
{country} | User country (2 letters) | US |
{signature} | Optional HMAC-SHA256 signature — see Securing postbacks | a3f1c9… |
{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.
1 — Add the signature macro
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:
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
$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
// 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
// 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']);
}{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.
{
"success": true,
"message": "Reward added successfully"
}{
"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.
GET https://gamwall.com/api/stats?api_key=YOUR_API_KEY&range=7d
| Parameter | Required | Description |
|---|---|---|
api_key | Yes | Your API key |
range | No | today (default), yesterday, 7d, 30d, month or all |
offer | No | Only this offer (offer ID) |
placement | No | Only this placement (placement ID) |
Response
{
"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.
GET https://gamwall.com/api/feed/wgvd372dty32dvb?api_key=YOUR_FEED_KEY&country=US
| Parameter | Required | Description |
|---|---|---|
/api/feed/{placement} | Yes | Your placement ID (in the path) |
api_key | Yes | That placement's Feed API key |
device | No | android, ios or desktop |
country | No | Comma-separated ISO codes, e.g. US,CA |
Response
{
"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
