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:

  1. Create a Customer
  2. Create a Wallet
  3. Check wallet balance
  4. Create a SWIFT Transfer
  5. 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 ID

    Approved:

    {
      "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 Reference
curl --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 Transfers

You 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 Id

    Crypto 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 Reference
curl --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 Quote

Use 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",
   ...
}