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

# Send a payout

> Pay a Beneficiary who is ready: create the payout, approve it, and follow it until the money has left.

Pay Jane Doe \$500.00 and follow the payout until the money has left your Cleff
Account. For developers wiring payouts into their product. Each step below is
one request, and each response that carries money is read back in plain English.

<Note>
  **Agents:** fetch this page as plain markdown at
  `https://docs.usecleff.com/guides/send-a-payout.md`.
</Note>

You need a sandbox API key exported as `CLEFF_API_KEY`, and Jane onboarded with
her `status` reading `ready` and her ID exported as `BEN_ID`.
[Onboard a Beneficiary](/guides/onboard-a-beneficiary) gets her there. What each
state below means is on [Payouts](/concepts/payouts).

<Steps>
  <Step title="Check you can cover the payout">
    In production your balance isn't checked when you create or approve a payout,
    only when it is sent, so check it first:

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

    ```json theme={null}
    {
      "currency": "USD",
      "available_balance_minor": 1250000,
      "total_balance_minor": 1250000
    }
    ```

    In this example your Cleff Account holds \$12,500.00 USD;
    `available_balance_minor` is 1250000 because amounts are in
    [minor units](/concepts/payouts#read-amounts-in-minor-and-major-units). That
    covers Jane's \$500.00.
  </Step>

  <Step title="Create the payout">
    Mint an idempotency key and keep it for as long as you might resend the request:

    ```bash theme={null}
    export IDEMPOTENCY_KEY=$(uuidgen)
    ```

    Name who to pay and how much. Leave out `destination_id`, so the payout goes to
    Jane's declared destination, or to her only one if she has declared none:

    ```bash theme={null}
    curl -X POST https://api.usecleff.com/v1/payouts \
      -H "Authorization: Bearer $CLEFF_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
      -d '{
        "beneficiary_id": "'$BEN_ID'",
        "amount_minor": 50000,
        "currency": "USD",
        "purpose_of_payment": "other",
        "external_ref": "INVOICE-2026-0001"
      }'
    ```

    ```json theme={null}
    {
      "payout": {
        "id": "5f0c1f6e-8f4b-4b0e-9f6d-2a7c9d1e3b42",
        "state": "pending_approval",
        "beneficiary_id": "3b9e1f4c-2a6d-4c8e-b1f0-5d7a9c3e2b18",
        "destination_id": "8d6f3c2a-51b7-4e0f-9a3d-7c1e2b4f6a90",
        "destination_kind": "bank",
        "amount_minor": 50000,
        "currency": "USD",
        "external_ref": "INVOICE-2026-0001",
        "failure_code": null,
        "replaceable": false
      }
    }
    ```

    The response is trimmed to the fields that matter here. Jane Doe is owed
    \$500.00 USD, to be paid to the bank account `destination_id` names;
    `amount_minor` is 50000 because amounts are in minor units.
    Nothing has moved: the payout is `pending_approval`, and its destination is now
    fixed even if Jane chooses a different one later.

    Resending this request with the same key within 24 hours returns this payout
    with HTTP 200 instead of creating a second one. See [Idempotency](/idempotency).

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

  <Step title="Approve it">
    Nothing is sent without a Decision. Approve the payout with a `decision_id` you
    mint, a ULID, which makes the approval safe to retry:

    ```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)'"
      }'
    ```

    ```json theme={null}
    {
      "decision": {
        "id": "c7d2a9e4-3f1b-4a6c-8e5d-9b0f2a4c6e81",
        "decision_id": "01K4Q6H8Z3TJN0V1B2C3D4E5F6",
        "payout_id": "5f0c1f6e-8f4b-4b0e-9f6d-2a7c9d1e3b42",
        "status": "approved",
        "reasons": [],
        "evaluated_at": "2026-09-29T14:02:11.000Z",
        "submitted_at": "2026-09-29T14:02:11.412Z"
      }
    }
    ```

    The response is trimmed. It is the Decision you recorded; the payout itself is
    now `approved` and queued to be sent. To refuse the payout instead, [reject it](/api-reference/payouts-reject) with at least one
    reason; rejection is terminal.
  </Step>

  <Step title="Watch it disburse">
    Read the payout until `state` moves from `approved` to `disbursed`:

    ```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",
      "destination_id": "8d6f3c2a-51b7-4e0f-9a3d-7c1e2b4f6a90",
      "destination_kind": "bank",
      "amount_minor": 50000,
      "currency": "USD",
      "external_ref": "INVOICE-2026-0001",
      "rail_ref": "ACH-2026-0001",
      "failure_code": null
    }
    ```

    \$500.00 USD has left your Cleff Account for Jane's bank account, and
    `rail_ref` is the payment's reference on the rail, or `null` until the rail
    assigns one. In sandbox the payout stops here. In production it is provisional until it becomes `settled`, and the
    receiving bank can still return it; [Payouts](/concepts/payouts#know-what-happens-after-approval)
    explains the rest of the way.
  </Step>

  <Step title="Hear about it instead of polling">
    In place of reading the payout, [subscribe an endpoint](/webhooks#subscribe-an-endpoint)
    to `payout.disbursed`, `payout.failed` and the other `payout.*` events. When
    Jane's payout leaves, your endpoint receives:

    ```json theme={null}
    {
      "id": "evt_…",
      "type": "payout.disbursed",
      "api_version": "2026-05-27",
      "occurred_at": "2026-09-29T14:02:14.000Z",
      "created_at": "2026-09-29T14:02:15.000Z",
      "sequence": 10472,
      "data": {
        "payout_id": "5f0c1f6e-8f4b-4b0e-9f6d-2a7c9d1e3b42",
        "external_ref": "INVOICE-2026-0001",
        "beneficiary_id": "3b9e1f4c-2a6d-4c8e-b1f0-5d7a9c3e2b18",
        "amount": "500.00",
        "currency": "USD",
        "rail_ref": "ACH-2026-0001",
        "status": "disbursed"
      }
    }
    ```

    The same \$500.00 USD has left for Jane. `amount` is `"500.00"` because
    webhooks carry amounts in major units, where the API's `amount_minor` is 50000.
  </Step>
</Steps>

## Handle a payout that fails

If the payout reads `failed` instead of `disbursed`, the money did not leave,
unless `failure_code` is `indeterminate`. `failure_code` says why and `replaceable` says whether you can try again. Fix
what the code names, then create a new payout with `replaces_payout_id` set to
this one's ID. [Payout events](/api-reference/webhook-events-payout#why-a-payout-failed)
lists every code and its recovery.


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