Create withdrawal
curl --request POST \
--url https://api.stabyl.com/v1/partner/wallets/withdrawals \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--header 'X-Stabyl-Nonce: <x-stabyl-nonce>' \
--header 'X-Stabyl-Signature: <x-stabyl-signature>' \
--header 'X-Stabyl-Timestamp: <x-stabyl-timestamp>' \
--data '
{
"currency": "USD",
"idempotency_key": "partner-withdrawal-20260711-001",
"items": [
{
"amount": "100.00",
"client_item_id": "vendor-a",
"destination": {
"address": "0xRecipient",
"chain": "evm",
"slug": "base",
"type": "crypto_address"
}
}
],
"settlement_rail": "USDC"
}
'import requests
url = "https://api.stabyl.com/v1/partner/wallets/withdrawals"
payload = {
"currency": "USD",
"idempotency_key": "partner-withdrawal-20260711-001",
"items": [
{
"amount": "100.00",
"client_item_id": "vendor-a",
"destination": {
"address": "0xRecipient",
"chain": "evm",
"slug": "base",
"type": "crypto_address"
}
}
],
"settlement_rail": "USDC"
}
headers = {
"X-Stabyl-Timestamp": "<x-stabyl-timestamp>",
"X-Stabyl-Nonce": "<x-stabyl-nonce>",
"X-Stabyl-Signature": "<x-stabyl-signature>",
"X-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-Stabyl-Timestamp': '<x-stabyl-timestamp>',
'X-Stabyl-Nonce': '<x-stabyl-nonce>',
'X-Stabyl-Signature': '<x-stabyl-signature>',
'X-Api-Key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
currency: 'USD',
idempotency_key: 'partner-withdrawal-20260711-001',
items: [
{
amount: '100.00',
client_item_id: 'vendor-a',
destination: {address: '0xRecipient', chain: 'evm', slug: 'base', type: 'crypto_address'}
}
],
settlement_rail: 'USDC'
})
};
fetch('https://api.stabyl.com/v1/partner/wallets/withdrawals', 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.stabyl.com/v1/partner/wallets/withdrawals",
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([
'currency' => 'USD',
'idempotency_key' => 'partner-withdrawal-20260711-001',
'items' => [
[
'amount' => '100.00',
'client_item_id' => 'vendor-a',
'destination' => [
'address' => '0xRecipient',
'chain' => 'evm',
'slug' => 'base',
'type' => 'crypto_address'
]
]
],
'settlement_rail' => 'USDC'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Api-Key: <api-key>",
"X-Stabyl-Nonce: <x-stabyl-nonce>",
"X-Stabyl-Signature: <x-stabyl-signature>",
"X-Stabyl-Timestamp: <x-stabyl-timestamp>"
],
]);
$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.stabyl.com/v1/partner/wallets/withdrawals"
payload := strings.NewReader("{\n \"currency\": \"USD\",\n \"idempotency_key\": \"partner-withdrawal-20260711-001\",\n \"items\": [\n {\n \"amount\": \"100.00\",\n \"client_item_id\": \"vendor-a\",\n \"destination\": {\n \"address\": \"0xRecipient\",\n \"chain\": \"evm\",\n \"slug\": \"base\",\n \"type\": \"crypto_address\"\n }\n }\n ],\n \"settlement_rail\": \"USDC\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Stabyl-Timestamp", "<x-stabyl-timestamp>")
req.Header.Add("X-Stabyl-Nonce", "<x-stabyl-nonce>")
req.Header.Add("X-Stabyl-Signature", "<x-stabyl-signature>")
req.Header.Add("X-Api-Key", "<api-key>")
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.stabyl.com/v1/partner/wallets/withdrawals")
.header("X-Stabyl-Timestamp", "<x-stabyl-timestamp>")
.header("X-Stabyl-Nonce", "<x-stabyl-nonce>")
.header("X-Stabyl-Signature", "<x-stabyl-signature>")
.header("X-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"currency\": \"USD\",\n \"idempotency_key\": \"partner-withdrawal-20260711-001\",\n \"items\": [\n {\n \"amount\": \"100.00\",\n \"client_item_id\": \"vendor-a\",\n \"destination\": {\n \"address\": \"0xRecipient\",\n \"chain\": \"evm\",\n \"slug\": \"base\",\n \"type\": \"crypto_address\"\n }\n }\n ],\n \"settlement_rail\": \"USDC\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.stabyl.com/v1/partner/wallets/withdrawals")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Stabyl-Timestamp"] = '<x-stabyl-timestamp>'
request["X-Stabyl-Nonce"] = '<x-stabyl-nonce>'
request["X-Stabyl-Signature"] = '<x-stabyl-signature>'
request["X-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"currency\": \"USD\",\n \"idempotency_key\": \"partner-withdrawal-20260711-001\",\n \"items\": [\n {\n \"amount\": \"100.00\",\n \"client_item_id\": \"vendor-a\",\n \"destination\": {\n \"address\": \"0xRecipient\",\n \"chain\": \"evm\",\n \"slug\": \"base\",\n \"type\": \"crypto_address\"\n }\n }\n ],\n \"settlement_rail\": \"USDC\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"amount": "200000000.00",
"currency": "NGN",
"debit_amount": "200000200.00",
"estimated_receive": "200000000.00",
"fee": "200.00",
"id": "0197f1f0-0000-7000-8000-000000000014",
"items": [
{
"amount": "200000000.00",
"client_item_id": "beneficiary-1",
"destination": {
"account_name": "Example Recipient",
"account_number": "0123456789",
"bank_code": "044",
"bank_name": "Access Bank",
"type": "bank_account"
},
"transfers": [
{
"amount": "100000000.00",
"sequence": 1,
"status": "pending"
},
{
"amount": "100000000.00",
"sequence": 2,
"status": "pending"
}
]
}
],
"max_transfer_amount": "100000000.00",
"rail": "fiat",
"receive_currency": "NGN",
"reference": "WD-0197f1f000007000",
"status": "processing",
"transfer_count": 2,
"tx_type": "withdrawal"
},
"status": "success"
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "invalid request parameters"
},
"status": "error"
}{
"error": {
"code": "UNAUTHORIZED",
"message": "missing X-Api-Key header"
},
"status": "error"
}{
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "insufficient balance"
},
"status": "error"
}{
"error": {
"code": "FORBIDDEN",
"message": "request is not allowed"
},
"status": "error"
}{
"error": {
"code": "CONFLICT",
"message": "idempotency key already used"
},
"status": "error"
}Wallets
Create withdrawal
Directly creates one parent withdrawal from the signed list request. Production requires approved KYB for every supported NGN and USD rail. Store the returned transaction ID and reconcile status and split-transfer outcomes through wallet transaction reads.
POST
/
partner
/
wallets
/
withdrawals
Create withdrawal
curl --request POST \
--url https://api.stabyl.com/v1/partner/wallets/withdrawals \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--header 'X-Stabyl-Nonce: <x-stabyl-nonce>' \
--header 'X-Stabyl-Signature: <x-stabyl-signature>' \
--header 'X-Stabyl-Timestamp: <x-stabyl-timestamp>' \
--data '
{
"currency": "USD",
"idempotency_key": "partner-withdrawal-20260711-001",
"items": [
{
"amount": "100.00",
"client_item_id": "vendor-a",
"destination": {
"address": "0xRecipient",
"chain": "evm",
"slug": "base",
"type": "crypto_address"
}
}
],
"settlement_rail": "USDC"
}
'import requests
url = "https://api.stabyl.com/v1/partner/wallets/withdrawals"
payload = {
"currency": "USD",
"idempotency_key": "partner-withdrawal-20260711-001",
"items": [
{
"amount": "100.00",
"client_item_id": "vendor-a",
"destination": {
"address": "0xRecipient",
"chain": "evm",
"slug": "base",
"type": "crypto_address"
}
}
],
"settlement_rail": "USDC"
}
headers = {
"X-Stabyl-Timestamp": "<x-stabyl-timestamp>",
"X-Stabyl-Nonce": "<x-stabyl-nonce>",
"X-Stabyl-Signature": "<x-stabyl-signature>",
"X-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-Stabyl-Timestamp': '<x-stabyl-timestamp>',
'X-Stabyl-Nonce': '<x-stabyl-nonce>',
'X-Stabyl-Signature': '<x-stabyl-signature>',
'X-Api-Key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
currency: 'USD',
idempotency_key: 'partner-withdrawal-20260711-001',
items: [
{
amount: '100.00',
client_item_id: 'vendor-a',
destination: {address: '0xRecipient', chain: 'evm', slug: 'base', type: 'crypto_address'}
}
],
settlement_rail: 'USDC'
})
};
fetch('https://api.stabyl.com/v1/partner/wallets/withdrawals', 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.stabyl.com/v1/partner/wallets/withdrawals",
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([
'currency' => 'USD',
'idempotency_key' => 'partner-withdrawal-20260711-001',
'items' => [
[
'amount' => '100.00',
'client_item_id' => 'vendor-a',
'destination' => [
'address' => '0xRecipient',
'chain' => 'evm',
'slug' => 'base',
'type' => 'crypto_address'
]
]
],
'settlement_rail' => 'USDC'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Api-Key: <api-key>",
"X-Stabyl-Nonce: <x-stabyl-nonce>",
"X-Stabyl-Signature: <x-stabyl-signature>",
"X-Stabyl-Timestamp: <x-stabyl-timestamp>"
],
]);
$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.stabyl.com/v1/partner/wallets/withdrawals"
payload := strings.NewReader("{\n \"currency\": \"USD\",\n \"idempotency_key\": \"partner-withdrawal-20260711-001\",\n \"items\": [\n {\n \"amount\": \"100.00\",\n \"client_item_id\": \"vendor-a\",\n \"destination\": {\n \"address\": \"0xRecipient\",\n \"chain\": \"evm\",\n \"slug\": \"base\",\n \"type\": \"crypto_address\"\n }\n }\n ],\n \"settlement_rail\": \"USDC\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Stabyl-Timestamp", "<x-stabyl-timestamp>")
req.Header.Add("X-Stabyl-Nonce", "<x-stabyl-nonce>")
req.Header.Add("X-Stabyl-Signature", "<x-stabyl-signature>")
req.Header.Add("X-Api-Key", "<api-key>")
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.stabyl.com/v1/partner/wallets/withdrawals")
.header("X-Stabyl-Timestamp", "<x-stabyl-timestamp>")
.header("X-Stabyl-Nonce", "<x-stabyl-nonce>")
.header("X-Stabyl-Signature", "<x-stabyl-signature>")
.header("X-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"currency\": \"USD\",\n \"idempotency_key\": \"partner-withdrawal-20260711-001\",\n \"items\": [\n {\n \"amount\": \"100.00\",\n \"client_item_id\": \"vendor-a\",\n \"destination\": {\n \"address\": \"0xRecipient\",\n \"chain\": \"evm\",\n \"slug\": \"base\",\n \"type\": \"crypto_address\"\n }\n }\n ],\n \"settlement_rail\": \"USDC\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.stabyl.com/v1/partner/wallets/withdrawals")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Stabyl-Timestamp"] = '<x-stabyl-timestamp>'
request["X-Stabyl-Nonce"] = '<x-stabyl-nonce>'
request["X-Stabyl-Signature"] = '<x-stabyl-signature>'
request["X-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"currency\": \"USD\",\n \"idempotency_key\": \"partner-withdrawal-20260711-001\",\n \"items\": [\n {\n \"amount\": \"100.00\",\n \"client_item_id\": \"vendor-a\",\n \"destination\": {\n \"address\": \"0xRecipient\",\n \"chain\": \"evm\",\n \"slug\": \"base\",\n \"type\": \"crypto_address\"\n }\n }\n ],\n \"settlement_rail\": \"USDC\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"amount": "200000000.00",
"currency": "NGN",
"debit_amount": "200000200.00",
"estimated_receive": "200000000.00",
"fee": "200.00",
"id": "0197f1f0-0000-7000-8000-000000000014",
"items": [
{
"amount": "200000000.00",
"client_item_id": "beneficiary-1",
"destination": {
"account_name": "Example Recipient",
"account_number": "0123456789",
"bank_code": "044",
"bank_name": "Access Bank",
"type": "bank_account"
},
"transfers": [
{
"amount": "100000000.00",
"sequence": 1,
"status": "pending"
},
{
"amount": "100000000.00",
"sequence": 2,
"status": "pending"
}
]
}
],
"max_transfer_amount": "100000000.00",
"rail": "fiat",
"receive_currency": "NGN",
"reference": "WD-0197f1f000007000",
"status": "processing",
"transfer_count": 2,
"tx_type": "withdrawal"
},
"status": "success"
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "invalid request parameters"
},
"status": "error"
}{
"error": {
"code": "UNAUTHORIZED",
"message": "missing X-Api-Key header"
},
"status": "error"
}{
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "insufficient balance"
},
"status": "error"
}{
"error": {
"code": "FORBIDDEN",
"message": "request is not allowed"
},
"status": "error"
}{
"error": {
"code": "CONFLICT",
"message": "idempotency key already used"
},
"status": "error"
}Withdrawal quote and submit calls require an Ed25519 signature over the exact HTTP method, request path and query, timestamp, nonce, and raw body hash. Reuse the business idempotency key with a new timestamp, nonce, and signature when retrying an uncertain response.
Authorizations
Headers
Body
application/json
List-shaped withdrawal request to execute directly. Include a stable business idempotency key and do not send an authorization token.
Response
Parent withdrawal accepted
Was this page helpful?