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

# Embedded Payouts API Overview

> Base URL, authentication, errors, and the conventions every Embedded Payouts endpoint shares.

## Base URL

| Environment | Base URL |
| - | - |
| Production | `https://api.zbdpay.com` |
| Sandbox | `https://sandbox-api.zbdpay.com` |

Paths are the same in both environments. Keys are issued per environment, so a sandbox key only works on the sandbox host and a production key only works in production. To go live, change the base URL and the key.

## Authentication

Send your API key in the `x-api-key` header. The key identifies your organization, so there's no publisher or organization ID in any path. Call these endpoints from your server only, so the key never reaches a browser or game client.

Where an endpoint is scoped to a project, pass an optional `project_id`: in the body for writes, and in the query for reads.

## Endpoints

| Method | Path | Purpose |
| - | - | - |
| `GET` | `/api/v1/projects` | List projects |
| `GET` | `/api/v1/projects/{projectId}` | Get a project |
| `POST` | `/api/v1/users` | Create a user |
| `GET` | `/api/v1/users/{userId}` | Get a user |
| `PATCH` | `/api/v1/users/{userId}` | Update a user |
| `POST` | `/api/v1/users/{userId}/deletion-request` | Delete a user |
| `GET` | `/api/v1/users/{userId}/payment-methods` | List a user's payment methods |
| `GET` · `POST` | `/api/v1/users/{userId}/disclosures` | Read or record disclosures |
| `POST` | `/api/v1/widget-sessions` | Create a widget session |
| `POST` | `/api/v1/payouts` | Create a payout |
| `GET` | `/api/v1/payouts/{payoutId}` | Get a payout |
| `GET` | `/api/v1/payouts` | List payouts |
| `POST` | `/api/v1/transactions/credits` | Credit a user's earnings |
| `POST` | `/api/v1/transactions/debits` | Reverse a credit |
| `GET` | `/api/v1/users/{userId}/balances` | Get a user's balances (their earnings) |
| `GET` | `/api/v1/transactions` | List transactions |
| `POST` · `GET` | `/api/v1/webhooks/subscriptions` | Create or list webhook subscriptions |
| `PATCH` · `DELETE` | `/api/v1/webhooks/subscriptions/{subscriptionId}` | Update or delete a subscription |

The credit, debit, earnings, and transaction endpoints are only for programs where ZBD tracks earnings. See [How Payouts Work](/embedded-payouts/how-payouts-work#two-ways-to-track-earnings).

## Idempotency

Every call that moves value takes an `Idempotency-Key` header with a UUID you generate. Retrying with the same key returns the original result instead of acting twice. Use a new key for each new operation, and the same key when retrying one.

## Responses

Every response uses the same wrapper:

```json theme={null}
{ "success": true, "message": "…", "data": {}, "error": null }
```

On failure, `data` is `null` and `error` is `{ code, message, details? }`. `code` is a stable string you can branch on, and the HTTP status matches it. Nothing is debited on any `4xx`.

## Errors

These codes are shared by every endpoint.

| HTTP | `code` | When |
| - | - | - |
| `400` | `idempotency_key_required` | A call that moves value has no `Idempotency-Key` |
| `400` | `validation_failed` | The body is malformed. `details` names the fields |
| `401` | `unauthorized` | The API key is missing or invalid |
| `403` | `feature_not_enabled` | The feature isn't enabled for your program or ledger model |
| `404` | `user_not_found` · `payment_method_not_found` · `payout_not_found` | The ID doesn't exist under your key |
| `409` | `idempotency_key_reused` | The same key was sent with a different body |
| `409` | `payouts_in_flight` | A user deletion was requested while the user has open payouts |
| `422` | `insufficient_funds` | Your pool, or the user's earnings if ZBD tracks them, doesn't cover the amount |
| `422` | `kyc_required` · `disclosure_required` · `screening_blocked` | The user isn't cleared for this payout |
| `422` | `limit_exceeded` | The amount is over the user's limit |
| `422` | `payment_method_inactive` · `unsupported_currency` | The payment method can't be used, or the currency can't be paid on that rail |

A feature that isn't enabled always returns `403 feature_not_enabled`, never `404`.

## Conventions

* **Amounts** are always whole numbers in the currency's smallest unit. Each currency has a `precision` that says how many decimal places to show: `2` for USD, so `100` is \$1.00, and `0` for a currency like JPY, so `100` is ¥100.
* **`user_id`** is the ZBD user ID returned by [Create a User](/embedded-payouts/apis/create-user).
* **Tracing.** Send an `X-Request-Id` header on any call to make it easier to trace with support.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.