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

# Quickstart: send your first payout

> From signup to a disbursed sandbox payout. No review, no real money, about ten minutes.

This walkthrough takes a brand-new account to a `disbursed` sandbox payout.
Everything runs against the sandbox environment: provider calls hit mock
implementations, no money moves, and nothing here requires review or approval
from Cleff.

You need an email address, a terminal with `curl`, and nothing else.

<Steps>
  <Step title="Create your account">
    Sign up at [app.usecleff.com/signup](https://app.usecleff.com/signup). The
    two-step wizard creates your user account and your Business (labelled
    *Organization* in the dashboard). Verify the email you receive, then sign in.

    Sandbox access is granted immediately on email verification. Production stays
    locked until your business completes verification; see [Go live](/go-live)
    when you get there.
  </Step>

  <Step title="Complete your business profile">
    In the dashboard, fill in your company profile under **Settings → Company**
    and submit it. A complete profile provisions your sandbox wallet with
    **\$1,000,000 of test money**; until then, payout creation is refused with
    `SANDBOX_WALLET_UNFUNDED`. (The same profile later becomes your verification
    dossier for [going live](/go-live), so nothing here is throwaway work.)
  </Step>

  <Step title="Mint a sandbox API key">
    In the dashboard, open **Settings → API keys** and create a key. The plaintext
    key is shown **exactly once**: Cleff stores only a verifier and cannot show it
    again. Export it for the rest of this walkthrough:

    ```bash theme={null}
    export CLEFF_API_KEY="ck_sandbox_..."
    ```

    The `ck_sandbox_` prefix is load-bearing: this key only ever sees sandbox data.
    [Authentication](/authentication) covers the key format and rotation.
  </Step>

  <Step title="Confirm your sandbox balance">
    Payouts draw from your Cleff Account. The test money from your submitted
    profile lands moments after the submit returns, so confirm it is there:

    ```bash theme={null}
    curl https://api.usecleff.com/v1/funding/account \
      -H "Authorization: Bearer $CLEFF_API_KEY"
    ```

    Poll until `available_balance_minor` is above zero. Amounts are in **minor
    units** everywhere in the API. If you ever want a different balance, the
    [sandbox top-up](/api-reference/funding-sandbox-balance) sets it directly;
    that endpoint is rejected outside sandbox.
  </Step>

  <Step title="Create a Beneficiary">
    A Beneficiary is a person or business you pay. Passing `acknowledged: true`
    attests that your Business has independently verified their identity, which
    moves them straight to `compliant`, the state payout creation requires. (See
    [Beneficiaries & compliance](/concepts/beneficiaries) for what that attestation
    means and for the invite flow where beneficiaries submit their own details.)

    ```bash theme={null}
    curl -X POST https://api.usecleff.com/v1/beneficiaries \
      -H "Authorization: Bearer $CLEFF_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "beneficiary_type": "person",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com",
        "country_of_residence": "US",
        "acknowledged": true
      }'
    ```

    Capture `beneficiary.id` from the response:

    ```bash theme={null}
    export BEN_ID="<beneficiary.id>"
    ```
  </Step>

  <Step title="Register their bank account">
    Payouts name an explicit destination account. Because the Beneficiary is
    already `compliant`, the account comes back `verified` immediately; a routing
    code that passes Cleff's format checks makes it `validated`. Both together set
    `payout_usable: true`, the one flag that matters.

    ```bash theme={null}
    curl -X POST https://api.usecleff.com/v1/beneficiaries/$BEN_ID/bank-accounts \
      -H "Authorization: Bearer $CLEFF_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "account_holder_name": "Jane Doe",
        "country": "US",
        "currency": "USD",
        "account_number": "000123456789",
        "routing_code": "021000021"
      }'
    ```

    Capture `bank_account.id`:

    ```bash theme={null}
    export BANK_ID="<bank_account.id>"
    ```

    Identifiers are masked to `last4` in every read; the full account number is
    never serialized back.
  </Step>

  <Step title="Create the payout">
    ```bash theme={null}
    curl -X POST https://api.usecleff.com/v1/payouts \
      -H "Authorization: Bearer $CLEFF_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "beneficiary_id": "'$BEN_ID'",
        "bank_account_id": "'$BANK_ID'",
        "amount_minor": 50000,
        "currency": "USD",
        "purpose_of_payment": "other",
        "idempotency_key": "quickstart-payout-1",
        "external_ref": "INVOICE-2026-0001"
      }'
    ```

    The payout is created in `pending_approval`; nothing moves until a Decision
    approves it. The `idempotency_key` makes this call safe to retry: replaying it
    within 24 hours returns the original payout with HTTP 200 instead of creating a
    second one.

    ```bash theme={null}
    export PAYOUT_ID="<payout.id>"
    ```
  </Step>

  <Step title="Approve it">
    Every payout passes an approval gate before dispatch. Approve yours (the
    `decision_id` is a caller-supplied ULID that makes the decision idempotent):

    ```bash theme={null}
    curl -X POST https://api.usecleff.com/v1/payouts/$PAYOUT_ID/approve \
      -H "Authorization: Bearer $CLEFF_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "decision_id": "01K4Q6H8Z3TJN0V1B2C3D4E5F6",
        "evaluated_at": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
      }'
    ```

    Approval enqueues the disbursement; the dispatch itself runs asynchronously.
  </Step>

  <Step title="Watch it disburse">
    Poll the payout and watch `state` advance from `approved` to `disbursed` as
    the sandbox provider confirms the disbursement:

    ```bash theme={null}
    curl https://api.usecleff.com/v1/payouts/$PAYOUT_ID \
      -H "Authorization: Bearer $CLEFF_API_KEY"
    ```

    ```json theme={null}
    {
      "id": "5f0c1f6e-8f4b-4b0e-9f6d-2a7c9d1e3b42",
      "state": "disbursed",
      "amount_minor": 50000,
      "currency": "USD",
      "external_ref": "INVOICE-2026-0001",
      "rail_ref": "FAKE-ACH-...",
      "provider": "fake"
    }
    ```

    That is the whole loop: fund → register → create → approve → disburse. In
    production the only differences are real providers, real money, and a funded
    account you cannot top up by API.
  </Step>
</Steps>

## Where to go next

<CardGroup cols={2}>
  <Card title="Listen instead of polling" icon="webhook" href="/api-reference/webhook-subscriptions">
    Register a webhook endpoint and receive signed payout lifecycle events.
  </Card>

  <Card title="Invite beneficiaries to self-onboard" icon="user-plus" href="/concepts/beneficiaries">
    Send secure collection links so beneficiaries submit their own bank details.
  </Card>

  <Card title="Understand the lifecycle" icon="arrow-right-left" href="/concepts/how-money-moves">
    Every payout state, the headroom check, and what happens on failure or return.
  </Card>

  <Card title="Go live" icon="ship" href="/go-live">
    The path from sandbox to production: verification, pricing, and a production key.
  </Card>
</CardGroup>
