SWIFT Payments on Behalf of Customers
This guide outlines how to make SWIFT payments on behalf of your business customers using the Keyrails API. These are POBO (Pay On Behalf Of) payments, where your customer's name appears as the sender.
Overview
To initiate a POBO SWIFT payment for a customer, follow these steps:
- Create a Customer
- Create a Wallet
- Check wallet balance
- Create a SWIFT Transfer
- Monitor Transfer Status
Step 1: Create a Customer
Use the POST /v1/customers endpoint to register your business customer.
See API Reference curl --request POST \
--url https://api.sandbox.keyrails.com/api/v1/customers \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {{AccessToken}}' \
--data '{
"businessType": "Cooperative",
"email": "string",
"businessLegalName": "string",
"businessTradeName": "string",
"countryOfIncorporation": "string",
"companyRegistrationNumber": "string",
"incorporationDate": "YYYY-mm-dd",
"businessModel": "string",
"website": "string",
"registeredAddress": {
"street1": "string",
"city": "string",
"country": "GB"
},
"operationalAddress": {
"street1": "string",
"city": "string",
"country": "GB"
},
"contactPerson": {
"firstName": "string",
"lastName": "string",
"phoneNumber": "+447912345678",
"email": "string"
},
"businessIndustries": [
"1231"
],
"termsOfServiceAcceptance": {
"date": "2025-06-12T08:42:13.797Z",
"ipAddress": "string",
},
"isBusinessRegulated": false,
"accountPurpose": "Payroll",
"sourceOfFunds": "BusinessLoans",
"transactionBreakdown": {
"averageTransactionSize": 100000,
"maxTransactionSize": 200000,
"minTransactionSize": 300000,
"monthlyVolume": 400000,
"averageSizeToKeyrails": 500000,
"monthlyVolumeKeyrails": 600000
},
"businessDocuments": {
"certificateOfIncorporation": "data:image/png;base64,xxxxxxxxxxx",
"articlesOfAssociation": "data:image/png;base64,xxxxxxxxxxx",
"companyProofOfAddress": "data:image/[type];base64,xxxxxxxxxxx",
"processingStatements": "data:image/[type];base64,xxxxxxxxxxx",
"directorsRegister": "data:image/[type];base64,xxxxxxxxxxx",
"shareholdersRegister": "data:image/[type];base64,xxxxxxxxxxx"
},
"associatedPersons": [
{
"firstName": "string",
"middleName": "string",
"lastName": "string",
"email": "string",
"dateOfBirth": "YYYY-MM-DD",
"phone": "+447912345678",
"taxIdentificationNumber": "string",
"jobTitle": "string",
"shareHolderPercentage": 25,
"relationshipEstablishedAt": "YYYY-MM-DD",
"address": {
"street1": "string",
"city": "string",
"country": "string"
},
"identityInformation": [
{
"type": "driversLicense"
}
],
"documents": [
{
"documentType": "Passport",
"file": "data:image/[type];base64,xxxxxxxxxx"
}
]
}
]
}
'
Response:
A unique customerId
will be returned and used in subsequent steps.
{
"customerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
Customer Webhooks Examples
Before proceeding, ensure that your webhook configuration is set up. Refer to the setup guide for detailed instructions.
-
Webhook types:
Identity
-
resourceId
: References the customer IDApproved:{ "tenantId": "36a6deef-8d5a-4560-b17d-e73f1dd3cd88", "action": "Update", "id": "05dfa0a6-0e9a-4891-9b20-42b5b2c39dbd", "resourceId": "d0ffaf3b-a73b-461b-a82b-c2cff911cb13", "resourceType": "Identity", "createdAtUtc": "2025-07-29T13:58:56.8454302Z", "changes": { "complianceStatus": "Approved" } }
Rejected:{ "tenantId": "36a6deef-8d5a-4560-b17d-e73f1dd3cd88", "action": "Update", "id": "c7f89968-d91f-4b2f-80c6-9ea2e1d6ad8a", "resourceId": "d0ffaf3b-a73b-461b-a82b-c2cff911cb13", "resourceType": "Identity", "createdAtUtc": "2025-07-29T14:00:26.1457208Z", "changes": { "complianceStatus": "Rejected", "rejectionReasons": [] } }
Step 2: Create a wallet
Create a wallet to hold funds for the customer.
See API Referencecurl --request POST \
--url https://api.sandbox.keyrails.com/api/v1/wallets \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {{AccessToken}}' \
--data '{
"customerId": "f3675f2e-da61-42e9-a9db-eef8bd4fb4e2",
"network": "Ethereum"
}
'
Response:
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"createdAtUtc": "2025-07-29T13:37:07.125Z",
"updatedAtUtc": "2025-07-29T13:37:07.125Z",
"status": "Active",
"customerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"cryptoDepositInstructions": [
{
"network": "Ethereum",
"address": "string"
}
]
}
Step 3: Check wallet balance
See API Reference
curl --request GET \
--url https://api.sandbox.keyrails.com/api/v1/wallets/{walletId}/balance \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {{AccessToken}}'
Response:
{
"data": [
{
"currency": "USDC",
"network": "Ethereum",
"total": 0
},
{
"currency": "USDT",
"network": "Ethereum",
"total": 0
}
]
}
Internal Wallet TransfersYou can transfer funds between a customerโs wallet and a tenant wallet.
See Internal transfer API
Wallet Webhooks Example
Before proceeding, ensure that your webhook configuration is set up. Refer to the setup guide for detailed instructions.
-
Webhook types:
Transaction
-
resourceId
: References the transaction IdCrypto deposited:{ "tenantId": "2711ad4d-2c6b-4238-9f9d-2381d7a6d214", "action": "Update", "id": "d58d77b2-396e-44b1-a918-90ca655d498b", "resourceId": "58a8bedd-7bda-4471-936d-f9d32191524f", "resourceType": "Transaction", "createdAtUtc": "2025-07-29T14:15:25.7333739Z", "changes": { "transactionStatus": "Completed", "transactionType": "DepositCrypto", "createdAt": "2025-07-29T14:11:10.8520000Z", "paymentId": "278721c5-58fe-4822-93ee-8c0b5b06ef28", "amount": null, "cryptoAmount": "10", "updatedAt": "2025-07-29T14:15:25.4489853Z", "transactionHash": "0xf580ef78b69f2be786e539681d49a2948f5051486bdb5802361b51a16ba39cc7" } }
Step 4: Initiate SWIFT Transfer
Send funds from the wallet to an external bank account via SWIFT.
See API Referencecurl --request POST \
--url https://api.sandbox.keyrails.com/api/v1/transfers \
--header 'accept: application/json' \
--header 'content-type: application/*+json' \
--header 'Authorization: Bearer {{AccessToken}}' \
--data '{
"customerId": "string",
"source": {
"currency": "USDC",
"network": "Ethereum",
"walletId": "string"
},
"destination": {
"currency": "GBP",
"receiver": {
"name": "string",
"phone": "+447912345678",
"address": {
"street1": "string",
"street2": "string", // optional
"postalCode": "string", // optional
"city": "string",
"state": "string", // optional
"country": "string"
}
},
"bank": {
"name": "string",
"address": {
"street1": "string",
"street2": "string", // optional
"postalCode": "string", // optional
"city": "string",
"state": "string", // optional
"country": "string"
},
"accountNumber": "string", // optional - when iban is provided
"iban": "string", // optional - when accountNumber is provided
"bic": "string"
}
},
"purposeOfPayment": "PaymentForGoods",
"amount": 50000.0, // Amount in USD
"receiverAmount": 5000.0, // Amount in destination currency eg. GBP
"memo": "INV-001",
"documents": ["data:image/[type];base64,abdcxxxx", "data:image/[type];base64,abdcxxxx"]
}
'
Response:
The API responds with a transactionId
, which can be used to track the transfer.
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"transactionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "New",
...
}
Transfer QuoteUse the transfer quote endpoint to see the transfer quote before creating a transfer.
See Transfer Quote API
Transfer Webhooks Examples
Before proceeding, ensure that your webhook configuration is set up. Refer to the setup guide for detailed instructions.
- Webhook types:
Transaction
resourceId
: References the transaction ID
Processing:
{
"tenantId": "2711ad4d-2c6b-4238-9f9d-2381d7a6d214",
"action": "Create",
"id": "e95503c4-f8bb-4f6b-89d3-42f10307a6bc",
"resourceId": "b5787a92-82ba-4f09-bacc-02f57ea601ed",
"resourceType": "Transaction",
"createdAtUtc": "2025-07-29T13:47:04.7710866Z",
"changes": {
"transactionStatus": "Processing",
"transactionType": "SettlementGlobalConnectUsdt",
"createdAt": "2025-07-29T13:47:04.3988318Z",
"paymentId": "600d1b07-f2e8-4e63-8f4e-2a01aa558b03",
"amount": null,
"cryptoAmount": "2"
}
}
Completed:
{
"tenantId": "36a6deef-8d5a-4560-b17d-e73f1dd3cd88",
"action": "Update",
"id": "4c01fdd9-923d-4ad9-9508-48a39cc85a3b",
"resourceId": "6470d2bd-89e3-4e10-a3ff-605d820f8da3",
"resourceType": "Transaction",
"createdAtUtc": "2025-07-29T14:06:04.1804263Z",
"changes": {
"transactionStatus": "Completed",
"transactionType": "SettlementGlobalConnectUsdc",
"createdAt": "2025-07-29T14:04:34.6845500Z",
"paymentId": "33420144-84c8-49ed-90aa-f0ca6a543c0a",
"amount": null,
"cryptoAmount": "2",
"updatedAt": "2025-07-29T14:06:04.1766465Z"
}
}
Failed:
{
"tenantId": "36a6deef-8d5a-4560-b17d-e73f1dd3cd88",
"action": "Update",
"id": "44110cf3-05c4-4652-b718-fc0d6475453f",
"resourceId": "6470d2bd-89e3-4e10-a3ff-605d820f8da3",
"resourceType": "Transaction",
"createdAtUtc": "2025-07-29T14:07:01.6713778Z",
"changes": {
"transactionStatus": "Failed",
"transactionType": "SettlementGlobalConnectUsdc",
"createdAt": "2025-07-29T14:04:34.6845500Z",
"paymentId": "33420144-84c8-49ed-90aa-f0ca6a543c0a",
"amount": null,
"cryptoAmount": "2",
"updatedAt": "2025-07-29T14:07:01.6684993Z"
}
}
Monitor Transfer Status
See API reference.
curl --request GET \
--url https://api.sandbox.keyrails.com/api/v1/transactions/{transactionId} \
--header 'accept: application/json' \
--header 'content-type: application/*+json' \
--header 'Authorization: Bearer {{AccessToken}}' \
Response:
The API responds with a transactionId
, which can be used to track the transfer.
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"transactionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "New",
"trackingStatus": "string",
"trackingReference": "string",
"currency": "USD",
"sourceCurrency": "USD",
"destinationCurrency": "USD",
"network": "Mainnet",
"amount": 0,
"cryptoAmount": 0,
"transactionFee": 0,
"appliedFee": 0,
"totalAmount": 0,
"comment": "string",
"memo": "string",
"purposeOfPayment": "string",
"country": "string",
...
}
Updated 18 days ago