> ## Documentation Index
> Fetch the complete documentation index at: https://playcamp.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# WebView Test Mode

> How to use test mode to verify WebView integration in the live environment

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.

<Warning>
  Test mode **does not apply to coupons**. Redeeming a coupon in test mode will consume the actual coupon.
</Warning>

## 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** — all statuses except `COMPLETED`, `CANCELLED` |
| Campaign detail              | **Real DB query**                                                |
| Coupons                      | **Not applied** — real coupons are consumed                      |
| WebView UI                   | Purple "TEST MODE" banner at the top                             |

## Flow

```mermaid theme={null}
sequenceDiagram
    participant S as Game Server
    participant P as PlayCamp SDK API
    participant W as WebView

    S->>P: Issue OTT (isTest: true)
    P-->>S: Return OTT
    S-->>W: Pass OTT → Open WebView
    Note over W: Purple TEST MODE banner shown
    W->>P: Search creators → Mock data returned
    W->>P: Register boost
    P-->>S: Webhook sent (_isTestData: true)
    Note over S: Webhook received, no DB write
```

## 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.

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    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
      }'
    ```
  </Tab>

  <Tab title="Node SDK">
    ```typescript theme={null}
    const { ott } = await server.webview.createOtt({
      userId: 'user-123',
      campaignId: 'camp-abc',
      isTest: true,
    });
    ```
  </Tab>

  <Tab title="Go SDK">
    ```go theme={null}
    result, err := server.Webview.CreateOTT(ctx, playcamp.WebviewOttParams{
        UserID:     "user-123",
        CampaignID: "camp-abc",
        IsTest:     true,
    })
    ```
  </Tab>
</Tabs>

<Note>
  `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.
</Note>

## 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, campaigns from **draft/review stages** are also visible:

| Mode   | Allowed                                                                             | Blocked                  |
| ------ | ----------------------------------------------------------------------------------- | ------------------------ |
| Normal | `IN_PROGRESS`, `COMPLETED`                                                          | All others               |
| Test   | `DRAFT`, `PENDING_REVIEW`, `REJECTED`, `PENDING_EXPOSURE`, `EXPOSED`, `IN_PROGRESS` | `COMPLETED`, `CANCELLED` |

This allows WebView QA from the draft stage (`DRAFT`) through pre-launch (`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:

```json theme={null}
{
  "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:

<Tabs>
  <Tab title="Node.js">
    ```typescript theme={null}
    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 });
    });
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    for _, evt := range payload.Events {
        if evt.Data.IsTestData {
            log.Printf("[TEST] %s: %+v", evt.Event, evt.Data)
            continue
        }

        // Production handling logic
    }
    ```
  </Tab>
</Tabs>

Applies to events: `sponsor.created`, `sponsor.changed`, `sponsor.ended`

<Warning>
  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`.
</Warning>

## 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](/guides/developers/game-integration/test-mode#integration-completion)

## Related Pages

* [WebView + Webhook Integration](/guides/developers/game-integration/cases/webview-webhook) — Full WebView integration flow
* [WebView Integration](/guides/developers/game-integration/webview) — OTT issuance, URL configuration, security details
* [Webhook Events](/guides/developers/game-integration/webhook) — Webhook reception and signature verification
* [Test Mode](/guides/developers/game-integration/test-mode) — Server/Client API isTest usage
