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

# Create a Payout

> Disburse funds from your pre-funded balance to a beneficiary

## Prerequisites

Before creating a payout you need:

1. **A pre-funded account** — created via `POST /api/v2/customers/pre-fund/create`
2. **Sufficient balance** — check via `GET /api/v2/customers/balances`
3. **Beneficiary details** — bank account, wallet address, or payment alias of the recipient

<Card title="Set Up Pre-Funded Accounts" icon="vault" href="/guides/pre-fund/pre-fund-accounts">
  Don't have a pre-funded account yet? Start here.
</Card>

## Complete Payout Flow

<Steps>
  <Step title="Check Available Balance">
    Verify you have enough funds before submitting the payout.

    ```bash theme={null}
    GET /api/v2/customers/balances
    ```

    ```json Response theme={null}
    [
      {
        "id": "balance-id",
        "currency": "COP",
        "amount": "10000000.00",
        "accountId": "prefund-account-id"
      }
    ]
    ```
  </Step>

  <Step title="Create the Payout">
    Submit the payout request with your pre-fund account, amount, and beneficiary.

    ```bash theme={null}
    POST /api/v2/payouts
    ```
  </Step>

  <Step title="Track Status">
    Poll the payout or listen to webhooks until it reaches a terminal status (`COMPLETED`, `FAILED`, `REJECTED`, `ERROR`, or `REFUNDED`).
  </Step>
</Steps>

## Implementation Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://sandbox.killb.app/api/v2/payouts \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: payout-2024-001" \
    -d '{
      "preFundAccountId": "prefund-account-id",
      "amount": 500000,
      "externalId": "payout-2024-001",
      "beneficiary": {
        "type": "BANK",
        "account": {
          "firstName": "Maria",
          "lastName": "Garcia",
          "email": "maria@example.com",
          "phone": "3001234567",
          "document": { "type": "CC", "number": "12345678" },
          "accountNumber": "123456789",
          "bankCode": "001",
          "type": "savings",
          "countryCode": "CO"
        }
      }
    }'
  ```

  ```javascript Node.js theme={null}
  const createPayout = async (preFundAccountId, amount, beneficiary) => {
    const response = await fetch(
      'https://sandbox.killb.app/api/v2/payouts',
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json',
          'Idempotency-Key': `payout-${Date.now()}`
        },
        body: JSON.stringify({
          preFundAccountId,
          amount,
          beneficiary
        })
      }
    );

    if (!response.ok) {
      const error = await response.json();
      throw new Error(`Payout failed: ${JSON.stringify(error)}`);
    }

    return response.json();
  };

  // Example: disburse 500,000 COP via Bank Transfer
  const payout = await createPayout(
    'prefund-account-id',
    500000,
    {
      type: 'BANK',
      account: {
        firstName: 'Maria',
        lastName: 'Garcia',
        email: 'maria@example.com',
        phone: '3001234567',
        document: { type: 'CC', number: '12345678' },
        accountNumber: '123456789',
        bankCode: '001',
        type: 'savings',
        countryCode: 'CO'
      }
    }
  );

  console.log('Payout ID:', payout.id);
  console.log('Status:', payout.status);
  ```

  ```python Python theme={null}
  import requests

  def create_payout(pre_fund_account_id, amount, beneficiary, access_token):
      response = requests.post(
          'https://sandbox.killb.app/api/v2/payouts',
          headers={
              'Authorization': f'Bearer {access_token}',
              'Content-Type': 'application/json',
              'Idempotency-Key': f'payout-{pre_fund_account_id}-{amount}'
          },
          json={
              'preFundAccountId': pre_fund_account_id,
              'amount': amount,
              'beneficiary': beneficiary
          }
      )
      response.raise_for_status()
      return response.json()

  # Example: disburse 500,000 COP via Bank Transfer
  payout = create_payout(
      pre_fund_account_id='prefund-account-id',
      amount=500000,
      beneficiary={
          'type': 'BANK',
          'account': {
              'firstName': 'Maria',
              'lastName': 'Garcia',
              'email': 'maria@example.com',
              'phone': '3001234567',
              'document': {'type': 'CC', 'number': '12345678'},
              'accountNumber': '123456789',
              'bankCode': '001',
              'type': 'savings',
              'countryCode': 'CO'
          }
      },
      access_token=token
  )

  print(f"Payout created: {payout['id']} — {payout['status']}")
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "id": "payout-abc123",
  "amount": 500000,
  "currency": "COP",
  "status": "PENDING",
  "externalId": "payout-2024-001",
  "beneficiary": {
    "type": "BANK",
    "account": { ... }
  },
  "createdAt": "2024-01-15T10:30:00.000Z",
  "updatedAt": "2024-01-15T10:30:00.000Z"
}
```

## Beneficiary Types

<Tabs>
  <Tab title="Bank Transfer (Colombia)">
    Standard Colombian bank account transfer via Bank Transfer rails.

    ```json theme={null}
    {
      "type": "BANK",
      "account": {
        "firstName": "Maria",
        "lastName": "Garcia",
        "email": "maria@example.com",
        "phone": "3001234567",
        "document": {
          "type": "CC",
          "number": "12345678"
        },
        "accountNumber": "123456789",
        "bankCode": "001",
        "type": "savings",
        "countryCode": "CO"
      }
    }
    ```

    **Required fields:** `firstName` or `companyName`, `lastName`, `email`, `phone`, `document`, `accountNumber`, `bankCode`, `type`, `countryCode`

    Use `GET /api/v2/banks` to look up valid `bankCode` values.
  </Tab>

  <Tab title="BREB (Colombia)">
    Disbursement via a registered alias (phone, email, ID, or BREB alias).

    ```json theme={null}
    {
      "type": "BREB",
      "account": {
        "firstName": "Carlos",
        "lastName": "Lopez",
        "email": "carlos@example.com",
        "phone": "3109876543",
        "document": {
          "type": "CC",
          "number": "87654321"
        },
        "aliasType": "PHONE",
        "alias": "3109876543",
        "countryCode": "CO"
      }
    }
    ```

    **Alias types:** `NATIONAL_ID`, `PHONE`, `EMAIL`, `ALPHANUMERIC`, `BUSINESS_ID`
  </Tab>
</Tabs>

## Checking Balance Before Payout

Always verify available balance before submitting large payouts:

```javascript theme={null}
const checkBalance = async (preFundAccountId, requiredAmount) => {
  const balances = await fetch('/api/v2/customers/balances', {
    headers: { 'Authorization': `Bearer ${token}` }
  }).then(r => r.json());

  const account = balances.find(b => b.accountId === preFundAccountId);

  if (!account || parseFloat(account.amount) < requiredAmount) {
    throw new Error(
      `Insufficient balance. Available: ${account?.amount ?? 0}, Required: ${requiredAmount}`
    );
  }

  return account;
};
```

## Idempotency

To prevent duplicate disbursements on network retries, pass a unique `Idempotency-Key` header with every payout creation request. If the same key is submitted twice, KillB returns the original payout instead of creating a new one.

```bash theme={null}
Idempotency-Key: <your-unique-payout-reference>
```

<Tip>
  Use a stable, unique identifier as the key — your internal payment ID or a UUID tied to the business transaction works well.
</Tip>

## Listing Payouts

Retrieve all payouts with optional filters:

```javascript theme={null}
const listPayouts = async ({ status, externalId, page = 1, limit = 20 } = {}) => {
  const params = new URLSearchParams({ page, limit });
  if (status) params.set('status', status);
  if (externalId) params.set('externalId', externalId);

  const response = await fetch(
    `https://sandbox.killb.app/api/v2/payouts?${params}`,
    { headers: { 'Authorization': `Bearer ${token}` } }
  );

  return response.json(); // { payouts: [...], totalPage: N }
};

// Get all pending payouts
const pending = await listPayouts({ status: 'PENDING' });
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Status Tracking" icon="chart-line" href="/guides/payouts/payout-status">
    Monitor payouts with polling and webhooks
  </Card>

  <Card title="Webhooks Setup" icon="bell" href="/guides/webhooks/setup">
    Configure PAYOUT webhook notifications
  </Card>
</CardGroup>
