Before a campaign goes live, you can verify that WebView integration works correctly in the live environment. In test mode, no data is written to the database, but webhooks are sent in real time — so you can verify your game server’s webhook handling end-to-end.
Test mode does not apply to coupons. Redeeming a coupon in test mode will consume the actual coupon.
How It Works
| Feature | Test Mode Behavior |
|---|
| Creators | Returns mock data (TEST1, TEST2, TEST3) |
| Boost register/change/remove | Mock response + real webhook sent (no DB write) |
| Boost status query | Stored in session — persists after registration |
| Campaign list | Real DB query — includes PENDING_EXPOSURE, EXPOSED |
| Campaign detail | Real DB query |
| Coupons | Not applied — real coupons are consumed |
| WebView UI | Purple “TEST MODE” banner at the top |
Flow
Step 1: Add isTest: true to OTT Issuance
When issuing an OTT from the game server, add isTest: true to put the entire session into test mode.
curl -X POST "https://sdk-api.playcamp.io/v1/server/webview/ott" \
-H "Authorization: Bearer {SERVER_KEY}" \
-H "Content-Type: application/json" \
-d '{
"userId": "user-123",
"campaignId": "camp-abc",
"isTest": true
}'
const { ott } = await server.webview.createOtt({
userId: 'user-123',
campaignId: 'camp-abc',
isTest: true,
});
result, err := server.Webview.CreateOTT(ctx, playcamp.WebviewOttParams{
UserID: "user-123",
CampaignID: "camp-abc",
IsTest: true,
})
isTest propagates from OTT to the session and persists for the session’s lifetime. It cannot be set from the WebView URL or client-side — it must be set at OTT issuance using the Server API Key.
Step 2: Test in the WebView
When entering the test mode WebView, a purple TEST MODE banner is displayed at the top.
Campaign List
In normal mode, only IN_PROGRESS and COMPLETED campaigns are shown. In test mode, pre-launch campaigns are also visible:
| Mode | Displayed Statuses |
|---|
| Normal | IN_PROGRESS, COMPLETED |
| Test | PENDING_EXPOSURE, EXPOSED, IN_PROGRESS, COMPLETED |
This allows WebView QA even before a campaign goes live (EXPOSED, PENDING_EXPOSURE).
Creators
In test mode, fixed mock creators are returned:
| creatorKey | creatorName | status |
|---|
TEST1 | [Mock] Alpha | TEST |
TEST2 | [Mock] Bravo | TEST |
TEST3 | [Mock] Charlie | TEST |
Boost
When registering/changing/removing a boost:
- DB write: None
- Response: Mock data
- Webhook: Actually sent (includes
_isTestData: true)
- Session state: Stored in Redis session, persists across page refreshes
Step 3: Handle _isTestData in Webhooks
Webhooks from test mode include an _isTestData: true field:
{
"events": [
{
"event": "sponsor.created",
"data": {
"userId": "user-123",
"campaignId": "camp-abc",
"creatorKey": "TEST1",
"_isTestData": true
},
"timestamp": "2026-04-16T05:00:00.000Z",
"callbackId": "..."
}
]
}
Check _isTestData in your webhook handler to distinguish test webhooks from real ones:
app.post('/webhooks/playcamp', (req, res) => {
for (const { event, data } of req.body.events) {
if (data._isTestData) {
console.log(`[TEST] ${event}`, data);
continue;
}
// Production handling logic
}
res.json({ received: true });
});
for _, evt := range payload.Events {
if evt.Data.IsTestData {
log.Printf("[TEST] %s: %+v", evt.Event, evt.Data)
continue
}
// Production handling logic
}
Applies to events: sponsor.created, sponsor.changed, sponsor.ended
If campaignId is not specified when issuing the OTT, the webhook payload’s campaignId will be set to the literal string 'TEST_CAMPAIGN'. If your game server tries to look up a campaign with this value, it will get a 404. Skip campaignId lookups for webhooks where _isTestData: true.
Important Notes
- Coupons are not affected by test mode: Redeeming a coupon in test mode consumes the actual coupon
- Sandbox vs Live: Test mode is safe to use in the live environment. It can be used alongside the sandbox environment
- Integration verification: Calls with
isTest: true count toward integration completion requirements
Related Pages