Skip to main content
A payout sends crypto from your Tender merchant balance to an external destination — either a raw wallet address or a saved payout account. Payouts are processed asynchronously and do not require an OTP.

How it works

1

Check the fee

Call GET /payout/fee/{chain}/{coin}/{amount} to see the fee and net amount before committing.
2

Submit the payout

Call POST /payout/crypto with the coin, chain, amount, and either a wallet address or a saved payoutAccountId.
3

Poll for completion

Call GET /payout/{id} until status is completed or failed.

Prerequisites

Authentication guide

All requests require an HMAC-SHA256 signature. See the authentication guide for code examples.
const BASE = 'https://sandbox-api.tender.cash/v1/api';
// makeHeaders() → { 'x-access-id', 'x-request-id', 'x-timestamp', 'authorization', ... }

Step 1 — Check the fee

const feeRes = await fetch(
  `${BASE}/payout/fee/tron/usdt/50`,
  { headers: makeHeaders() }
);
const { data: fee } = await feeRes.json();
/*
{
  amount:         50,
  amountUSD:      50.00,
  fee:            0.5,
  feeUSD:         0.50,
  amountAfterFee: 49.5,
  currency:       "usdt",
  chain:          "tron"
}
*/

Step 2 — Submit a payout to a wallet address

const payoutRes = await fetch(`${BASE}/payout/crypto`, {
  method: 'POST',
  headers: makeHeaders(),
  body: JSON.stringify({
    coin:    'usdt',
    chain:   'tron',
    amount:  '50',
    address: 'TQn9Y2khDD9JHTfVE5oB2h8BKWWM4LxKLT',
  }),
});

const { data: payout } = await payoutRes.json();
const payoutId = payout._id;
console.log('Status:', payout.status); // "pending"

Step 2 (alt) — Payout to a saved payout account

const payoutRes = await fetch(`${BASE}/payout/crypto`, {
  method: 'POST',
  headers: makeHeaders(),
  body: JSON.stringify({
    coin:            'usdt',
    chain:           'tron',
    amount:          '50',
    payoutAccountId: '66aec7de809b7f45c42a49f9',
  }),
});

Step 3 — Poll for completion

async function pollPayout(id, intervalMs = 8000) {
  while (true) {
    const res = await fetch(`${BASE}/payout/${id}`, { headers: makeHeaders() });
    const { data } = await res.json();

    console.log('Status:', data.status);

    if (data.status === 'completed') return data;
    if (data.status === 'failed') throw new Error('Payout failed');

    await new Promise(r => setTimeout(r, intervalMs));
  }
}

const result = await pollPayout(payoutId);
Configure a webhook to be notified when a payout completes instead of polling. See Webhooks for setup instructions.

Payout status values

StatusMeaning
pendingQueued, not yet sent on-chain
processingBroadcast to the network
completedConfirmed on-chain
failedRejected — see failureReason

Error handling

ScenarioAction
Insufficient balanceCheck merchant balance before submitting
Amount below minimumCall the fee endpoint first; verify amountAfterFee > 0
status: "failed"Read failureReason on the payout record
Neither address nor payoutAccountId providedExactly one must be supplied; omitting both returns 400