> 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/js/guides/payouts.md).

# Send a payout

Send single crypto payouts in Node.js — 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:

```ts
const est = await client.payouts.estimate({
  network: Chain.EthMainnet,
  coin: 'USDT',
  amount: '25.0',
  toAddress: '0xRecipient...',
});
// est.amountToReceive, est.feeInfo?.estimatedFiat, est.sources
```

## Execute

```ts
const payout = await client.payouts.execute({
  orderId: 'order-42',   // idempotency key — safe to retry
  userId: 'u-7',
  network: Chain.EthMainnet,
  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

```ts
const final = await client.payouts.waitFor(payout.uuid, {
  intervalMs: 5_000,
  timeoutMs: 5 * 60_000,
});
if (final.status === 'paid') {
  console.log('paid: tx =', final.txid);
}
```

Or react to the `payout.*` [webhook](/processing/js/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

```ts
import { ApiError, ErrorCode, isApiError } from '@cryptochiefs/cryptochief-crypto-processing-node';

try {
  await client.payouts.execute(req);
} catch (err) {
  if (isApiError(err, ErrorCode.InsufficientFunds)) {
    // top up and retry
  } else if (err instanceof ApiError) {
    switch (err.code) {
      case ErrorCode.AssetNotEnabled:   // coin/network not enabled
      case ErrorCode.DebtLimitExceeded: // postpaid cap hit
        break;
    }
  } else throw err;
}
```

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

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