curl --request POST \
--url https://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"provider": "provider_code",
"providerIdentifierToken": "rail_provider_token_opaque_123",
"rail": "upi",
"identifierType": "vpa",
"displayLabel": "Business account",
"maskedIdentifier": "mi***@bank",
"country": "IN",
"currency": "INR"
}
'import requests
url = "https://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers"
payload = {
"provider": "provider_code",
"providerIdentifierToken": "rail_provider_token_opaque_123",
"rail": "upi",
"identifierType": "vpa",
"displayLabel": "Business account",
"maskedIdentifier": "mi***@bank",
"country": "IN",
"currency": "INR"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Basic <encoded-value>",
"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: 'Basic <encoded-value>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
provider: 'provider_code',
providerIdentifierToken: 'rail_provider_token_opaque_123',
rail: 'upi',
identifierType: 'vpa',
displayLabel: 'Business account',
maskedIdentifier: 'mi***@bank',
country: 'IN',
currency: 'INR'
})
};
fetch('https://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers', 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://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers",
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([
'provider' => 'provider_code',
'providerIdentifierToken' => 'rail_provider_token_opaque_123',
'rail' => 'upi',
'identifierType' => 'vpa',
'displayLabel' => 'Business account',
'maskedIdentifier' => 'mi***@bank',
'country' => 'IN',
'currency' => 'INR'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"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://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers"
payload := strings.NewReader("{\n \"provider\": \"provider_code\",\n \"providerIdentifierToken\": \"rail_provider_token_opaque_123\",\n \"rail\": \"upi\",\n \"identifierType\": \"vpa\",\n \"displayLabel\": \"Business account\",\n \"maskedIdentifier\": \"mi***@bank\",\n \"country\": \"IN\",\n \"currency\": \"INR\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Basic <encoded-value>")
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://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Basic <encoded-value>")
.header("Content-Type", "application/json")
.body("{\n \"provider\": \"provider_code\",\n \"providerIdentifierToken\": \"rail_provider_token_opaque_123\",\n \"rail\": \"upi\",\n \"identifierType\": \"vpa\",\n \"displayLabel\": \"Business account\",\n \"maskedIdentifier\": \"mi***@bank\",\n \"country\": \"IN\",\n \"currency\": \"INR\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers")
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"] = 'Basic <encoded-value>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"provider\": \"provider_code\",\n \"providerIdentifierToken\": \"rail_provider_token_opaque_123\",\n \"rail\": \"upi\",\n \"identifierType\": \"vpa\",\n \"displayLabel\": \"Business account\",\n \"maskedIdentifier\": \"mi***@bank\",\n \"country\": \"IN\",\n \"currency\": \"INR\"\n}"
response = http.request(request)
puts response.read_body{
"paymentRailIdentifier": {
"id": "rail_identifier_123",
"accountId": "acct_123",
"provider": "provider_code",
"rail": "upi",
"identifierType": "vpa",
"displayLabel": "Business account",
"maskedIdentifier": "mi***@bank",
"country": "IN",
"currency": "INR",
"status": "pending_verification",
"verification": {
"version": 0,
"verifiedAt": null
},
"disabledAt": null,
"createdAt": "2026-08-28T10:00:00.000Z",
"updatedAt": "2026-08-28T10:00:00.000Z"
},
"settlementDestination": {
"id": "destination_123",
"accountId": "acct_123",
"type": "payment_rail_identifier",
"status": "pending_verification",
"preferred": false,
"capabilities": {
"directions": [
"receive"
],
"settlementSupported": false,
"unavailableReason": "bank_settlement_provider_not_configured",
"country": "IN",
"currencies": [
"INR"
],
"rail": "upi"
},
"resource": {
"type": "payment_rail_identifier",
"paymentRailIdentifier": {
"id": "rail_identifier_123",
"accountId": "acct_123",
"provider": "provider_code",
"rail": "upi",
"identifierType": "vpa",
"displayLabel": "Business account",
"maskedIdentifier": "mi***@bank",
"country": "IN",
"currency": "INR",
"status": "pending_verification",
"verification": {
"version": 0,
"verifiedAt": null
},
"disabledAt": null,
"createdAt": "2026-08-28T10:00:00.000Z",
"updatedAt": "2026-08-28T10:00:00.000Z"
}
},
"disabledAt": null,
"createdAt": "2026-08-28T10:00:00.000Z",
"updatedAt": "2026-08-28T10:00:00.000Z"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}Link a tokenized rail identifier
Link a provider-tokenized static payment rail alias to a UPA.
curl --request POST \
--url https://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"provider": "provider_code",
"providerIdentifierToken": "rail_provider_token_opaque_123",
"rail": "upi",
"identifierType": "vpa",
"displayLabel": "Business account",
"maskedIdentifier": "mi***@bank",
"country": "IN",
"currency": "INR"
}
'import requests
url = "https://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers"
payload = {
"provider": "provider_code",
"providerIdentifierToken": "rail_provider_token_opaque_123",
"rail": "upi",
"identifierType": "vpa",
"displayLabel": "Business account",
"maskedIdentifier": "mi***@bank",
"country": "IN",
"currency": "INR"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Basic <encoded-value>",
"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: 'Basic <encoded-value>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
provider: 'provider_code',
providerIdentifierToken: 'rail_provider_token_opaque_123',
rail: 'upi',
identifierType: 'vpa',
displayLabel: 'Business account',
maskedIdentifier: 'mi***@bank',
country: 'IN',
currency: 'INR'
})
};
fetch('https://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers', 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://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers",
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([
'provider' => 'provider_code',
'providerIdentifierToken' => 'rail_provider_token_opaque_123',
'rail' => 'upi',
'identifierType' => 'vpa',
'displayLabel' => 'Business account',
'maskedIdentifier' => 'mi***@bank',
'country' => 'IN',
'currency' => 'INR'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"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://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers"
payload := strings.NewReader("{\n \"provider\": \"provider_code\",\n \"providerIdentifierToken\": \"rail_provider_token_opaque_123\",\n \"rail\": \"upi\",\n \"identifierType\": \"vpa\",\n \"displayLabel\": \"Business account\",\n \"maskedIdentifier\": \"mi***@bank\",\n \"country\": \"IN\",\n \"currency\": \"INR\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Basic <encoded-value>")
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://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Basic <encoded-value>")
.header("Content-Type", "application/json")
.body("{\n \"provider\": \"provider_code\",\n \"providerIdentifierToken\": \"rail_provider_token_opaque_123\",\n \"rail\": \"upi\",\n \"identifierType\": \"vpa\",\n \"displayLabel\": \"Business account\",\n \"maskedIdentifier\": \"mi***@bank\",\n \"country\": \"IN\",\n \"currency\": \"INR\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://prod-api.stableyard.fi/v2/accounts/{accountId}/payment-rail-identifiers")
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"] = 'Basic <encoded-value>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"provider\": \"provider_code\",\n \"providerIdentifierToken\": \"rail_provider_token_opaque_123\",\n \"rail\": \"upi\",\n \"identifierType\": \"vpa\",\n \"displayLabel\": \"Business account\",\n \"maskedIdentifier\": \"mi***@bank\",\n \"country\": \"IN\",\n \"currency\": \"INR\"\n}"
response = http.request(request)
puts response.read_body{
"paymentRailIdentifier": {
"id": "rail_identifier_123",
"accountId": "acct_123",
"provider": "provider_code",
"rail": "upi",
"identifierType": "vpa",
"displayLabel": "Business account",
"maskedIdentifier": "mi***@bank",
"country": "IN",
"currency": "INR",
"status": "pending_verification",
"verification": {
"version": 0,
"verifiedAt": null
},
"disabledAt": null,
"createdAt": "2026-08-28T10:00:00.000Z",
"updatedAt": "2026-08-28T10:00:00.000Z"
},
"settlementDestination": {
"id": "destination_123",
"accountId": "acct_123",
"type": "payment_rail_identifier",
"status": "pending_verification",
"preferred": false,
"capabilities": {
"directions": [
"receive"
],
"settlementSupported": false,
"unavailableReason": "bank_settlement_provider_not_configured",
"country": "IN",
"currencies": [
"INR"
],
"rail": "upi"
},
"resource": {
"type": "payment_rail_identifier",
"paymentRailIdentifier": {
"id": "rail_identifier_123",
"accountId": "acct_123",
"provider": "provider_code",
"rail": "upi",
"identifierType": "vpa",
"displayLabel": "Business account",
"maskedIdentifier": "mi***@bank",
"country": "IN",
"currency": "INR",
"status": "pending_verification",
"verification": {
"version": 0,
"verifiedAt": null
},
"disabledAt": null,
"createdAt": "2026-08-28T10:00:00.000Z",
"updatedAt": "2026-08-28T10:00:00.000Z"
}
},
"disabledAt": null,
"createdAt": "2026-08-28T10:00:00.000Z",
"updatedAt": "2026-08-28T10:00:00.000Z"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}providerIdentifierToken with its rail, identifierType, country, currency and the display fields displayLabel and maskedIdentifier. Raw rail aliases, raw bank identifiers and raw QR payloads are rejected by design.
The identifier stays a pending destination until provider verification and payout execution are available. Idempotency-Key is required and must contain 1–256 characters after trimming surrounding whitespace. Retry the identical request with the same key; changed input returns a conflict.Authorizations
HTTP Basic auth. Username is the Stableyard app ID. Password is the app secret. The optional Stableyard-Version request header must match the environment pin.
Headers
Required retry key for linking a bank account or rail identifier: 1-256 characters after trimming surrounding whitespace. Retry the identical request with the same key; changed input returns a conflict.
1 - 256"bank-beneficiary-supplier-123"
Optional contract-version assertion. Omit it to use the app environment's pinned version. A different supported version is accepted only after that environment is explicitly migrated.
2026-09-09 Path Parameters
Canonical account id returned by the Accounts API.
"acct_123"
Body
^[a-z0-9][a-z0-9_-]{1,63}$"provider_code"
Opaque provider token. Raw rail aliases and raw QR payloads are rejected by design.
8 - 512"rail_provider_token_opaque_123"
1 - 64"upi"
1 - 64"vpa"
1 - 160"Business account"
1 - 160"mi***@bank"
^[A-Za-z]{2}$"IN"
^[A-Za-z]{3}$"INR"