> For the complete documentation index, see [llms.txt](https://docs-sdk.crypto-chief.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs-sdk.crypto-chief.com/processing/kotlin/guides/payouts.md).

# Send a payout

Send single crypto payouts in Kotlin — estimate, execute idempotently, and wait for confirmation.

A payout sends crypto from your project balance to any address. The flow is **estimate** (optional) → **execute** → **wait for confirmation** (optional).

## Estimate

Preview the network fee and the net amount the recipient receives before sending:

```kotlin
import com.cryptochief.processing.Chain
import com.cryptochief.processing.models.EstimatePayoutRequest

val est = client.payouts.estimate(
    EstimatePayoutRequest(
        network   = Chain.ETH_MAINNET,
        coin      = "USDT",
        amount    = "25.0",
        toAddress = "0xRecipient...",
    ),
)
// est.amountToReceive, est.feeInfo?.estimatedFiat, est.sources
```

## Execute

```kotlin
import com.cryptochief.processing.models.ExecutePayoutRequest

val payout = client.payouts.execute(
    ExecutePayoutRequest(
        orderId     = "order-42",   // idempotency key — safe to retry
        userId      = "u-7",
        network     = Chain.ETH_MAINNET,
        coin        = "USDT",
        amount      = "25.0",
        toAddress   = "0xRecipient...",
        urlCallback = "https://your.app/webhooks/payout",
    ),
)
```

{% hint style="info" %}
`orderId` is an **idempotency key**: re-submitting the same `order_id` returns the same payout instead of creating a second one. That is what makes the SDK's automatic retries safe.
{% endhint %}

## Wait for confirmation

```kotlin
import com.cryptochief.processing.PollOptions
import com.cryptochief.processing.poll.waitForPayout
import java.time.Duration

val final = client.waitForPayout(
    uuid    = payout.uuid,
    options = PollOptions(interval = Duration.ofSeconds(5), timeout = Duration.ofMinutes(5)),
)
if (final.succeeded) {
    println("paid: tx=${final.txid}")
}
```

Or react to the `payout.*` [webhook](/processing/kotlin/guides/webhooks.md) instead of polling.

## Pay out in a different asset (swap)

{% hint style="warning" %}
**Not available yet.** The payout request carries an `auto_convert` field and this SDK exposes it, but the platform refuses any payout that sets it, answering `AUTO_CONVERT_NOT_IMPLEMENTED`. `auto_convert_policy` is reserved alongside it. Convert the asset yourself and pay out what the master wallet already holds.
{% endhint %}

## Handle errors

```kotlin
import com.cryptochief.processing.ApiException
import com.cryptochief.processing.ErrorCode

try {
    client.payouts.execute(req)
} catch (e: ApiException) {
    when (e.code) {
        ErrorCode.INSUFFICIENT_FUNDS  -> { /* top up and retry */ }
        ErrorCode.ASSET_NOT_ENABLED   -> { /* coin/network not enabled */ }
        ErrorCode.DEBT_LIMIT_EXCEEDED -> { /* postpaid cap hit */ }
        else                          -> throw e
    }
}
```

See [Errors & retries](/processing/kotlin/concepts/errors.md).

{% content-ref url="/pages/D1e7H6WbSjE5yE3IbO9n" %}
[Mass payouts](/processing/kotlin/guides/mass-payouts.md)
{% endcontent-ref %}
