diff --git a/widget.mdx b/widget.mdx
index 442d40b..9e35b9e 100644
--- a/widget.mdx
+++ b/widget.mdx
@@ -5,7 +5,7 @@ description: "Embed a hosted cashout experience so your users can withdraw earne
## 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.
+The ZBD Widget is an embeddable iframe that runs the cashout experience for your users — OTP verification, identity verification, bank account linking, and bank payouts. Your backend creates widget users, funds their point balances, creates sessions, and handles its own end-user terms and disclosures before the widget opens.
## Prerequisites
@@ -28,19 +28,52 @@ To get sandbox running quickly, start with the [sandbox guide](/widget/sandbox):
4. Embed the returned `widget_url` in your frontend.
5. Listen for widget events and webhook deliveries.
+## Terms and disclosures
+
+Your application must present and record acceptance of its applicable Terms of
+Service, Privacy Policy, and required disclosures before it creates a widget
+session. The widget does not render those documents or collect that acceptance
+on the publisher's behalf, but it validates that the required terms have been
+accepted before the user can access its services.
+
+## Country availability
+
+The widget uses the country resolved from the user's IP before identity
+verification. After identity verification, it uses the user's verified
+residential country to select the available bank rail.
+
+### USD bank cashout
+
+USD bank cashout (ACH) is available only in the United States.
+
+### EUR bank cashout
+
+EUR bank cashout (SCT) is available in Austria, Belgium, Denmark, Estonia,
+Finland, France, Germany, Italy, Latvia, Lithuania, the Netherlands, Poland,
+Portugal, Spain, and Sweden.
+
+SCT is not available in other countries, including Bulgaria, Croatia, Cyprus,
+Czechia, Greece, Hungary, Ireland, Luxembourg, Malta, Romania, Slovakia,
+Slovenia, and Switzerland.
+
+### Restricted locations
+
+The widget is not supported for users in Cuba, Iran, North Korea, or Syria.
+
## 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)
+3. Reverse a Fund 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 (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.
+Use `POST /api/v1/widget/users/deplete` to reverse an available balance that
+your server previously funded, such as when a reward is canceled.
## Events
diff --git a/widget/create-session.mdx b/widget/create-session.mdx
index d55ee5c..a193ebf 100644
--- a/widget/create-session.mdx
+++ b/widget/create-session.mdx
@@ -8,9 +8,16 @@ api: "POST https://api.zbdpay.com/api/v1/widget/users/session"
Creates a widget session for a user. Returns a `session_token` (JWT) and a `widget_url` that you embed as an iframe. The session is valid for the duration specified in `expires_at`.
-The widget handles OTP email verification, KYC (Onfido), bank linking (Plaid), and cashout initiation internally.
+The widget handles OTP email verification, identity verification (Onfido), bank linking (Plaid), and cashout initiation internally.
-The widget also checks whether the user has any outstanding session disclosures. Cashout-specific disclosures are enforced when a cashout is submitted. See [Disclosure Agreements](/widget/disclosures).
+Before creating a session, your application must already have presented and
+recorded the user's acceptance of its applicable Terms of Service, Privacy
+Policy, and required disclosures. The widget does not display or collect those
+acceptances for the publisher.
+
+The session can report outstanding disclosures as a read-only status. It does
+not render them or collect acceptance. Cashout-specific disclosures are enforced
+when a cashout is submitted. See [Disclosure Agreements](/widget/disclosures).
## Configuration
diff --git a/widget/create-user.mdx b/widget/create-user.mdx
index 27e6a14..3432960 100644
--- a/widget/create-user.mdx
+++ b/widget/create-user.mdx
@@ -11,7 +11,7 @@ Provisions a user in ZBD for your project. Idempotent — if a user with the sam
Call this from your server before creating a widget session.
- Some cashout methods require the user to accept the latest disclosure before cashout can proceed. The hosted widget can collect this during the session. If your integration records disclosure acceptance before opening the widget, see [Disclosure Agreements](/widget/disclosures).
+ Some cashout methods require acceptance of the latest disclosure before they can proceed. When `outstanding_disclosures` is not empty, your application must present those documents and record acceptance before creating a widget session. See [Disclosure Agreements](/widget/disclosures).
## Configuration
diff --git a/widget/deplete-user.mdx b/widget/deplete-user.mdx
index 4257ad7..5048d0b 100644
--- a/widget/deplete-user.mdx
+++ b/widget/deplete-user.mdx
@@ -6,7 +6,11 @@ api: "POST https://api.zbdpay.com/api/v1/widget/users/deplete"
## Description
-Debit publisher points from a widget user's point balance and return them to the project's configured sink/source account. Amount is in **currency minor units**. For USDZ, `100` equals `$1.00` worth of points.
+Reverse an available fund by debiting publisher points from a widget user's
+point balance and returning them to the project's configured sink/source
+account. This creates a new debit; it does not modify the original fund
+transfer. Amount is in **currency minor units**. For USDZ, `100` equals `$1.00`
+worth of points.
This endpoint is idempotent on `idempotency_key`. The user must already have enough point balance for the debit.
diff --git a/widget/disclosures.mdx b/widget/disclosures.mdx
index 51d380d..a8eb4de 100644
--- a/widget/disclosures.mdx
+++ b/widget/disclosures.mdx
@@ -5,24 +5,30 @@ description: "Understand how widget user disclosure acceptance works before cash
## Overview
-Some widget flows require the user to accept the latest legal disclosure before continuing. ZBD tracks acceptance by disclosure type and version, so a user may need to accept a new version even if they accepted an older version before.
+Some cashout flows require the user to accept the latest legal disclosure before
+continuing. ZBD tracks acceptance by disclosure type and version, so a user may
+need to accept a new version even if they accepted an older version before.
-The widget session exposes outstanding session disclosures, and the cashout backend separately verifies cashout-specific disclosures before a payout is submitted.
+Your application is responsible for presenting the documents and collecting the
+user's acceptance before it creates a widget session. The widget does not render
+Terms of Service, Privacy Policy, or other disclosure documents, or record
+acceptance on the publisher's behalf. It validates that the required terms have
+been accepted before the user can access its services.
## End-to-end Flow
```
1. Your server creates or resolves the widget user.
-2. Your server creates a widget session.
-3. Your frontend opens the returned widget_url.
-4. The widget loads the user's session status, including outstanding_disclosures.
-5. If a session disclosure is outstanding, the widget asks the user to accept it.
-6. ZBD records the acceptance against the latest disclosure version.
-7. The user can continue to bank linking, KYC, and cashout.
+2. Your server reads `outstanding_disclosures` from the response or calls Get Disclosure Status.
+3. Your application presents each outstanding document to the user outside the widget.
+4. Your server records acceptance with Submit Disclosure Acceptance.
+5. Your server creates a widget session.
+6. Your frontend opens the returned `widget_url`.
+7. The user can continue to bank linking, identity verification, and cashout.
```
- If your integration only embeds the hosted widget, the disclosure prompt and acceptance flow are handled inside the widget. Your backend still creates users, funds balances, creates sessions, and processes webhooks as usual.
+ Do not open a widget session until the publisher-side disclosure flow is complete. The disclosure APIs require your server-side API key and must not be called from a browser, game client, or WebView.
## Outstanding Disclosures on User Creation
@@ -31,7 +37,7 @@ You do not need a separate call to discover what a user still owes. The [Create
`outstanding_disclosures` only lists what is **still outstanding**. When you need the complete picture — including which disclosures a user has **already accepted** and when — use the dedicated endpoints:
-- [Get Disclosure Status](/widget/get-disclosure-status) — list every current disclosure type with the user's acceptance state (`is_current`, `accepted_at`), so you can show accepted vs. outstanding.
+- [Get Disclosure Status](/widget/get-disclosure-status) — list every current disclosure type with the user's acceptance state (`tos_current`, `accepted_at`), so you can show accepted vs. outstanding.
- [Submit Disclosure Acceptance](/widget/submit-disclosure-acceptance) — record acceptance of the latest version from your server.
@@ -54,9 +60,13 @@ The widget disclosure endpoints can check and record acceptance for all current
## Session Status
-During a widget session, ZBD returns outstanding session disclosure information to the widget runtime. The field is named `outstanding_disclosures`.
+During a widget session, ZBD can return outstanding disclosure information as a
+read-only status. The field is named `outstanding_disclosures`. This does not
+cause the widget to display the documents or collect acceptance.
-Today this session response includes Terms of Service and Privacy Policy disclosure checks. Cashout-specific checks, such as Electronic Funds Transfer acceptance for ACH, are enforced when the user submits the cashout.
+Terms of Service and Privacy Policy are expected to be accepted before session
+creation. Cashout-specific checks, such as Electronic Funds Transfer acceptance
+for ACH, are enforced when the user submits the cashout.
Example session status shape:
@@ -88,11 +98,13 @@ Example session status shape:
}
```
-If `outstanding_disclosures` is empty, the user is current on all session disclosures returned by this endpoint.
+If `outstanding_disclosures` is empty, the user is current on all session disclosures returned by this endpoint. If it is not empty, return the user to the publisher-side acceptance flow rather than expecting the widget to collect it.
-## Recording Acceptance Outside the Widget
+## Recording acceptance before the widget
-Most integrations should let the hosted widget collect the user's acceptance. If your integration collects disclosure acceptance before the widget opens, use the widget disclosure APIs from your server. The API key determines the project context, so these endpoints only require the widget user ID in the path.
+Use the widget disclosure APIs from your server before opening the widget. The
+API key determines the project context, so these endpoints only require the
+widget user ID in the path.
Disclosure endpoints require your server-side API key. Do not call these endpoints directly from a browser, mobile client, game client, or WebView.
diff --git a/widget/fund-user.mdx b/widget/fund-user.mdx
index 79f3bb7..9ea7f35 100644
--- a/widget/fund-user.mdx
+++ b/widget/fund-user.mdx
@@ -10,6 +10,17 @@ Credit publisher points to a widget user's point balance. Amount is in **currenc
This endpoint is idempotent on `idempotency_key`.
+## Reverse a fund
+
+To take back points that you previously funded, call
+[`POST /api/v1/widget/users/deplete`](/widget/deplete-user). This creates a new
+debit from the user's currently available point balance back to your configured
+sink/source account; it does not undo or mutate the original fund transfer.
+
+Use a new `idempotency_key` for the deplete request. A deplete can only succeed
+while the user has enough available points. It cannot recover points that have
+already been spent or cashed out.
+
## Configuration
### Header Parameters
diff --git a/widget/get-disclosure-status.mdx b/widget/get-disclosure-status.mdx
index 4d21818..053ee92 100644
--- a/widget/get-disclosure-status.mdx
+++ b/widget/get-disclosure-status.mdx
@@ -8,7 +8,7 @@ api: "GET https://api.zbdpay.com/api/v1/widget/users/{userId}/disclosures"
Returns the user's acceptance status for each current disclosure type.
-Use this from your server only if your integration needs to check disclosure acceptance outside the hosted widget. Most integrations can let the widget handle disclosure prompts during the session.
+Use this from your server to determine which current disclosures the user must accept. Present any outstanding documents and collect the user's acceptance in your application before creating a widget session, then record it with [Submit Disclosure Acceptance](/widget/submit-disclosure-acceptance). Do not call this endpoint from a browser, mobile client, game client, or WebView.
The API key determines the publisher/project context. `userId` is the ZBD user ID returned when the widget user is created or resolved.
diff --git a/widget/get-user.mdx b/widget/get-user.mdx
index 2b70f87..20bcc14 100644
--- a/widget/get-user.mdx
+++ b/widget/get-user.mdx
@@ -6,7 +6,7 @@ api: "GET https://api.zbdpay.com/api/v1/widget/users/{user_id}"
## Description
-Returns the user's details including their current identity verification status. Use this to check if a user has completed KYC before showing cashout options.
+Returns the user's details including their current identity verification status. Use this to check if a user has completed identity verification before showing cashout options.
## Configuration
diff --git a/widget/sandbox.mdx b/widget/sandbox.mdx
index 243597f..4b26fca 100644
--- a/widget/sandbox.mdx
+++ b/widget/sandbox.mdx
@@ -1,6 +1,6 @@
---
title: "Sandbox"
-description: "Test the full ZBD Widget flow without real money, real KYC, or real bank transfers."
+description: "Test the full ZBD Widget flow without real money, real identity verification, or real bank transfers."
---
## Overview
@@ -19,7 +19,7 @@ Every ZBD project includes a **sandbox environment** for testing the ZBD Widget
|---|---|---|
| **User creation** | Creates sandbox-scoped widget users | Creates production widget users |
| **Balance funding** | Credits test reward balance; no live pool is debited | Transfers publisher points from your live pool |
-| **KYC / Identity** | Controlled through sandbox KYC status helpers; no live Onfido review | Required for bank cashouts |
+| **Identity verification** | Controlled through sandbox identity verification status helpers; no live Onfido review | Required for bank cashouts |
| **Bank linking (Plaid)** | Full Plaid sandbox flow | Real bank connections |
| **ACH payout** | Simulated when sandbox bypass is enabled; no real transfer | Real ACH via banking partner |
| **Disclosures** | Same status and acceptance model; bypass settings may skip cashout disclosure checks | Required disclosures can block cashout until accepted |
@@ -49,7 +49,7 @@ curl -X POST https://sandbox-api.zbdpay.com/api/v1/cashout/sandbox/users \
```
- Sandbox user creation uses a sandbox-only endpoint. Use the returned `data.id` as `zbd_user_id` when funding the user and as the user ID when setting KYC status. Use `POST /api/v1/widget/users` only for production widget users.
+ Sandbox user creation uses a sandbox-only endpoint. Use the returned `data.id` as `zbd_user_id` when funding the user and as the user ID when setting identity verification status. Use `POST /api/v1/widget/users` only for production widget users.
### 3. Fund the Test User
@@ -91,7 +91,7 @@ Embed the returned `widget_url` in an iframe. In sandbox, the URL should point a
- When you reach KYC in sandbox, use a **US address** so the approval path can complete successfully.
+ When you reach identity verification in sandbox, use a **US address** so the approval path can complete successfully.
## Sandbox Controls
@@ -103,11 +103,11 @@ For user rewards, use `POST /api/v1/widget/users/fund` and `POST /api/v1/widget/
| Control | Endpoint | Request body |
|---|---|---|
| Create sandbox user | `POST /api/v1/cashout/sandbox/users` | `{ "reference_id": "test-player-1", "email": "test@yourcompany.com" }` |
-| Set user KYC status | `POST /api/v1/principal-accounts/{zbd_user_id}/kyc-status` | `{ "status": "approved", "country_code": "US" }` |
+| Set user identity verification status | `POST /api/v1/principal-accounts/{zbd_user_id}/kyc-status` | `{ "status": "approved", "country_code": "US" }` |
| Add sandbox balance | `POST /api/v1/monetary-accounts/{monetary_account_id}/fund` | `{ "amount": 5000 }` |
| Remove sandbox balance | `POST /api/v1/monetary-accounts/{monetary_account_id}/deplete` | `{ "amount": 5000 }` |
-KYC `status` must be `approved`, `rejected`, or `processing`. Include `country_code` when setting `approved`.
+The identity verification `status` must be `approved`, `rejected`, or `processing`. Include `country_code` when setting `approved`.
Balance helper amounts use currency minor units. For USD, `5000` means `$50.00`.
diff --git a/widget/submit-disclosure-acceptance.mdx b/widget/submit-disclosure-acceptance.mdx
index b571fc9..5e56536 100644
--- a/widget/submit-disclosure-acceptance.mdx
+++ b/widget/submit-disclosure-acceptance.mdx
@@ -8,7 +8,9 @@ api: "POST https://api.zbdpay.com/api/v1/widget/users/{userId}/disclosures"
Records the user's acceptance of the latest version of each disclosure type in `acceptedDisclosureTypeIds`.
-Use this from your server only if your integration collects disclosure acceptance outside the hosted widget. Do not call this endpoint from a browser, mobile client, game client, or WebView.
+Use this from your server after your application has presented the applicable
+documents and collected the user's acceptance. Do not call this endpoint from a
+browser, mobile client, game client, or WebView.
## Configuration