Create Transaction
curl --request POST \
--url https://api.stablepay.global/v2/transactions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"type": "<string>",
"userId": "<string>",
"amountInr": "<string>",
"amount": "<string>",
"asset": "<string>",
"network": "<string>",
"partnerReference": "<string>",
"metadata": {}
}
'import requests
url = "https://api.stablepay.global/v2/transactions"
payload = {
"type": "<string>",
"userId": "<string>",
"amountInr": "<string>",
"amount": "<string>",
"asset": "<string>",
"network": "<string>",
"partnerReference": "<string>",
"metadata": {}
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: '<string>',
userId: '<string>',
amountInr: '<string>',
amount: '<string>',
asset: '<string>',
network: '<string>',
partnerReference: '<string>',
metadata: {}
})
};
fetch('https://api.stablepay.global/v2/transactions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.stablepay.global/v2/transactions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'type' => '<string>',
'userId' => '<string>',
'amountInr' => '<string>',
'amount' => '<string>',
'asset' => '<string>',
'network' => '<string>',
'partnerReference' => '<string>',
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.stablepay.global/v2/transactions"
payload := strings.NewReader("{\n \"type\": \"<string>\",\n \"userId\": \"<string>\",\n \"amountInr\": \"<string>\",\n \"amount\": \"<string>\",\n \"asset\": \"<string>\",\n \"network\": \"<string>\",\n \"partnerReference\": \"<string>\",\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.stablepay.global/v2/transactions")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"<string>\",\n \"userId\": \"<string>\",\n \"amountInr\": \"<string>\",\n \"amount\": \"<string>\",\n \"asset\": \"<string>\",\n \"network\": \"<string>\",\n \"partnerReference\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.stablepay.global/v2/transactions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"<string>\",\n \"userId\": \"<string>\",\n \"amountInr\": \"<string>\",\n \"amount\": \"<string>\",\n \"asset\": \"<string>\",\n \"network\": \"<string>\",\n \"partnerReference\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"transactionId": "txn_xyz789",
"type": "sell",
"status": "deposit_pending",
"depositAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f3A123",
"depositNetwork": "ethereum",
"depositAsset": "USDT",
"expectedAmount": "100",
"quote": {
"exchangeRate": 84.50,
"feePercent": 0.005,
"feeInr": "42.25",
"grossInr": "8450.00",
"netInr": "8407.75"
},
"expiresAt": "2025-06-16T10:30:00Z"
}
}
{
"success": true,
"data": {
"transactionId": "tx-uuid",
"type": "pool_settlement",
"status": "payout_processing",
"amountInr": "100000.00",
"settlementInr": "99000.00",
"tds": { "applicable": true, "percent": "1", "amountInr": "1000.00" },
"recipient": { "bank": "HDFC Bank", "account": "XXXXXX7890", "name": "RAHUL KUMAR" },
"payout": { "status": "processing", "amountInr": "99000.00", "rail": "imps" }
}
}
{
"error": "INSUFFICIENT_BALANCE",
"message": "Amount exceeds available INR balance (₹5000.00)"
}
{
"error": "KYC_INCOMPLETE",
"message": "User KYC is not complete"
}
Transactions
Create Transaction
Create a new transaction (sell, pool settlement, or buy)
POST
/
v2
/
transactions
Create Transaction
curl --request POST \
--url https://api.stablepay.global/v2/transactions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"type": "<string>",
"userId": "<string>",
"amountInr": "<string>",
"amount": "<string>",
"asset": "<string>",
"network": "<string>",
"partnerReference": "<string>",
"metadata": {}
}
'import requests
url = "https://api.stablepay.global/v2/transactions"
payload = {
"type": "<string>",
"userId": "<string>",
"amountInr": "<string>",
"amount": "<string>",
"asset": "<string>",
"network": "<string>",
"partnerReference": "<string>",
"metadata": {}
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: '<string>',
userId: '<string>',
amountInr: '<string>',
amount: '<string>',
asset: '<string>',
network: '<string>',
partnerReference: '<string>',
metadata: {}
})
};
fetch('https://api.stablepay.global/v2/transactions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.stablepay.global/v2/transactions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'type' => '<string>',
'userId' => '<string>',
'amountInr' => '<string>',
'amount' => '<string>',
'asset' => '<string>',
'network' => '<string>',
'partnerReference' => '<string>',
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.stablepay.global/v2/transactions"
payload := strings.NewReader("{\n \"type\": \"<string>\",\n \"userId\": \"<string>\",\n \"amountInr\": \"<string>\",\n \"amount\": \"<string>\",\n \"asset\": \"<string>\",\n \"network\": \"<string>\",\n \"partnerReference\": \"<string>\",\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.stablepay.global/v2/transactions")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"<string>\",\n \"userId\": \"<string>\",\n \"amountInr\": \"<string>\",\n \"amount\": \"<string>\",\n \"asset\": \"<string>\",\n \"network\": \"<string>\",\n \"partnerReference\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.stablepay.global/v2/transactions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"<string>\",\n \"userId\": \"<string>\",\n \"amountInr\": \"<string>\",\n \"amount\": \"<string>\",\n \"asset\": \"<string>\",\n \"network\": \"<string>\",\n \"partnerReference\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"transactionId": "txn_xyz789",
"type": "sell",
"status": "deposit_pending",
"depositAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f3A123",
"depositNetwork": "ethereum",
"depositAsset": "USDT",
"expectedAmount": "100",
"quote": {
"exchangeRate": 84.50,
"feePercent": 0.005,
"feeInr": "42.25",
"grossInr": "8450.00",
"netInr": "8407.75"
},
"expiresAt": "2025-06-16T10:30:00Z"
}
}
{
"success": true,
"data": {
"transactionId": "tx-uuid",
"type": "pool_settlement",
"status": "payout_processing",
"amountInr": "100000.00",
"settlementInr": "99000.00",
"tds": { "applicable": true, "percent": "1", "amountInr": "1000.00" },
"recipient": { "bank": "HDFC Bank", "account": "XXXXXX7890", "name": "RAHUL KUMAR" },
"payout": { "status": "processing", "amountInr": "99000.00", "rail": "imps" }
}
}
{
"error": "INSUFFICIENT_BALANCE",
"message": "Amount exceeds available INR balance (₹5000.00)"
}
{
"error": "KYC_INCOMPLETE",
"message": "User KYC is not complete"
}
Create Transaction
Creates a new transaction. Thetype parameter determines the flow.
See the Transaction Lifecycle guide for status flows and the Pool Settlement guide for the two-step pool workflow.
Idempotency Required: Include an
Idempotency-Key header (UUID) to prevent duplicate transactions. See Idempotency for details.Headers
A unique UUID for each transaction. One key = one transaction.
Body Parameters
Transaction type:
sell, pool_settlement, or buy. (payout is an accepted alias for pool_settlement.)The user ID. Must have completed KYC when KYC is enforced on your account.
pool_settlement only. Gross INR to disburse from your escrow balance. TDS (if enabled) is withheld from this — the user receives the net.sell only. Amount in stablecoin units (e.g., “100”).sell only. Stablecoin: USDC or USDTsell only. Blockchain: polygon, ethereum, arbitrum, base, tronYour internal reference ID. For
pool_settlement, this is also a business idempotency key: retrying with the same partnerReference returns the original payout and never sends a second transfer.Custom key-value metadata
Request
- sell
- pool_settlement
curl -X POST https://api.stablepay.global/v2/transactions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-d '{
"type": "sell",
"userId": "usr_abc123",
"amount": "100",
"asset": "USDT",
"network": "ethereum",
"partnerReference": "order_456"
}'
Only available on accounts with
transactionMode: sell or transactionMode: both.curl -X POST https://api.stablepay.global/v2/transactions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-d '{
"type": "pool_settlement",
"userId": "usr_abc123",
"amountInr": "100000",
"partnerReference": "disbursal_789"
}'
Disburses INR from your escrow balance to a user’s verified bank account. Single call — the payout is initiated immediately; there is no separate step. See Pool Settlement for how the balance is funded.
type: "payout" is an accepted alias for the same flow.Response
- sell
- pool_settlement
{
"success": true,
"data": {
"transactionId": "txn_xyz789",
"type": "sell",
"status": "deposit_pending",
"depositAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f3A123",
"depositNetwork": "ethereum",
"depositAsset": "USDT",
"expectedAmount": "100",
"quote": {
"exchangeRate": 84.50,
"feePercent": 0.005,
"feeInr": "42.25",
"grossInr": "8450.00",
"netInr": "8407.75"
},
"expiresAt": "2025-06-16T10:30:00Z"
}
}
{
"success": true,
"data": {
"transactionId": "tx-uuid",
"status": "payout_processing",
"type": "pool_settlement",
"amountInr": "100000.00",
"settlementInr": "99000.00",
"tds": { "applicable": true, "percent": "1", "amountInr": "1000.00" },
"recipient": { "bank": "HDFC Bank", "account": "XXXXXX7890", "name": "RAHUL KUMAR" },
"payout": { "status": "processing", "amountInr": "99000.00", "rail": "imps" }
}
}
amountInr is the gross debited from your escrow; settlementInr is the net the user receives (gross − TDS). A replay of the same partnerReference returns the original transaction with idempotentReplayed: true. See the Pool Settlement guide for the payout lifecycle, TDS, and failure handling.Errors
| Code | Description | Applies To |
|---|---|---|
IDEMPOTENCY_KEY_REQUIRED | Missing Idempotency-Key header | All |
INVALID_TYPE | Invalid transaction type | All |
USER_NOT_FOUND | User doesn’t exist | All |
KYC_INCOMPLETE | User hasn’t completed KYC | All |
NO_BANK_ACCOUNT | No verified bank account | All |
AMOUNT_TOO_LOW | Below minimum ($10) | sell |
AMOUNT_TOO_HIGH | Above maximum ($50,000) | sell |
PENDING_TRANSACTION_EXISTS | User has an active transaction | sell |
INVALID_AMOUNT | amountInr is not a positive number | pool_settlement |
AMOUNT_EXCEEDS_IMPS_LIMIT | Above the ₹5,00,000 per-transaction IMPS cap | pool_settlement |
INSUFFICIENT_BALANCE | amountInr exceeds your available escrow INR balance | pool_settlement |
DUPLICATE_PARTNER_REFERENCE | A payout with this partnerReference already exists | pool_settlement |
PAYOUT_FAILED | The bank rail rejected the transfer (escrow debit reversed) | pool_settlement |
{
"success": true,
"data": {
"transactionId": "txn_xyz789",
"type": "sell",
"status": "deposit_pending",
"depositAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f3A123",
"depositNetwork": "ethereum",
"depositAsset": "USDT",
"expectedAmount": "100",
"quote": {
"exchangeRate": 84.50,
"feePercent": 0.005,
"feeInr": "42.25",
"grossInr": "8450.00",
"netInr": "8407.75"
},
"expiresAt": "2025-06-16T10:30:00Z"
}
}
{
"success": true,
"data": {
"transactionId": "tx-uuid",
"type": "pool_settlement",
"status": "payout_processing",
"amountInr": "100000.00",
"settlementInr": "99000.00",
"tds": { "applicable": true, "percent": "1", "amountInr": "1000.00" },
"recipient": { "bank": "HDFC Bank", "account": "XXXXXX7890", "name": "RAHUL KUMAR" },
"payout": { "status": "processing", "amountInr": "99000.00", "rail": "imps" }
}
}
{
"error": "INSUFFICIENT_BALANCE",
"message": "Amount exceeds available INR balance (₹5000.00)"
}
{
"error": "KYC_INCOMPLETE",
"message": "User KYC is not complete"
}
⌘I
