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

# Payout

> This guide introduces GatePay's payout (withdrawal) capabilities for batch fund distribution, commission payouts, merchant settlements, and other bulk transfer scenarios.

## Overview

GatePay payout capabilities enable merchants to distribute funds to multiple recipients in a single batch operation. Common use cases include:

* Commission distribution to affiliates or partners
* Merchant settlement and revenue sharing
* Batch fund transfers to user wallets
* Royalty payments
* Refunds and chargebacks

In this guide, the terms "payout", "withdrawal", and "merchant-side fund transfer" all refer to the same outbound transfer capability. To keep the reading experience consistent, this page uses "payout" as the primary label.

***

## Prerequisites

Before integrating payout capabilities, you must complete the following setup steps:

1. **Application Creation**: Create a GatePay application in the merchant dashboard
2. **Retrieve ClientId**: Obtain your `ClientId` for API authentication
3. **Signing Key Configuration**: Configure your signing key for request authentication
4. **Callback URL Configuration**: Set up your callback endpoint for asynchronous notifications

For detailed setup instructions, see [Overview](/essentials/version/100/en/common/overview) and [Authentication and Security](/essentials/version/100/en/common/authentication).

***

## Payout Integration Steps

### Step 1: Query Fees and Limits

Before creating any payout batch, query the current fee structure and amount limits. These values may change dynamically and should not be cached.

**Request**:

```
POST /v1/pay/withdraw/query
```

This endpoint retrieves:

* Current withdrawal fees
* Minimum and maximum payout amounts
* Per-transaction limits
* Daily payout limits

Operationally, this step should be treated as more than a fee check. It is also the safest pre-flight validation before order creation, because it confirms the current payout path is available for the intended amount and conditions.

### Step 2: Create a Batch Payout

Create a batch containing one or more sub-orders (recipient withdrawal requests). Each batch is identified by a unique `batch_id`.

#### Minimum Integration Path

Operationally, the minimum payout path is usually:

1. call `POST /v1/pay/withdraw/query` to retrieve current fees and limits
2. call `POST /v1/pay/withdraw` to create the batch
3. process the payout callback notifications
4. use query endpoints as fallback confirmation when needed

For first-time merchants, it is best to validate the full lifecycle with a single sub-order before expanding to large batches.

### Step 3: Receive Callbacks and Track Status

GatePay sends asynchronous callbacks to your configured callback URL. These callbacks report both batch-level status and individual sub-order status.

**Callback Order**:

1. Initial callback when batch is created (`INIT` status)
2. Processing callback when batch enters processing (`PROCESSING` status)
3. Final callback with completion status (`SUCCESS`, `PARTIAL`, or `FAIL`)

### Step 4: Reconciliation and Fallback Queries

Use the query API as a fallback mechanism for:

* Verifying callback delivery
* Reconciling accounts
* Investigating failed transactions
* Confirming final status

If your business has strict confirmation requirements, it is helpful to treat "callback received" and "query confirmed" as two separate checkpoints rather than relying on only one of them.

***

## Callbacks First, Query as Fallback

GatePay's payout system prioritizes **asynchronous callbacks** for reliability and performance:

| Stage                | Primary Method                                               | Fallback                                                |
| -------------------- | ------------------------------------------------------------ | ------------------------------------------------------- |
| **Batch Status**     | Receive callbacks to `callbackUrl`                           | Use `POST /v1/pay/withdraw/query` to query batch status |
| **Sub-order Status** | Callbacks include sub-order details                          | Query individual sub-order details via query API        |
| **Reconciliation**   | Receive detailed callback payloads with all amounts and fees | Query endpoint for audit trails and confirmation        |

**Best Practice**: Implement callback handling as your primary status update mechanism. Use the query API only for fallback verification or periodic reconciliation.

For detailed callback information, signing, and verification procedures, see [Notification](/essentials/version/100/en/common/notification).

If you want to understand the callback status combinations first, continue with [Notification](/essentials/version/100/en/common/notification).

***

## Idempotency and Reconciliation

GatePay uses two key identifiers for idempotency and reconciliation:

| Field                  | Scope         | Purpose                                                           | Usage                                                        |
| ---------------------- | ------------- | ----------------------------------------------------------------- | ------------------------------------------------------------ |
| `merchant_withdraw_id` | Per sub-order | Merchant-assigned unique identifier for each withdrawal recipient | Idempotency; prevent duplicate payouts to the same recipient |
| `suborder_id`          | Per sub-order | GatePay-assigned unique identifier                                | Platform-side tracking, callbacks, and query operations      |

**Idempotency Guarantee**: If you resubmit a batch with the same `merchant_withdraw_id` values, GatePay will detect duplicates and prevent double-payments.

From the merchant system perspective, `merchant_withdraw_id` is best treated as a business reconciliation key rather than only as a technical idempotency field. That makes support handling, manual investigation, and ledger matching easier later.

***

## Batch and Sub-Order Statuses

### Batch Status Lifecycle

A batch progresses through the following states:

| Status       | Description                                                 |
| ------------ | ----------------------------------------------------------- |
| `INIT`       | Batch created; initial validation in progress               |
| `PROCESSING` | Batch being processed; funds are being transferred on-chain |
| `PARTIAL`    | Some sub-orders succeeded; others failed                    |
| `FAIL`       | Entire batch failed; no funds were distributed              |
| `SUCCESS`    | Entire batch succeeded; all sub-orders completed            |

### Sub-Order Status

Each withdrawal within a batch has its own status:

| Status | Description                                                       |
| ------ | ----------------------------------------------------------------- |
| `DONE` | Sub-order completed successfully; funds transferred and confirmed |
| `FAIL` | Sub-order failed; funds were not transferred or were reversed     |

***

## Callback Payload Structure

### Main Batch Callback Payload

When a batch status changes, GatePay sends a callback with the following main-order fields:

| Field             | Required | Description                                                                 |
| ----------------- | -------- | --------------------------------------------------------------------------- |
| `batch_id`        | Yes      | Unique batch identifier assigned by GatePay                                 |
| `merchant_id`     | Yes      | Your merchant ID from GatePay                                               |
| `status`          | Yes      | Current batch status: `INIT`, `PROCESSING`, `PARTIAL`, `FAIL`, or `SUCCESS` |
| `client_id`       | Yes      | The `client_id` used to create this batch                                   |
| `pay_back_status` | Yes      | Rollback/refund status for the batch                                        |
| `channel_id`      | Yes      | Channel identifier used for this payout batch                               |

### Sub-Order Array Callback Payload

Each callback includes a `suborders` array with detailed information about individual withdrawals:

| Field                  | Required | Description                                                   |
| ---------------------- | -------- | ------------------------------------------------------------- |
| `suborder_id`          | Yes      | GatePay-assigned sub-order identifier                         |
| `chain`                | Yes      | Blockchain network (e.g., Ethereum, Polygon)                  |
| `address`              | Yes      | Recipient wallet address                                      |
| `currency`             | Yes      | Payout currency (e.g., USDT, ETH)                             |
| `amount`               | Yes      | Requested payout amount in currency units                     |
| `fee`                  | Yes      | Actual fee deducted for this sub-order                        |
| `txHash`               | Yes      | Blockchain transaction hash (confirms on-chain transfer)      |
| `status`               | Yes      | Sub-order status: `DONE` or `FAIL`                            |
| `merchant_withdraw_id` | Yes      | Your merchant-assigned identifier for reconciliation          |
| `fee_type`             | Yes      | Fee deduction type: `0` (internal) or `1` (external)          |
| `finish_time`          | Yes      | Completion timestamp (Unix epoch in seconds)                  |
| `sub_amount`           | Yes      | Total amount for this sub-order (including fee if applicable) |
| `done_amount`          | Yes      | Amount actually credited to the recipient's address           |

### Fee Type Clarification

* **Fee Type 0 (Internal Deduction)**: Fee is deducted from the merchant's account; the full `amount` is sent to the recipient.
* **Fee Type 1 (External Deduction)**: Fee is deducted from the withdrawal amount; the recipient receives `amount - fee`.

***

## Error Handling

### Common Error Codes

When creating or processing payouts, you may encounter the following error codes:

| Error Code | Description                                         | Applicable API        | Recommended Handling                                                                           |
| ---------- | --------------------------------------------------- | --------------------- | ---------------------------------------------------------------------------------------------- |
| `550233`   | Insufficient balance in merchant account            | Batch payout creation | Check available balance via account balance query; top up account                              |
| `550234`   | Memo/description field exceeds maximum length       | Batch payout creation | Check memo length limits and truncate if necessary                                             |
| `550235`   | Amount precision exceeds allowed decimal places     | Batch payout creation | Verify amount precision matches currency requirements (e.g., USDT typically allows 6 decimals) |
| `550238`   | Batch contains too many sub-orders                  | Batch payout creation | Split into multiple batches with fewer sub-orders                                              |
| `550239`   | `amount` field is missing or empty                  | Batch payout creation | Verify `amount` is provided for each sub-order                                                 |
| `550240`   | `currency` field is missing or empty                | Batch payout creation | Verify `currency` is provided for each sub-order                                               |
| `550241`   | `address` field is missing or empty                 | Batch payout creation | Verify recipient address is provided for each sub-order                                        |
| `550242`   | `chain` field is missing or empty                   | Batch payout creation | Verify blockchain network is provided for each sub-order                                       |
| `550245`   | `batch_id` already exists (duplicate batch)         | Batch payout creation | Use a unique `batch_id` or leverage idempotency for retries                                    |
| `550249`   | Invalid `batch_id` or `merchant_withdraw_id` format | Batch payout creation | Ensure IDs are valid strings without special characters                                        |

### Error Response Handling

When an error occurs, GatePay returns an error response with:

* **Error Code**: Numeric identifier for the error
* **Error Message**: Human-readable description
* **Details**: Additional context (if available)

Implement retry logic with exponential backoff for transient errors (network issues, timeouts). For permanent errors (insufficient balance, invalid parameters), address the underlying issue before retrying.

***

## Reconciliation and Auditing

### Account Balance Reconciliation

Regularly reconcile your GatePay merchant account balance against your internal records:

1. **Query Fees Before Each Payout**: Get current fee rates
2. **Track Batch Status**: Monitor batch and sub-order status via callbacks
3. **Audit Amounts**: Verify `amount`, `fee`, and `done_amount` match your expectations
4. **Reconcile Daily**: Use query APIs to reconcile at end of day

For detailed reconciliation procedures, see [Balance](/essentials/version/100/en/common/balance).

### Investigating Failed Payouts

If a sub-order fails:

1. **Check Sub-Order Status**: Query the batch to get `status` for each sub-order
2. **Review Error Details**: Look for error reason in callback or query response
3. **Verify Recipient Address**: Ensure wallet address is valid for the specified chain
4. **Check Recipient Chain**: Confirm the recipient's wallet supports the specified blockchain
5. **Retry If Transient**: For temporary failures, resubmit with a new `batch_id` and same `merchant_withdraw_id`

***

## Query Payout Results

**Request**:

```
POST /v1/pay/withdraw/query
```

Query detailed results for a specific payout batch. This endpoint returns:

* Batch status and metadata
* Sub-order array with individual results
* Fee information
* Transaction hashes for on-chain verification

Use this endpoint for:

* Fallback verification if callbacks are delayed
* Periodic reconciliation
* Detailed audit trails
* Support and investigation

***

## Request Signing and Validation

All payout requests must use the standard GatePay signing mechanism. For request signing, signature generation, and callback verification details, see [Authentication and Security](/essentials/version/100/en/common/authentication).

Key signing requirements:

* Compute HMAC-SHA512 with the Payment API Secret using the `timestamp\nnonce\nbody\n` signing string
* Include the computed signature in the `X-GatePay-Signature` header
* Verify callbacks with the same Payment API Secret and signing rules

***

## Best Practices

1. **Query Fees Dynamically**: Always query current fees before creating a batch; do not cache fee values.
2. **Use Unique Identifiers**: Assign unique `merchant_withdraw_id` and `batch_id` values to prevent duplicates and enable idempotency.
3. **Implement Callback Handling**: Set up robust callback processing for real-time status updates.
4. **Monitor Batch Status**: Track batches through their lifecycle; alert on `PARTIAL` or `FAIL` status.
5. **Verify Transactions On-Chain**: For critical payouts, verify `txHash` on the blockchain explorer.
6. **Reconcile Daily**: Reconcile your internal account balance against GatePay records daily.
7. **Handle Errors Gracefully**: Implement proper error handling with exponential backoff for retries.
8. **Secure Your Signing Key**: Protect your signing key; never expose it in logs or to unauthorized parties.
9. **Validate Recipient Addresses**: Perform basic validation (checksum, format) on recipient addresses before submission.
10. **Plan for Rate Limits**: Be aware of API rate limits; implement request queuing for large batch operations.

***

## Related Documentation

* [Overview](/essentials/version/100/en/common/overview)
* [Authentication and Security](/essentials/version/100/en/common/authentication)
* [Notification](/essentials/version/100/en/common/notification)
* [Balance](/essentials/version/100/en/common/balance)
* [Notification](/essentials/version/100/en/common/notification)
