Sign in
Thanh toán và rút tiền/Payout API

Payout API

Gửi rút tiền từ số dư merchant đến bất kỳ địa chỉ blockchain nào.

Payout API cho phép bạn rút tiền theo chương trình từ số dư merchant đến bất kỳ địa chỉ blockchain nào.

Đối với tất cả endpoint Payout, bạn phải sử dụng một Payout API key riêng để tạo chữ ký sign. Key này khác với API key thông thường và phải được tạo trong phần cài đặt project.

Tạo rút tiền

Tạo một yêu cầu rút tiền từ số dư merchant.

POST/v1/payout

Tham số yêu cầu

FieldTypeRequiredDescription
currencystringyesĐồng tiền rút (xem References)
networkstringyesMã mạng (xem References)
amountstringyesSố tiền rút
to_addressstringyesĐịa chỉ blockchain nhận tiền
order_idstringnoIdempotency key — duy nhất trong phạm vi project. Một POST lặp lại với cùng order_id sẽ không tạo rút tiền mới — thay vào đó trả về cái đã tồn tại
url_callbackstringnoURL nhận webhook rút tiền. Bỏ trống để tắt webhook cho rút tiền này
memostring | nullnoDestination tag / memo. Hiện tại chỉ được dùng bởi mạng TONSOL; tối đa 255 ký tự
from_currencystringnoSố dư nguồn sẽ bị trừ và tự động quy đổi sang currency tại thời điểm rút tiền. Cho phép bạn rút bằng các tài sản biến động (BTC, ETH, …) trong khi vẫn giữ số dư bằng stablecoin như USDT — bạn không phải tự nắm giữ tiền điện tử biến động. Truyền "USDT" để trừ từ số dư USDT
fee_optionstringnoCách thu phí. deduct (mặc định) — phí mạng + phí nền tảng được trừ vào amount, người nhận nhận được amount - fees. add — phí được cộng thêm, merchant bị trừ amount + fees, người nhận nhận đúng amount

Idempotency. Trong một project, một rút tiền là duy nhất theo order_id. Gửi lại cùng POST với cùng order_idan toàn — API trả về rút tiền hiện có thay vì tạo bản trùng lặp. Hãy luôn truyền order_id cho các rút tiền production.

Ví dụ yêu cầu

Shell
curl -X POST https://api.2328.io/api/v1/payout \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
  -H "project: YOUR_PROJECT_UUID" \
  -H "sign: YOUR_HMAC_SIGNATURE" \
  -d '{"currency":"TRX","network":"TRX-TRC20","amount":"1.00","to_address":"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t","order_id":"9ed25264-8be4-439f-acf5-2a8732538d27","url_callback":"https://your-site.com/webhook/payout","memo":null,"fee_option":"deduct"}'

Ví dụ phản hồi

JSON
{
  "state": 0,
  "result": {
    "uuid": "019dea62-1727-72aa-ac2c-eaf2ade193ef",
    "order_id": "9ed25264-8be4-439f-acf5-2a8732538d27",
    "status": "pending",
    "currency": "TRX",
    "network": "TRX-TRC20",
    "amount": "1.00",
    "merchant_amount": "1",
    "network_amount": "0.89",
    "amount_usd": "0.33",
    "to_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
    "memo": null,
    "txid": null,
    "block_number": null,
    "error_type": null,
    "created_at": "2026-05-02T23:29:50+03:00",
    "updated_at": "2026-05-02T23:29:50+03:00"
  }
}

Phí. Mặc định fee_option: deduct — phí mạng + phí nền tảng được trừ vào amount (người nhận nhận amount - fees). Truyền fee_option: add để cộng phí lên trên — người nhận nhận đúng amount và merchant bị trừ amount + fees.

Tính toán rút tiền

Ước tính số tiền và phí rút mà không tạo rút tiền và không trừ số dư của bạn. Dùng để hiển thị cho người dùng số tiền chính xác họ sẽ nhận (hoặc trả) trước khi xác nhận.

POST/v1/payout/calc

Tham số yêu cầu

Giống hệt với Tạo rút tiền — cùng các trường, cùng chữ ký. order_id, url_callback, to_addressmemo được chấp nhận nhưng bị bỏ qua: không có rút tiền nào được lưu và không có callback nào được gửi.

Ví dụ yêu cầu

Shell
curl -X POST https://api.2328.io/api/v1/payout/calc \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
  -H "project: YOUR_PROJECT_UUID" \
  -H "sign: YOUR_HMAC_SIGNATURE" \
  -d '{"currency":"USDT","network":"TRX-TRC20","amount":"100","fee_option":"add"}'

Ví dụ phản hồi

JSON
{
  "state": 0,
  "result": {
    "currency": "USDT",
    "network": "TRX-TRC20",
    "amount": "100",
    "fee_option": "add",
    "merchant_amount": "103.00000000",
    "network_amount": "100",
    "total_fee": "3.00000000",
    "total_fee_usd": "3.00000000"
  }
}

Chỉ xem trước. Endpoint này chỉ đọc — không có số dư nào bị trừ và không có bản ghi rút tiền nào được tạo. Hãy gọi tuỳ ý để hiển thị chi tiết phí trong UI của bạn.

Trạng thái rút tiền

Lấy trạng thái của một yêu cầu rút tiền.

GET/v1/payout/status/{uuid}

Tham số đường dẫn

FieldTypeRequiredDescription
uuidstringyesUUID rút tiền (lấy từ result.uuid khi tạo)

Ví dụ phản hồi

JSON
{
  "state": 0,
  "result": {
    "uuid": "019dff1f-0dbd-7277-8d45-271e7775388f",
    "order_id": "4dfdcc84402b1185b71cbe399321533e",
    "status": "completed",
    "currency": "TRX",
    "network": "TRX-TRC20",
    "amount": "3.00",
    "merchant_amount": "3.00",
    "network_amount": "3.00",
    "amount_usd": "1.04",
    "to_address": "THauRv5tcucQRohXg8NiyGTk16DX1XQG5x",
    "memo": null,
    "txid": "9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
    "block_number": null,
    "error_type": null,
    "created_at": "2026-05-07T00:08:38+03:00",
    "updated_at": "2026-05-07T00:08:54+03:00",
    "from_currency": "USDT",
    "debited_amount": "1.050735",
    "debited_currency": "USDT"
  }
}

Đối với yêu cầu GET này, chữ ký được tính từ thân rỗng: hash_hmac('sha256', base64_encode(''), $apiKey)

Trường phản hồi

Các trường được trả về trong result từ POST /v1/payoutGET /v1/payout/status/{uuid}:

FieldTypeDescription
uuidstringUUID rút tiền do hệ thống cấp
order_idstringMã định danh rút tiền nội bộ của bạn (duy nhất trong project)
statusstringTrạng thái rút tiền hiện tại (xem bên dưới)
currencystringĐồng tiền rút
networkstringMã mạng
amountstringSố tiền rút theo yêu cầu
merchant_amountstringSố tiền bị trừ từ số dư merchant
network_amountstringSố tiền thực sự được gửi trên chuỗi (sau phí mạng + phí nền tảng)
amount_usdstringGiá trị quy đổi USD của số tiền rút
to_addressstringĐịa chỉ blockchain nhận tiền
memostring | nullDestination tag / memo (TON, SOL). Ngược lại là null
txidstring | nullHash giao dịch blockchain. null cho đến khi giao dịch được gửi
block_numberint | nullSố block chứa giao dịch. null cho đến khi được đưa vào
error_typestring | nullLý do thất bại khi status = failed (xem Error types bên dưới). Ngược lại là null
created_atstring (ISO 8601)Thời điểm tạo rút tiền
updated_atstring (ISO 8601)Thời điểm trạng thái thay đổi gần nhất
from_currencystring | nullSố dư nguồn mà khoản rút tiền đã bị trừ khi sử dụng quy đổi tự động (ví dụ USDT cho khoản rút BTC). null nếu không có quy đổi nào xảy ra
debited_amountstring | nullSố tiền thực sự bị trừ từ số dư nguồn sau quy đổi. Chỉ có khi sử dụng tự quy đổi
debited_currencystring | nullĐồng tiền của debited_amount — số dư từ đó tiền bị trừ

Trạng thái rút tiền

Trường status có thể nhận các giá trị sau:

StatusDescription
pendingĐã tạo, chờ xử lý
completedHoàn tất thành công — txid đã được đặt
failedLỗi gửi — xem error_type
cancelledĐã hủy

Loại lỗi

Khi status = failed, trường error_type mô tả lý do:

CodeDescription
aml_riskRút tiền bị chặn bởi kiểm tra rủi ro AML (địa chỉ người nhận bị đánh dấu rủi ro cao)

Thông báo webhook

Khi trạng thái của một rút tiền thay đổi, hệ thống sẽ gửi webhook POST đến URL url_callback được truyền khi tạo rút tiền. Nếu không cung cấp url_callback, sẽ không có webhook nào được gửi cho rút tiền đó.

  • Method: POST
  • Content-Type: application/json
  • Chữ ký: trường sign trong thân yêu cầu, được tính bằng Payout API key (cùng key dùng để ký yêu cầu rút tiền).

Payload phản chiếu object result từ GET /v1/payout/status/{uuid} cộng với một trường sign để xác minh.

Payload

JSON
{
  "uuid": "019dff1f-0dbd-7277-8d45-271e7775388f",
  "order_id": "4dfdcc84402b1185b71cbe399321533e",
  "status": "completed",
  "currency": "TRX",
  "network": "TRX-TRC20",
  "amount": "3.00",
  "merchant_amount": "3.00",
  "network_amount": "3.00",
  "amount_usd": "1.04",
  "to_address": "THauRv5tcucQRohXg8NiyGTk16DX1XQG5x",
  "memo": null,
  "txid": "9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
  "block_number": null,
  "error_type": null,
  "created_at": "2026-05-07T00:08:38+03:00",
  "updated_at": "2026-05-07T00:08:54+03:00",
  "from_currency": "USDT",
  "debited_amount": "1.050735",
  "debited_currency": "USDT",
  "sign": "925ad7bf3d6841864101f7cc2c7e30652e70a06cdb04dbe07a0129480000ce4a"
}

Xác minh chữ ký. Sử dụng cùng thuật toán như với webhook thanh toán, nhưng ký bằng Payout API key thay vì API key thông thường. Loại bỏ trường sign, mã hóa JSON phần payload còn lại, mã hóa Base64, sau đó tính hash_hmac('sha256', $base64, $payoutApiKey) và so sánh với sign nhận được.