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

# Payouts (offramp)

> Send stablecoins and pay out fiat to a bank account, from quotation to webhook.

A payout turns stablecoins into fiat in a bank account. You send crypto to a Zapyd deposit address, and Zapyd pays the beneficiary over local bank rails.

**Base URL:** `https://sandbox.zapyd.com/pos/api/v1`. Customer and bank calls use `/cms/api/v1` and limit calls use `/ren/api/v1`.

<CardGroup cols={2}>
  <Card title="Paying from a balance?" icon="vault" href="/guides/payments/prefunded-payouts">
    Prefunded payouts skip the per-order crypto transfer.
  </Card>

  <Card title="Paying outside India?" icon="earth-americas" href="/guides/customers/payout-only-onboarding">
    Onboard beneficiaries in the UAE, UK, SEPA, Brazil, Mexico, the US and others.
  </Card>
</CardGroup>

## Before you start

* The customer is `VERIFIED` and has a `VERIFIED` [bank account](/guides/customers/bank-accounts-and-wallets). Save its `id` as `bank_id`.
* Your [webhook URL](/guides/development-and-testing/webhooks) is registered.

## Flow

```mermaid theme={null}
sequenceDiagram
    participant App as Your backend
    participant Z as Zapyd
    participant C as Blockchain
    participant B as Beneficiary bank
    App->>Z: GET /payout/limits/{customer_id}
    App->>Z: POST /payout/quotation
    Z-->>App: rate, fees, wallet_address, expiry_time
    App->>C: Send sending_amount to wallet_address
    App->>Z: POST /payout/initiate (transaction_hash)
    Z->>C: Verify the transfer on-chain
    Z->>B: Pay fiat
    Z-->>App: PAYOUT webhook: SUCCESS + utr
```

## 1. Read the configuration

[`GET /payout/configuration`](/api-reference-exchange/endpoint/payout/config/configuration) returns, for each fiat, the supported assets, the minimum and maximum per payment method, and the required risk parameters. Cache it and refresh it daily.

## 2. Check the customer's limit

[`GET /ren/api/v1/payout/limits/{customer_id}`](/api-reference-exchange/endpoint/payout/config/edd-limits-\{customer_id}) returns `available_limit` and `is_edd_required`. If the limit doesn't cover the amount and EDD is required, collect [EDD](/guides/payments/limits-and-edd) first.

## 3. Create a quotation

Call [`POST /payout/quotation`](/api-reference-exchange/endpoint/payout/quotation/quotation). Send **either** `sending_amount` (the crypto you send) **or** `receiving_amount` (the fiat the beneficiary gets).

<CodeGroup>
  ```json Request theme={null}
  {
    "customer_id": "84737c7d-7b62-4204-80d6-80f6ecb3ceb4",
    "bank_id": "cab47575-bbcb-4294-81a3-30774104f3b6",
    "asset": "usdt",
    "fiat": "inr",
    "network": "tron",
    "payment_method": "IMPS",
    "sending_amount": "60",
    "risk_parameters": {
      "ip_address": "203.0.113.10",
      "device_id": "device-123",
      "suspicious_activity_report": false,
      "law_enforcement_agency_report": false
    }
  }
  ```

  ```json Response (201) theme={null}
  {
    "status": true,
    "message": "Success",
    "data": {
      "id": "59bf60c3-e9af-40a7-9d5c-2a1aa191e769",
      "asset": "USDT",
      "fiat": "INR",
      "network": "tron",
      "sending_amount": "60.00",
      "rate": "85.00",
      "receiving_amount": "5100.00",
      "fees": { "zapyd_fee": "0.00", "client_fee_fiat": "0.00", "tds": "0.00" },
      "wallet_address": "TXqH4MnDw46f3yyrRwau3JF92Y1ie3pAXf",
      "created_at": "2026-09-30T10:00:00Z",
      "expiry_time": "2026-09-30T10:10:00Z"
    }
  }
  ```
</CodeGroup>

`payment_method` and `network` are required. `payment_method` must be valid for the fiat, for example `IMPS` for INR.

## 4. Send the crypto

Send exactly `sending_amount` of the quoted asset, on the quoted network, to `wallet_address`, before `expiry_time`. Keep the transaction hash.

<Warning>
  A wrong asset, a wrong network or a wrong address can mean permanent loss. Read all three from the quotation. Never hardcode or reuse a deposit address.
</Warning>

## 5. Initiate the payout

Call [`POST /payout/initiate`](/api-reference-exchange/endpoint/payout/order/initiate).

```json theme={null}
{
  "quotation_id": "59bf60c3-e9af-40a7-9d5c-2a1aa191e769",
  "customer_id": "84737c7d-7b62-4204-80d6-80f6ecb3ceb4",
  "client_reference_id": "payout-001",
  "transaction_hash": "0x9f2c3b1a..."
}
```

* A `transaction_hash` can fund one payout only. EVM hashes are compared without regard to case.
* Zapyd verifies the transfer on-chain before it pays out.

The payout starts as `PROCESSING`. Most payouts complete within 30 to 60 minutes. Bank delays can stretch this to 24 hours.

## 6. Track the result

Zapyd doesn't send a webhook for `PROCESSING`. You receive one for each status after that:

| Event | Meaning | Metadata | Your action |
| - | - | - | - |
| `SUCCESS` | Fiat delivered | `utr`: the bank reference | Show the UTR to the user |
| `IN_REVIEW` | Compliance review, or a request for information | `reason`, and `rfi_link` when the customer must answer | Send the customer to `rfi_link`. Otherwise wait |
| `FAILED` | Payout failed | `failure_reason`: always `Payout failed` | Tell the user. Contact support with the payout `id` for details |
| `REFUNDED` | The funds were returned | `refund_reason` | Tell the user |

Every payout event also carries your `client_reference_id`. To poll instead, call [`GET /payout/{payout_id}`](/api-reference-exchange/endpoint/payout/order/\{payout_id}), or list orders with [`GET /payout/history`](/api-reference-exchange/endpoint/payout/order/history).

## Test it in sandbox

1. Create a quotation on `sepolia`, and send testnet USDT or USDC to `wallet_address`.
2. Initiate with the Sepolia transaction hash.
3. Move the payout with [Mock Payout Status](/api-reference-exchange/endpoint/payout/order/mock-payout-status): `SUCCESS`, `FAILED` or `REFUNDED`.
