Api References
Payout
Processes a payout to a specified account.
Endpoint
POST https://merchant.dv.vai247.pro/api/v1/payment-gateway/order/payout
Required Headers
| Header | Type | Required | Description |
|---|---|---|---|
X-Api-Key | string | Yes | Your API key |
X-Timestamp | string | Yes | Unix timestamp in seconds |
X-Signature | string | Yes | HMAC-SHA256 signature (see below) |
X-Idempotent-Key | string | Yes | Unique key to prevent duplicate payouts (UUID recommended) |
Important:
- The
X-Signatureheader requires HMAC-SHA256 signature generation using your API secret - The
X-Idempotent-Keyheader is required to prevent accidental duplicate payouts - Use a unique identifier (UUID) for each payout operation
Generating the Signature
The X-Signature header must contain an HMAC-SHA256 signature of your request:
Formula:
message = rawPayload + timestamp
signature = HMAC-SHA256(message, api_secret)
Where:
rawPayload= JSON request body as a string (e.g.,{"accountNumber":"123456789","amount":100,"currency":"USD"})timestamp= Unix timestamp in seconds (same value asX-Timestampheader)api_secret= Your API secret from DVPay mobile app
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
accountNumber | string | Yes | Recipient account number |
amount | number | Yes | Payout amount |
currency | string | Yes | Currency code (USD, KHR) |
Code Examples
package main
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
"time"
"github.com/google/uuid"
)
type PayoutRequest struct {
AccountNumber string `json:"accountNumber"`
Amount float64 `json:"amount"`
Currency string `json:"currency"`
}
type PayoutResponse struct {
AccountName string `json:"accountName"`
AccountNumber string `json:"accountNumber"`
Amount float64 `json:"amount"`
Currency string `json:"currency"`
OrderID int64 `json:"orderId"`
Remark string `json:"remark"`
TransactionDate string `json:"transactionDate"`
TransactionID int64 `json:"transactionId"`
}
func generateSignature(secret, timestamp, rawPayload string) string {
// Create message: rawPayload + timestamp
message := rawPayload + timestamp
// Create HMAC with SHA256
h := hmac.New(sha256.New, []byte(secret))
h.Write([]byte(message))
// Return hex digest
return hex.EncodeToString(h.Sum(nil))
}
func processPayout(accountNumber string, amount float64, currency, apiKey, apiSecret string) (*PayoutResponse, error) {
url := "https://merchant.dv.vai247.pro/api/v1/payment-gateway/order/payout"
payload := PayoutRequest{
AccountNumber: accountNumber,
Amount: amount,
Currency: currency,
}
jsonData, err := json.Marshal(payload)
if err != nil {
return nil, err
}
rawPayload := string(jsonData)
// Generate timestamp
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
// Generate signature
signature := generateSignature(apiSecret, timestamp, rawPayload)
// Generate idempotent key
idempotentKey := uuid.New().String()
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
return nil, err
}
// Add authentication headers
req.Header.Set("X-Api-Key", apiKey)
req.Header.Set("X-Timestamp", timestamp)
req.Header.Set("X-Signature", signature)
req.Header.Set("X-Idempotent-Key", idempotentKey)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result PayoutResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return &result, nil
}
func main() {
payout, err := processPayout("123456789", 100.00, "USD", "your-api-key", "your-api-secret")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Transaction ID: %d\n", payout.TransactionID)
fmt.Printf("Account: %s (%s)\n", payout.AccountName, payout.AccountNumber)
fmt.Printf("Amount: %.2f %s\n", payout.Amount, payout.Currency)
}
const axios = require('axios');
const crypto = require('crypto');
const { v4: uuidv4 } = require('uuid');
function generateSignature(secret, timestamp, rawPayload) {
// Create HMAC with SHA256
const hmac = crypto.createHmac('sha256', secret);
// Create message: rawPayload + timestamp
const message = rawPayload + timestamp.toString();
// Update HMAC with message and get hex digest
hmac.update(message);
return hmac.digest('hex');
}
async function processPayout(accountNumber, amount, currency, apiKey, apiSecret) {
const url = 'https://merchant.dv.vai247.pro/api/v1/payment-gateway/order/payout';
// Create payload
const payload = {
accountNumber: accountNumber,
amount: amount,
currency: currency
};
const rawPayload = JSON.stringify(payload);
// Generate timestamp
const timestamp = Math.floor(Date.now() / 1000);
// Generate signature
const signature = generateSignature(apiSecret, timestamp, rawPayload);
// Generate idempotent key
const idempotentKey = uuidv4();
// Make request
const headers = {
'X-Api-Key': apiKey,
'X-Timestamp': timestamp.toString(),
'X-Signature': signature,
'X-Idempotent-Key': idempotentKey,
'Content-Type': 'application/json'
};
try {
const response = await axios.post(url, payload, { headers });
return response.data;
} catch (error) {
console.error('Error processing payout:', error.response?.data || error.message);
throw error;
}
}
// Usage
(async () => {
try {
const payout = await processPayout('123456789', 100.00, 'USD', 'your-api-key', 'your-api-secret');
console.log('Transaction ID:', payout.data.transactionId);
console.log('Account:', `${payout.data.accountName} (${payout.data.accountNumber})`);
console.log('Amount:', `${payout.data.amount} ${payout.data.currency}`);
} catch (error) {
console.error('Failed to process payout');
}
})();
Response
{
"statusCode": 200,
"message": "Success",
"data": {
"accountName": "John Doe",
"accountNumber": "123456789",
"amount": 100.00,
"currency": "USD",
"orderId": 1234567890,
"remark": "",
"transactionDate": "2026-03-02T12:00:00Z",
"transactionId": 9876543210
},
"traceId": "trace_abc123"
}
Notes
- Signature Required: All payout requests must include a valid
X-Signatureheader generated using HMAC-SHA256 - Idempotency: Each payout request requires a unique
X-Idempotent-Keyheader. If you retry a request with the same key, the API will return the original response without processing a duplicate payout - Verify account balance before initiating payouts
- Payouts typically process within 1-2 business days
- Failed payouts are automatically reversed
X-App-Id header has been removed. Use signature-based authentication with X-Signature header instead. See v1.4.0 Release Notes for migration guide.