curl --request POST \
--url https://api-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"wallet_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"amount": 100.5,
"idempotency_key": "pay_req_20260604_abc123",
"destination_wallet_id": "c3d4e5f6-a7b8-9012-3456-7890abcdef01",
"user_id": "b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4",
"currency": "USD",
"payment_type": "transfer",
"metadata": {
"order_id": "ORD-12345"
},
"payment_category": 1,
"from_hold": false
}
'import requests
url = "https://api-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet"
payload = {
"wallet_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"amount": 100.5,
"idempotency_key": "pay_req_20260604_abc123",
"destination_wallet_id": "c3d4e5f6-a7b8-9012-3456-7890abcdef01",
"user_id": "b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4",
"currency": "USD",
"payment_type": "transfer",
"metadata": { "order_id": "ORD-12345" },
"payment_category": 1,
"from_hold": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
wallet_id: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
amount: 100.5,
idempotency_key: 'pay_req_20260604_abc123',
destination_wallet_id: 'c3d4e5f6-a7b8-9012-3456-7890abcdef01',
user_id: 'b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4',
currency: 'USD',
payment_type: 'transfer',
metadata: {order_id: 'ORD-12345'},
payment_category: 1,
from_hold: false
})
};
fetch('https://api-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet', 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-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet",
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([
'wallet_id' => 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
'amount' => 100.5,
'idempotency_key' => 'pay_req_20260604_abc123',
'destination_wallet_id' => 'c3d4e5f6-a7b8-9012-3456-7890abcdef01',
'user_id' => 'b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4',
'currency' => 'USD',
'payment_type' => 'transfer',
'metadata' => [
'order_id' => 'ORD-12345'
],
'payment_category' => 1,
'from_hold' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet"
payload := strings.NewReader("{\n \"wallet_id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n \"amount\": 100.5,\n \"idempotency_key\": \"pay_req_20260604_abc123\",\n \"destination_wallet_id\": \"c3d4e5f6-a7b8-9012-3456-7890abcdef01\",\n \"user_id\": \"b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4\",\n \"currency\": \"USD\",\n \"payment_type\": \"transfer\",\n \"metadata\": {\n \"order_id\": \"ORD-12345\"\n },\n \"payment_category\": 1,\n \"from_hold\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
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-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"wallet_id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n \"amount\": 100.5,\n \"idempotency_key\": \"pay_req_20260604_abc123\",\n \"destination_wallet_id\": \"c3d4e5f6-a7b8-9012-3456-7890abcdef01\",\n \"user_id\": \"b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4\",\n \"currency\": \"USD\",\n \"payment_type\": \"transfer\",\n \"metadata\": {\n \"order_id\": \"ORD-12345\"\n },\n \"payment_category\": 1,\n \"from_hold\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"wallet_id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n \"amount\": 100.5,\n \"idempotency_key\": \"pay_req_20260604_abc123\",\n \"destination_wallet_id\": \"c3d4e5f6-a7b8-9012-3456-7890abcdef01\",\n \"user_id\": \"b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4\",\n \"currency\": \"USD\",\n \"payment_type\": \"transfer\",\n \"metadata\": {\n \"order_id\": \"ORD-12345\"\n },\n \"payment_category\": 1,\n \"from_hold\": false\n}"
response = http.request(request)
puts response.read_body{
"status_code": 123,
"data": "<unknown>",
"query_generated_time": 123
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}{
"status_code": 429,
"data": {
"detail": "You just made a payment. Please wait before making another.",
"code": "payment_cooldown",
"error_code": 1000
},
"query_generated_time": 1750000000000
}Wallet to Wallet (Internal Transfer)
Move money from one wallet to another on your platform. A transfer
payment — no external rail or provider.
Address the destination one of two ways (send exactly one):
destination_wallet_id— a wallet UUID you already know. The server resolves the owning user from the wallet.destination_payee_id— a payee addressed by email. Funds route to the matching user’s wallet, or to a held inbound-only wallet (a ghost recipient is provisioned) until that person is added — seerecipient_statusin the response (existingvspending_claim).
curl --request POST \
--url https://api-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"wallet_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"amount": 100.5,
"idempotency_key": "pay_req_20260604_abc123",
"destination_wallet_id": "c3d4e5f6-a7b8-9012-3456-7890abcdef01",
"user_id": "b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4",
"currency": "USD",
"payment_type": "transfer",
"metadata": {
"order_id": "ORD-12345"
},
"payment_category": 1,
"from_hold": false
}
'import requests
url = "https://api-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet"
payload = {
"wallet_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"amount": 100.5,
"idempotency_key": "pay_req_20260604_abc123",
"destination_wallet_id": "c3d4e5f6-a7b8-9012-3456-7890abcdef01",
"user_id": "b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4",
"currency": "USD",
"payment_type": "transfer",
"metadata": { "order_id": "ORD-12345" },
"payment_category": 1,
"from_hold": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
wallet_id: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
amount: 100.5,
idempotency_key: 'pay_req_20260604_abc123',
destination_wallet_id: 'c3d4e5f6-a7b8-9012-3456-7890abcdef01',
user_id: 'b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4',
currency: 'USD',
payment_type: 'transfer',
metadata: {order_id: 'ORD-12345'},
payment_category: 1,
from_hold: false
})
};
fetch('https://api-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet', 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-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet",
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([
'wallet_id' => 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
'amount' => 100.5,
'idempotency_key' => 'pay_req_20260604_abc123',
'destination_wallet_id' => 'c3d4e5f6-a7b8-9012-3456-7890abcdef01',
'user_id' => 'b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4',
'currency' => 'USD',
'payment_type' => 'transfer',
'metadata' => [
'order_id' => 'ORD-12345'
],
'payment_category' => 1,
'from_hold' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet"
payload := strings.NewReader("{\n \"wallet_id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n \"amount\": 100.5,\n \"idempotency_key\": \"pay_req_20260604_abc123\",\n \"destination_wallet_id\": \"c3d4e5f6-a7b8-9012-3456-7890abcdef01\",\n \"user_id\": \"b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4\",\n \"currency\": \"USD\",\n \"payment_type\": \"transfer\",\n \"metadata\": {\n \"order_id\": \"ORD-12345\"\n },\n \"payment_category\": 1,\n \"from_hold\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
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-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"wallet_id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n \"amount\": 100.5,\n \"idempotency_key\": \"pay_req_20260604_abc123\",\n \"destination_wallet_id\": \"c3d4e5f6-a7b8-9012-3456-7890abcdef01\",\n \"user_id\": \"b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4\",\n \"currency\": \"USD\",\n \"payment_type\": \"transfer\",\n \"metadata\": {\n \"order_id\": \"ORD-12345\"\n },\n \"payment_category\": 1,\n \"from_hold\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-sandbox.finogates.com/v1/platform/payments/wallet-to-wallet")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"wallet_id\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n \"amount\": 100.5,\n \"idempotency_key\": \"pay_req_20260604_abc123\",\n \"destination_wallet_id\": \"c3d4e5f6-a7b8-9012-3456-7890abcdef01\",\n \"user_id\": \"b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4\",\n \"currency\": \"USD\",\n \"payment_type\": \"transfer\",\n \"metadata\": {\n \"order_id\": \"ORD-12345\"\n },\n \"payment_category\": 1,\n \"from_hold\": false\n}"
response = http.request(request)
puts response.read_body{
"status_code": 123,
"data": "<unknown>",
"query_generated_time": 123
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}{
"status_code": 429,
"data": {
"detail": "You just made a payment. Please wait before making another.",
"code": "payment_cooldown",
"error_code": 1000
},
"query_generated_time": 1750000000000
}Authorizations
The access token received from the authorization server in the OAuth 2.0 flow.
Body
Move funds to another wallet on your platform (intent_type=transfer).
A wallet-to-wallet transfer is user-to-user: it moves money from the
source wallet (wallet_id) to another user's wallet
(destination_wallet_id) on the same platform. Both wallets must
belong to your platform — cross-platform transfers are not allowed. The
master wallet may be on either side. No KYC/KYB is required to transfer
between wallets.
Source wallet UUID — the tenant's master wallet or one of the user's wallets. Server validates tenant ownership and currency and resolves the owner from it.
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"
Amount in major currency units (e.g. dollars).
100.5
Unique key to ensure idempotent payment creation.
1 - 120"pay_req_20260604_abc123"
Destination wallet UUID to credit — another user's wallet (or your master wallet) on the same platform. The server validates tenant ownership and currency and resolves the owner from it.
"c3d4e5f6-a7b8-9012-3456-7890abcdef01"
Optional safety cross-check — when sent, must match the owner of wallet_id.
"b3a9b622-cc63-4d3c-aad6-2d8e29e6f9d4"
ISO 4217 currency code.
3"USD"
Optional movement classification. transfer moves your own money (e.g. a bank deposit into your own wallet); send pays another party (e.g. a wallet → bank payout). When omitted the server derives it from the source and destination. When provided it is validated against them and rejected on mismatch.
transfer, send "transfer"
Arbitrary key-value metadata to attach to the payment.
{ "order_id": "ORD-12345" }
Optional. The payment category code to tag this payment with, recording what the payment was for. Omit it and the payment is created exactly as before, untagged. If you do send one it must be a code your platform can currently use, otherwise the request is rejected and no money moves. Fetch the codes from GET /v1/platform/catalog/payment-categories. Codes are issued separately in test and live, so read the list in each mode — the same number does not mean the same category across them.
x > 01
Draw this transfer from the source wallet's frozen (held) funds instead of its available balance. The held balance must cover the amount plus any payer-borne fee, or the request is rejected with insufficient_held_funds. Omit for a normal transfer from available balance.
false
Response
Successful Response
Standard response wrapper for single-object responses and errors.
Generic over the payload type. A route that declares
CommonResponse[SomeModel] gets the real data schema rendered in
OpenAPI/Swagger; a bare CommonResponse leaves data untyped.

