curl --request POST \
--url https://api-sandbox.finogates.com/v1/platform/payments/request-payload \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"source_type": "wallet",
"destination_type": "bank",
"amount": 250,
"idempotency_key": "quote-2026-09-11-0001",
"currency": "USD",
"delivery_speed": "standard",
"destination_country": "MX",
"destination_currency": "MXN",
"bank_account_id": "33333333-3333-3333-3333-333333333333",
"payee_destination_id": "22222222-2222-2222-2222-222222222222"
}
'import requests
url = "https://api-sandbox.finogates.com/v1/platform/payments/request-payload"
payload = {
"source_type": "wallet",
"destination_type": "bank",
"amount": 250,
"idempotency_key": "quote-2026-09-11-0001",
"currency": "USD",
"delivery_speed": "standard",
"destination_country": "MX",
"destination_currency": "MXN",
"bank_account_id": "33333333-3333-3333-3333-333333333333",
"payee_destination_id": "22222222-2222-2222-2222-222222222222"
}
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({
source_type: 'wallet',
destination_type: 'bank',
amount: 250,
idempotency_key: 'quote-2026-09-11-0001',
currency: 'USD',
delivery_speed: 'standard',
destination_country: 'MX',
destination_currency: 'MXN',
bank_account_id: '33333333-3333-3333-3333-333333333333',
payee_destination_id: '22222222-2222-2222-2222-222222222222'
})
};
fetch('https://api-sandbox.finogates.com/v1/platform/payments/request-payload', 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/request-payload",
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([
'source_type' => 'wallet',
'destination_type' => 'bank',
'amount' => 250,
'idempotency_key' => 'quote-2026-09-11-0001',
'currency' => 'USD',
'delivery_speed' => 'standard',
'destination_country' => 'MX',
'destination_currency' => 'MXN',
'bank_account_id' => '33333333-3333-3333-3333-333333333333',
'payee_destination_id' => '22222222-2222-2222-2222-222222222222'
]),
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/request-payload"
payload := strings.NewReader("{\n \"source_type\": \"wallet\",\n \"destination_type\": \"bank\",\n \"amount\": 250,\n \"idempotency_key\": \"quote-2026-09-11-0001\",\n \"currency\": \"USD\",\n \"delivery_speed\": \"standard\",\n \"destination_country\": \"MX\",\n \"destination_currency\": \"MXN\",\n \"bank_account_id\": \"33333333-3333-3333-3333-333333333333\",\n \"payee_destination_id\": \"22222222-2222-2222-2222-222222222222\"\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/request-payload")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"source_type\": \"wallet\",\n \"destination_type\": \"bank\",\n \"amount\": 250,\n \"idempotency_key\": \"quote-2026-09-11-0001\",\n \"currency\": \"USD\",\n \"delivery_speed\": \"standard\",\n \"destination_country\": \"MX\",\n \"destination_currency\": \"MXN\",\n \"bank_account_id\": \"33333333-3333-3333-3333-333333333333\",\n \"payee_destination_id\": \"22222222-2222-2222-2222-222222222222\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-sandbox.finogates.com/v1/platform/payments/request-payload")
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 \"source_type\": \"wallet\",\n \"destination_type\": \"bank\",\n \"amount\": 250,\n \"idempotency_key\": \"quote-2026-09-11-0001\",\n \"currency\": \"USD\",\n \"delivery_speed\": \"standard\",\n \"destination_country\": \"MX\",\n \"destination_currency\": \"MXN\",\n \"bank_account_id\": \"33333333-3333-3333-3333-333333333333\",\n \"payee_destination_id\": \"22222222-2222-2222-2222-222222222222\"\n}"
response = http.request(request)
puts response.read_body{
"status_code": 201,
"data": {
"reference": "3f9c1b2a-9d84-4e15-8c26-0b7a5d3e1f90",
"status": "open",
"expires_at": "2026-09-11T10:30:00Z",
"source_type": "wallet",
"destination_type": "bank",
"payment_type": "send",
"amount": 250,
"currency": "USD",
"fee": 3,
"destinations_supported": false,
"fields": {
"reference": {
"required": true,
"requirements": []
},
"idempotency_key": {
"required": true,
"requirements": []
},
"wallet_id": {
"required": true,
"requirements": []
},
"payee_destination_id": {
"required": true,
"requirements": [
{
"field": "bank_account_number",
"label": "Bank account number"
},
{
"field": "last_name",
"label": "Last name"
}
]
},
"user_id": {
"required": false,
"requirements": []
},
"payment_category": {
"required": false,
"requirements": []
},
"metadata": {
"required": false,
"requirements": []
},
"from_hold": {
"required": false,
"requirements": []
},
"notify_recipient": {
"required": false,
"requirements": []
}
}
},
"query_generated_time": 1712847600000
}Request a Payment Payload
Tell us what you want to move — where from, where to, and how much — and we
answer with everything the payment needs: the fields to send on
create-transaction, what the objects behind those fields must carry, our
fee, and a reference that pins the amount.
source_type:wallet,bank(the user’s linked bank account),card(the user’s saved card) orvba(the user’s virtual bank account).destination_type:wallet,bank(a bank in the US: the user’s own linked bank or a payee’s bank destination — the id you send oncreate-transactionsays which),bank_international(a payee’s bank abroad — senddestination_countryanddestination_currencytoo) ormerchant(a card-acquiring account).amountis what the payment will move.create-transactiontakes no amount of its own; it comes off the reference.
fields is the whole body create-transaction takes, keyed by field name,
mandatory fields first. Each entry says whether it is required and lists
its requirements — the details the object behind that id must already have
for this payment to go through (for example a payee’s last name, or an
address in the destination country), as {field, label} items. required
is about that one field. Some fields are alternatives to each other: each of
those is required: false and names its one_of group, and the top-level
one_of map states the rule — send exactly one field of each group. A
bank payout has one such group: bank_account_id (the user’s own bank — a
transfer) or payee_destination_id (a payee — a send). A field marked
companion_of goes only with that alternative: payee_address_id rides with
payee_destination_id, and is required when the route chosen for the
payment asks for the payee’s address (some routes for a bank payout do, as
every payout abroad does). Where
destinations_supported is true, destinations is listed too: the optional
alternative to the single destination field, for splitting the amount across
wallets. Create or update the objects first, then call create-transaction
with the reference.
fee is our fee for this payment. It is not taken out of the amount —
it is billed to your platform on the monthly invoice. For wallet → wallet it
is null here and settled at create-transaction, because it depends on
whether the two wallets belong to the same user (payment_type).
Name the objects when you know them. bank_account_id (the user’s
linked bank on a deposit from bank or a withdrawal to bank) and
payee_destination_id (the destination of a bank or bank_international
payout) are optional here, and worth sending: the payload is then worked out
for that exact bank or destination, so a route that cannot serve it is never
offered and create-transaction will not send you back for a new payload.
Always send payee_destination_id for an email destination. An id sent for
a movement that does not take it is refused (field_not_allowed), as are
both ids of a bank payout together; one that is not yours is 404; and
when no route can serve the objects at all the answer is
payload_incomplete with missing — the same answer create-transaction
gives, one call earlier. Without them the payload is worked out from the
types alone, exactly as before — a bank payout then reports
payment_type: null, settled by the id create-transaction receives.
The reference is single-use and valid until expires_at (30 minutes).
Sending the same idempotency_key again returns the same reference, even
once it has expired — a fresh quote needs a fresh key.
curl --request POST \
--url https://api-sandbox.finogates.com/v1/platform/payments/request-payload \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"source_type": "wallet",
"destination_type": "bank",
"amount": 250,
"idempotency_key": "quote-2026-09-11-0001",
"currency": "USD",
"delivery_speed": "standard",
"destination_country": "MX",
"destination_currency": "MXN",
"bank_account_id": "33333333-3333-3333-3333-333333333333",
"payee_destination_id": "22222222-2222-2222-2222-222222222222"
}
'import requests
url = "https://api-sandbox.finogates.com/v1/platform/payments/request-payload"
payload = {
"source_type": "wallet",
"destination_type": "bank",
"amount": 250,
"idempotency_key": "quote-2026-09-11-0001",
"currency": "USD",
"delivery_speed": "standard",
"destination_country": "MX",
"destination_currency": "MXN",
"bank_account_id": "33333333-3333-3333-3333-333333333333",
"payee_destination_id": "22222222-2222-2222-2222-222222222222"
}
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({
source_type: 'wallet',
destination_type: 'bank',
amount: 250,
idempotency_key: 'quote-2026-09-11-0001',
currency: 'USD',
delivery_speed: 'standard',
destination_country: 'MX',
destination_currency: 'MXN',
bank_account_id: '33333333-3333-3333-3333-333333333333',
payee_destination_id: '22222222-2222-2222-2222-222222222222'
})
};
fetch('https://api-sandbox.finogates.com/v1/platform/payments/request-payload', 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/request-payload",
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([
'source_type' => 'wallet',
'destination_type' => 'bank',
'amount' => 250,
'idempotency_key' => 'quote-2026-09-11-0001',
'currency' => 'USD',
'delivery_speed' => 'standard',
'destination_country' => 'MX',
'destination_currency' => 'MXN',
'bank_account_id' => '33333333-3333-3333-3333-333333333333',
'payee_destination_id' => '22222222-2222-2222-2222-222222222222'
]),
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/request-payload"
payload := strings.NewReader("{\n \"source_type\": \"wallet\",\n \"destination_type\": \"bank\",\n \"amount\": 250,\n \"idempotency_key\": \"quote-2026-09-11-0001\",\n \"currency\": \"USD\",\n \"delivery_speed\": \"standard\",\n \"destination_country\": \"MX\",\n \"destination_currency\": \"MXN\",\n \"bank_account_id\": \"33333333-3333-3333-3333-333333333333\",\n \"payee_destination_id\": \"22222222-2222-2222-2222-222222222222\"\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/request-payload")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"source_type\": \"wallet\",\n \"destination_type\": \"bank\",\n \"amount\": 250,\n \"idempotency_key\": \"quote-2026-09-11-0001\",\n \"currency\": \"USD\",\n \"delivery_speed\": \"standard\",\n \"destination_country\": \"MX\",\n \"destination_currency\": \"MXN\",\n \"bank_account_id\": \"33333333-3333-3333-3333-333333333333\",\n \"payee_destination_id\": \"22222222-2222-2222-2222-222222222222\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-sandbox.finogates.com/v1/platform/payments/request-payload")
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 \"source_type\": \"wallet\",\n \"destination_type\": \"bank\",\n \"amount\": 250,\n \"idempotency_key\": \"quote-2026-09-11-0001\",\n \"currency\": \"USD\",\n \"delivery_speed\": \"standard\",\n \"destination_country\": \"MX\",\n \"destination_currency\": \"MXN\",\n \"bank_account_id\": \"33333333-3333-3333-3333-333333333333\",\n \"payee_destination_id\": \"22222222-2222-2222-2222-222222222222\"\n}"
response = http.request(request)
puts response.read_body{
"status_code": 201,
"data": {
"reference": "3f9c1b2a-9d84-4e15-8c26-0b7a5d3e1f90",
"status": "open",
"expires_at": "2026-09-11T10:30:00Z",
"source_type": "wallet",
"destination_type": "bank",
"payment_type": "send",
"amount": 250,
"currency": "USD",
"fee": 3,
"destinations_supported": false,
"fields": {
"reference": {
"required": true,
"requirements": []
},
"idempotency_key": {
"required": true,
"requirements": []
},
"wallet_id": {
"required": true,
"requirements": []
},
"payee_destination_id": {
"required": true,
"requirements": [
{
"field": "bank_account_number",
"label": "Bank account number"
},
{
"field": "last_name",
"label": "Last name"
}
]
},
"user_id": {
"required": false,
"requirements": []
},
"payment_category": {
"required": false,
"requirements": []
},
"metadata": {
"required": false,
"requirements": []
},
"from_hold": {
"required": false,
"requirements": []
},
"notify_recipient": {
"required": false,
"requirements": []
}
}
},
"query_generated_time": 1712847600000
}Authorizations
The access token received from the authorization server in the OAuth 2.0 flow.
Body
Request body for POST /v1/platform/payments/request-payload.
Where the money comes from: wallet, bank (the user's linked bank account), card (the user's saved card) or vba (the user's virtual bank account).
40"wallet"
Where the money goes: wallet, bank (a bank in the US — the user's own linked bank, named by bank_account_id, or a payee's bank destination, named by payee_destination_id), bank_international (a payee's bank abroad) or merchant (a card-acquiring account).
40"bank"
The amount to move, in major units, at most 2 decimal places. This is the amount the payment will move — create-transaction takes no amount of its own.
x > 0250
A unique value you pick for this request. Sending the same key again returns the same reference — even after it has expired — so a fresh quote needs a fresh key.
1 - 120"quote-2026-09-11-0001"
ISO-4217 code of the amount. Defaults to USD.
3"USD"
How fast the money should land. standard is the default for every movement; same_day (same-day ACH) and instant (real-time payment, bank destinations only) are offered where the movement supports them and are priced and timed on their own terms. A speed the movement cannot deliver is refused with speed_not_offered; a payment is never silently downgraded.
standard, same_day, instant "standard"
ISO-3166 alpha-2 country the money lands in. Required when destination_type is bank_international; ignored otherwise.
2"MX"
ISO-4217 code the recipient is paid in. Required when destination_type is bank_international; ignored otherwise.
3"MXN"
Optional. The user's linked bank account this payment will use — the source of a deposit from bank, or the destination of a withdrawal to bank (the user's own bank; a transfer). When given, the payload is worked out for that bank: a route that cannot serve it is not offered, and create-transaction will not send you back for a new payload. Refused (field_not_allowed) for a movement that takes no bank account, or alongside payee_destination_id.
"33333333-3333-3333-3333-333333333333"
Optional. The payee destination a bank or bank_international payout will pay (a send). When given, the payload is worked out for that destination — send it whenever you know it, and always for an email destination. Refused (field_not_allowed) for a movement that takes no payee destination, or alongside bank_account_id.
"22222222-2222-2222-2222-222222222222"
Response
Payload described
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.

