curl --request POST \
--url https://api.globalstack.io/v1/beneficiaries \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"label": "<string>",
"currency": "<string>",
"network": "bank",
"metadata": {},
"merchant_reference": "<string>",
"customer_id": "<string>",
"country_code": "<string>",
"provider_id": "prov_01JBQR7K3M9XZVTNA4H5C2PDES",
"rail": "payshap",
"account_number": "<string>",
"account_name": "<string>",
"address": "<string>"
}
'import requests
url = "https://api.globalstack.io/v1/beneficiaries"
payload = {
"name": "<string>",
"label": "<string>",
"currency": "<string>",
"network": "bank",
"metadata": {},
"merchant_reference": "<string>",
"customer_id": "<string>",
"country_code": "<string>",
"provider_id": "prov_01JBQR7K3M9XZVTNA4H5C2PDES",
"rail": "payshap",
"account_number": "<string>",
"account_name": "<string>",
"address": "<string>"
}
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({
name: '<string>',
label: '<string>',
currency: '<string>',
network: 'bank',
metadata: {},
merchant_reference: '<string>',
customer_id: '<string>',
country_code: '<string>',
provider_id: 'prov_01JBQR7K3M9XZVTNA4H5C2PDES',
rail: 'payshap',
account_number: '<string>',
account_name: '<string>',
address: '<string>'
})
};
fetch('https://api.globalstack.io/v1/beneficiaries', 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.globalstack.io/v1/beneficiaries",
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([
'name' => '<string>',
'label' => '<string>',
'currency' => '<string>',
'network' => 'bank',
'metadata' => [
],
'merchant_reference' => '<string>',
'customer_id' => '<string>',
'country_code' => '<string>',
'provider_id' => 'prov_01JBQR7K3M9XZVTNA4H5C2PDES',
'rail' => 'payshap',
'account_number' => '<string>',
'account_name' => '<string>',
'address' => '<string>'
]),
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.globalstack.io/v1/beneficiaries"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"label\": \"<string>\",\n \"currency\": \"<string>\",\n \"network\": \"bank\",\n \"metadata\": {},\n \"merchant_reference\": \"<string>\",\n \"customer_id\": \"<string>\",\n \"country_code\": \"<string>\",\n \"provider_id\": \"prov_01JBQR7K3M9XZVTNA4H5C2PDES\",\n \"rail\": \"payshap\",\n \"account_number\": \"<string>\",\n \"account_name\": \"<string>\",\n \"address\": \"<string>\"\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.globalstack.io/v1/beneficiaries")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"label\": \"<string>\",\n \"currency\": \"<string>\",\n \"network\": \"bank\",\n \"metadata\": {},\n \"merchant_reference\": \"<string>\",\n \"customer_id\": \"<string>\",\n \"country_code\": \"<string>\",\n \"provider_id\": \"prov_01JBQR7K3M9XZVTNA4H5C2PDES\",\n \"rail\": \"payshap\",\n \"account_number\": \"<string>\",\n \"account_name\": \"<string>\",\n \"address\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.globalstack.io/v1/beneficiaries")
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 \"name\": \"<string>\",\n \"label\": \"<string>\",\n \"currency\": \"<string>\",\n \"network\": \"bank\",\n \"metadata\": {},\n \"merchant_reference\": \"<string>\",\n \"customer_id\": \"<string>\",\n \"country_code\": \"<string>\",\n \"provider_id\": \"prov_01JBQR7K3M9XZVTNA4H5C2PDES\",\n \"rail\": \"payshap\",\n \"account_number\": \"<string>\",\n \"account_name\": \"<string>\",\n \"address\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"status": true,
"message": "Beneficiary created successfully",
"code": "ok",
"data": {
"id": "ben_01KPBAP7WTDKQKW5B3R31VPNX4",
"customer_id": "cust_01HXYZABC1234567890ABCDEFG",
"name": "Alice Bank Beneficiary",
"type": "fiat",
"currency": "NGN",
"details": {
"country_code": "NG",
"network": "bank",
"account_number": "0039415616",
"provider": {
"id": "prov_01KPBAP7WTDKQKW5B3R31VPNX4",
"name": "Access Bank",
"code": "000014"
},
"rail": "payshap",
"account_name": "ALICE JOHNSON"
},
"metadata": {},
"status": "pending",
"created_at": "2026-04-16T16:14:08.000Z",
"updated_at": "2026-04-16T16:14:08.000Z",
"label": "Alice's salary account",
"merchant_reference": "ref_01HXYZ4K5ABCDEFGHJKLMNPQRS"
},
"meta": {
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}Create a beneficiary
Create a beneficiary for fiat payouts (offramp) or crypto outbound transfers.
Pass type, currency, and corridor fields at the top level (country_code, network, account_number,provider_id, routing_number, address, etc.). On read, we nest account information under details and expand provider_id to provider.
Body — shared fields
type— required. One offiat,crypto.name— required. Max 255 chars.label— required. Max 128 chars.currency— required. ISO/crypto currency code (2–8 uppercase alphanumerics).metadata— optional. Free-formRecord<string, string>.merchant_reference— optional. Max 128 chars. Auto-generated asref_<ULID>when omitted. Per-integration unique.customer_id— optional. GlobalStack customer external id (cust_<ULID>). When omitted, the integration’s default customer is used; in that casedata.customer_idin the response will carry the default customer’s external id, which is intentionally not addressable viaGET /v1/customers/:customer_id.
Body — fiat fields (type = "fiat")
country_code— required. ISO-3166-1 alpha-2 (e.g.NG,KE).provider_id— required, except withrail = "payshap". GlobalStack provider external id (prov_<ULID>). A PayShap proxy resolves to whichever bank holds it, so no provider is chosen on that rail and any value sent is ignored — though it is still format-checked when present.network— required. One ofbank,mobile_money. This says WHAT the destination is; seerailfor HOW money reaches it.rail— optional. The payout rail, currently onlypayshap. Valid only whennetwork = "bank", and only forZARinZA. Omit for the corridor’s default rail, which is every beneficiary today.account_number— required. What it carries depends on the delivery: fornetwork = "mobile_money"the phone number; forrail = "payshap"a PayShap proxy — a South African mobile number in E.164 form (e.g.+27821234567), or a ShapName with its bank (e.g.acme@nedbank), which is how businesses usually register; send a ShapName exactly as the recipient gives it, including the part after@. Fornetwork = "bank"otherwise, the bank account number.account_name— required, except where GlobalStack resolves the account name from the provider:network = "bank"in currencies that resolve (currentlyNGN,GHS), andrail = "payshap", where the recipient’s bank returns the registered holder. In those casesaccount_nameis optional and, if supplied, is discarded in favour of the resolved value. For every other combination the suppliedaccount_nameis what we persist and pass to payout, so it is required.
Body — crypto fields (type = "crypto")
network— required. One ofsolana,base,ethereum.address— required. Max 128 chars.
Example — fiat (bank)
POST /v1/beneficiaries
{
"type": "fiat",
"name": "Alice Bank Beneficiary",
"label": "Alice's salary account",
"currency": "NGN",
"country_code": "NG",
"network": "bank",
"account_number": "0039415616",
"provider_id": "prov_01KPBAP7WTDKQKW5B3R31VPNX4"
}
Example — crypto (USDC on Solana)
POST /v1/beneficiaries
{
"type": "crypto",
"name": "Alice Wallet",
"label": "Personal cold wallet",
"currency": "USDC",
"network": "solana",
"address": "9wFFa…"
}
curl --request POST \
--url https://api.globalstack.io/v1/beneficiaries \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"label": "<string>",
"currency": "<string>",
"network": "bank",
"metadata": {},
"merchant_reference": "<string>",
"customer_id": "<string>",
"country_code": "<string>",
"provider_id": "prov_01JBQR7K3M9XZVTNA4H5C2PDES",
"rail": "payshap",
"account_number": "<string>",
"account_name": "<string>",
"address": "<string>"
}
'import requests
url = "https://api.globalstack.io/v1/beneficiaries"
payload = {
"name": "<string>",
"label": "<string>",
"currency": "<string>",
"network": "bank",
"metadata": {},
"merchant_reference": "<string>",
"customer_id": "<string>",
"country_code": "<string>",
"provider_id": "prov_01JBQR7K3M9XZVTNA4H5C2PDES",
"rail": "payshap",
"account_number": "<string>",
"account_name": "<string>",
"address": "<string>"
}
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({
name: '<string>',
label: '<string>',
currency: '<string>',
network: 'bank',
metadata: {},
merchant_reference: '<string>',
customer_id: '<string>',
country_code: '<string>',
provider_id: 'prov_01JBQR7K3M9XZVTNA4H5C2PDES',
rail: 'payshap',
account_number: '<string>',
account_name: '<string>',
address: '<string>'
})
};
fetch('https://api.globalstack.io/v1/beneficiaries', 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.globalstack.io/v1/beneficiaries",
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([
'name' => '<string>',
'label' => '<string>',
'currency' => '<string>',
'network' => 'bank',
'metadata' => [
],
'merchant_reference' => '<string>',
'customer_id' => '<string>',
'country_code' => '<string>',
'provider_id' => 'prov_01JBQR7K3M9XZVTNA4H5C2PDES',
'rail' => 'payshap',
'account_number' => '<string>',
'account_name' => '<string>',
'address' => '<string>'
]),
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.globalstack.io/v1/beneficiaries"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"label\": \"<string>\",\n \"currency\": \"<string>\",\n \"network\": \"bank\",\n \"metadata\": {},\n \"merchant_reference\": \"<string>\",\n \"customer_id\": \"<string>\",\n \"country_code\": \"<string>\",\n \"provider_id\": \"prov_01JBQR7K3M9XZVTNA4H5C2PDES\",\n \"rail\": \"payshap\",\n \"account_number\": \"<string>\",\n \"account_name\": \"<string>\",\n \"address\": \"<string>\"\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.globalstack.io/v1/beneficiaries")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"label\": \"<string>\",\n \"currency\": \"<string>\",\n \"network\": \"bank\",\n \"metadata\": {},\n \"merchant_reference\": \"<string>\",\n \"customer_id\": \"<string>\",\n \"country_code\": \"<string>\",\n \"provider_id\": \"prov_01JBQR7K3M9XZVTNA4H5C2PDES\",\n \"rail\": \"payshap\",\n \"account_number\": \"<string>\",\n \"account_name\": \"<string>\",\n \"address\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.globalstack.io/v1/beneficiaries")
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 \"name\": \"<string>\",\n \"label\": \"<string>\",\n \"currency\": \"<string>\",\n \"network\": \"bank\",\n \"metadata\": {},\n \"merchant_reference\": \"<string>\",\n \"customer_id\": \"<string>\",\n \"country_code\": \"<string>\",\n \"provider_id\": \"prov_01JBQR7K3M9XZVTNA4H5C2PDES\",\n \"rail\": \"payshap\",\n \"account_number\": \"<string>\",\n \"account_name\": \"<string>\",\n \"address\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"status": true,
"message": "Beneficiary created successfully",
"code": "ok",
"data": {
"id": "ben_01KPBAP7WTDKQKW5B3R31VPNX4",
"customer_id": "cust_01HXYZABC1234567890ABCDEFG",
"name": "Alice Bank Beneficiary",
"type": "fiat",
"currency": "NGN",
"details": {
"country_code": "NG",
"network": "bank",
"account_number": "0039415616",
"provider": {
"id": "prov_01KPBAP7WTDKQKW5B3R31VPNX4",
"name": "Access Bank",
"code": "000014"
},
"rail": "payshap",
"account_name": "ALICE JOHNSON"
},
"metadata": {},
"status": "pending",
"created_at": "2026-04-16T16:14:08.000Z",
"updated_at": "2026-04-16T16:14:08.000Z",
"label": "Alice's salary account",
"merchant_reference": "ref_01HXYZ4K5ABCDEFGHJKLMNPQRS"
},
"meta": {
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}Authorizations
API key issued during merchant onboarding.
Body
CreateBeneficiaryDto
fiat, crypto 1 - 2551 - 128^[A-Z0-9]{2,8}$What the destination is. For type: fiat one of: bank, mobile_money. For type: crypto a supported chain. account_name is required only for mobile_money: bank has its resolved by the provider. See rail for HOW the money reaches a bank account.
bank, mobile_money, solana, base, ethereum 1"bank"
128^cust_[0-9A-HJKMNP-TV-Z]{26}$^[A-Z]{2}$Required for type: fiat, except with rail: 'payshap': a PayShap proxy resolves to whichever bank holds it, so no provider is chosen and any value sent is ignored.
^prov_[0-9A-HJKMNP-TV-Z]{26}$"prov_01JBQR7K3M9XZVTNA4H5C2PDES"
How to move money into the account, rather than what the account is. Optional; omit for the corridor's default rail. Only valid when network is 'bank'. 'payshap' is ZAR and South Africa only, and its account_number is a PayShap proxy rather than a bank account number — a mobile number in E.164 form, or a ShapName with its bank such as 'acme@nedbank', sent exactly as the recipient gives it — so no provider is chosen for it.
payshap "payshap"
1 - 642551 - 128Response
Beneficiary created successfully