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

# ZBD Widget

> Embed a hosted cashout experience so your users can withdraw earned balances to bank accounts, Cash App, and more.

## Overview

The ZBD Widget is an embeddable iframe that handles the full cashout flow for your users — identity verification (KYC), bank account linking (Plaid), and ACH payouts. Your backend handles user creation, session minting, and balance funding; the widget handles everything else.

## Prerequisites

Before integrating:

1. Make sure you already have a [ZBD Developer Dashboard account](/get-started/create-account) and a [project](/get-started/create-project).
2. Copy the project API key from the project's [API section](/get-started/api-keys).
3. Open the **Widget** tab in the Developer Dashboard to configure sandbox balance and webhook settings.
4. If the Widget tab is not available yet, contact ZBD support to enable it for your project.

After that, fund the sandbox account before you try to cash out.

## Quick Start

To get sandbox running quickly, start with the [sandbox guide](/widget/sandbox):

1. Create a sandbox user.
2. Fund the sandbox user.
3. Create a widget session.
4. Embed the returned `widget_url` in your frontend.
5. Listen for widget events and webhook deliveries.

## Integration Flow

```
1. Create User        POST /api/v1/widget/users                (your server → ZBD API)
2. Fund User          POST /api/v1/widget/users/fund           (your server → ZBD API)
3. Deplete User       POST /api/v1/widget/users/deplete        (your server → ZBD API)
4. Get Balance        GET /api/v1/widget/users/{userId}/balance (your server → ZBD API)
5. Create Session     POST /api/v1/widget/users/session        (your server → ZBD API)
6. Embed Widget       <iframe src="{widget_url}" />            (your frontend)
7. Listen for Events  window.addEventListener("message", ...)  (your frontend)
```

Use `POST /api/v1/widget/users/deplete` when your server needs to debit points back from a widget user's point balance.

## Events

The ZBD Widget emits browser events to your frontend and server webhooks to your backend.

<CardGroup cols={2}>
  <Card title="Browser Events" icon="window" href="/widget/browser-events">
    Handle iframe callbacks in your frontend.
  </Card>

  <Card title="Server Webhooks" icon="webhook" href="/widget/webhooks">
    Process signed backend webhook deliveries.
  </Card>
</CardGroup>

## Authentication

Widget endpoints use two auth patterns:

| Context                 | Auth                    | Header                                  |
| ----------------------- | ----------------------- | --------------------------------------- |
| **Your server → ZBD**   | Publisher API key       | `apikey: YOUR_API_KEY`                  |
| **Widget iframe → ZBD** | Session JWT (automatic) | `Authorization: Bearer {session_token}` |

<Warning>Never expose your publisher API key in the browser. Steps 1–3 must happen on your server.</Warning>

## Embedding the Widget

After creating a session, load the returned `widget_url` in your client. Your backend should create the session; your game or web client only receives the `widget_url`.

<Tabs>
  <Tab title="Web">
    ```html theme={null}
    <iframe
      src="https://widget.zbd.gg/?session_token=eyJhbGci..."
      style="width: 100%; height: 600px; border: none;"
      allow="camera; microphone"
      sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-downloads"
    ></iframe>
    ```
  </Tab>

  <Tab title="Unity">
    Use a native WebView package for your Unity target and load the `widget_url` returned by your backend.

    ```csharp theme={null}
    using UnityEngine;

    public class ZbdWidgetLauncher : MonoBehaviour
    {
        [SerializeField] private GameObject webViewContainer;

        public void OpenWidget(string widgetUrl)
        {
            // Replace this with your Unity WebView package API.
            var webView = webViewContainer.GetComponent<IWebView>();
            webView.LoadUrl(widgetUrl);
            webView.SetVisible(true);
        }
    }

    public interface IWebView
    {
        void LoadUrl(string url);
        void SetVisible(bool visible);
    }
    ```
  </Tab>

  <Tab title="Unreal">
    Enable Unreal's **Web Browser** plugin, add a Web Browser widget to your UMG screen, and load the `widget_url` returned by your backend.

    ```cpp theme={null}
    #include "Components/WebBrowser.h"

    void UCashoutScreen::OpenZbdWidget(const FString& WidgetUrl)
    {
        if (ZbdWidgetBrowser)
        {
            ZbdWidgetBrowser->LoadURL(WidgetUrl);
        }
    }
    ```
  </Tab>
</Tabs>

<Warning>
  **Allow document downloads.** The widget lets users download documents (disclosure PDFs, cashout receipts/statements). Browsers only permit a framed page to start a download if the iframe explicitly allows it. If you apply a `sandbox` attribute — as in the example above — it **must** include **`allow-downloads`** (alongside `allow-scripts allow-same-origin allow-forms allow-popups`). Without `allow-downloads`, the browser blocks the in-frame download and the widget falls back to opening the document in a **new browser tab**. If you do not set a `sandbox` attribute at all, downloads work by default.
</Warning>

## Embed Parameters

Pass these as URL query parameters on the widget URL:

| Parameter       | Required | Description                                                     |
| --------------- | -------- | --------------------------------------------------------------- |
| `session_token` | Yes      | JWT from Create Session                                         |
| `flow`          | No       | `cashout` (default), `kyc`, `add-method`                        |
| `theme`         | No       | `zbd-default`, `zbd-light`                                      |
| `embed`         | No       | `true` for chrome-less mode (no header/footer)                  |
| `component`     | No       | `balance`, `history`, `method-picker` for standalone components |
