# Payouts

This is how money reaches your bank account. You sell tickets in your currency,
your earnings (sales proceeds plus resale royalties, net of platform fees)
accumulate as a single **balance**, and you pay that balance out to your bank
account.

> **One balance, your currency, fiat in and fiat out.** Customers pay by card; you
> get paid to your bank. Everything you see here is a plain amount in your
> settlement currency — no settlement internals, no conversions for you to manage.
> The platform reconciles all of that behind the scenes.


## The fiat-in / fiat-out model

* **Fiat in:** customers buy tickets with a card. The platform collects the
  payment and credits your share to your balance.
* **Your balance:** a single spendable number in your currency. It already
  reflects platform fees and any resale royalties owed to you — there is nothing
  to net out yourself.
* **Fiat out:** you request a payout, and the platform transfers the money to
  your connected bank account.

You never see more than one balance, and it's always in your own currency.

## Scopes

| Endpoint | Method | Scope |
| --- | --- | --- |
| `/v1/connect/account` | `POST` | `payouts:claim` |
| `/v1/connect/account` | `GET` | `payouts:claim` |
| `/v1/balance` | `GET` | `payouts:read` (or `payouts:claim`) |
| `/v1/payouts` | `GET` | `payouts:read` (or `payouts:claim`) |
| `/v1/payouts` | `POST` | `payouts:claim` |

> **Note:** `payouts:read` is read-only (balance and payout history). `payouts:claim` can do
> everything `payouts:read` can **and** onboard the account and request payouts.
> Give back-office dashboards a read-only key; reserve `payouts:claim` for the
> service that moves money.


## 1. Onboard with Stripe Connect

Before you can be paid, you complete a one-time Stripe Connect onboarding (bank
details, identity verification). Start it by creating an onboarding link, then
redirect your user to the returned `onboarding_url`.

```bash
curl https://api.ticketconnect.example/v1/connect/account \
  -X POST \
  -H "Authorization: Bearer sk_test_..."
```

```json
{
  "account_id": "acct_1Q...",
  "onboarding_url": "https://connect.stripe.com/setup/e/acct_1Q.../..."
}
```

Send the user to `onboarding_url` to finish setup. If they don't complete it in
one sitting, call this endpoint again to get a fresh link — it resumes the same
connected account.

## 2. Check onboarding status

Confirm whether the account is ready to receive payouts:

```bash
curl https://api.ticketconnect.example/v1/connect/account \
  -H "Authorization: Bearer sk_test_..."
```

Before onboarding has started:

```json
{ "connected": false }
```

Once a connected account exists:

```json
{
  "connected": true,
  "charges_enabled": true,
  "payouts_enabled": true,
  "details_submitted": true
}
```

You're ready to receive money when `payouts_enabled` is `true`. (No personal or
bank details are ever returned — only these capability flags.)

## 3. Check your balance

```bash
curl https://api.ticketconnect.example/v1/balance \
  -H "Authorization: Bearer sk_test_..."
```

```json
{
  "object": "balance",
  "available": 1284.50,
  "currency": "USD"
}
```

`available` is what you can pay out right now, in `currency` (your settlement
currency).

### Refunds move the balance, not your bank account

Earnings land in your balance when a sale settles, and they leave it again if
that sale is reversed — a refunded ticket or a cancelled event removes your
share of it. Nothing is ever pulled back out of your bank account or your
connected Stripe account: a reversal is a debit against the balance, so it nets
off against what you earn next.

That also means the balance can go **negative**, if refunds land after you've
already paid out. `available` reports the real figure — including a negative one
— so you can see how far under you are:

```json
{ "object": "balance", "available": -128.40, "currency": "USD" }
```

Payouts are refused while you're under: requesting a specific amount returns
`400 insufficient_balance`, and requesting the full balance returns
`400 parameter_invalid` (there is no positive amount to pay out). New earnings
net against the shortfall until the balance is positive again.

> Because reversals settle against your balance, request payouts on a rhythm
> (weekly, monthly) rather than draining to zero after every sale — that keeps a
> buffer for refunds and avoids a stretch where you can't pay out at all.

## 4. Request a payout

Request a payout to your connected bank account. Pass an `amount` (in your
currency) to pay out part of your balance, or omit it to pay out the **full
available balance**.

```bash
curl https://api.ticketconnect.example/v1/payouts \
  -X POST \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 500.00,
    "currency": "USD"
  }'
```

```json
{
  "object": "payout",
  "id": "tr_1Q9...",
  "amount": 500.00,
  "currency": "USD",
  "status": "paid"
}
```

A successful payout also emits a `payout.paid` webhook — see
[Webhooks](#webhooks).

> **Warning:** A payout can never exceed your available balance — an over-request returns `400`
> with an `insufficient_balance` error. You must have finished Connect onboarding
> first; otherwise you'll get a `connect_account_required` error.


> **Use an `Idempotency-Key` header** when requesting a payout, so a network retry
> can't accidentally pay you out twice. A replay with the same key returns the
> original response.
>
> ```bash
> curl https://api.ticketconnect.example/v1/payouts \
>   -X POST \
>   -H "Authorization: Bearer sk_test_..." \
>   -H "Idempotency-Key: payout-2026-06-05-001" \
>   -H "Content-Type: application/json" \
>   -d '{ "amount": 500.00 }'
> ```


## 5. List past payouts

Review your payout history, newest first, cursor-paginated via `limit` (and
`starting_after`).

```bash
curl "https://api.ticketconnect.example/v1/payouts?limit=20" \
  -H "Authorization: Bearer sk_test_..."
```

```json
{
  "object": "list",
  "data": [
    {
      "id": "668a2f1c9e7d654321fedcba",
      "amount": 500.00,
      "currency": "USD",
      "reference": "tr_1Q9...",
      "created_at": "2026-06-05T12:00:00.000Z"
    }
  ],
  "has_more": false
}
```

`reference` ties each entry back to the underlying transfer.

## See also

* [Webhooks](#webhooks) — listen for `payout.paid`.
* [Marketplace & resale](#marketplace-and-resale) — resale royalties feed your
  balance.
* [API reference](#api-overview) — full endpoint details.
