Cross-Border Remittance (Stablecoins)
Onboard a sender, fund in USD, convert to a stablecoin for transfer, and deliver to a recipient, either a recipient-controlled wallet or a recipient who is themselves a RAMFi client. For fiat delivery with no recipient wallet, see Cross-Border Remittance (Fiat).
Your app sends the customer's details; RAMFi runs KYC, opens the account, and returns a client record with Active status when verification passes.
| Field | Type | Required | Description | Value |
|---|---|---|---|---|
| firstName | string | REQUIRED | Client's legal first name. | |
| lastName | string | REQUIRED | Client's legal last name. | |
| address | string | REQUIRED | Street address. | |
| city | string | REQUIRED | City. | |
| state | string | REQUIRED | State code. | |
| zip | string | REQUIRED | ZIP code. | |
| taxID | string | REQUIRED | SSN (or EIN for business accounts). | |
| dob | string (date) | REQUIRED | Date of birth (YYYY-MM-DD). | |
| clientID | string | REQUIRED | Your external identifier for this client. | |
| string | REQUIRED | Email address (validated). |
curl --request POST \
--url 'https://FQDN/api/FE/NewClient' \
--header 'Authorization: Bearer <SHORT_TERM_TOKEN>' \
--header 'X-OTP: <X_OTP>' \
--header 'Content-Type: application/json' \
--data '{
"firstName": "string",
"lastName": "string",
"taxID": "string",
"clientID": "sender-id",
"email": "user@example.com"
}'const options = {
method: 'POST',
headers: {
'Authorization': 'Bearer <SHORT_TERM_TOKEN>',
'X-OTP': '<X_OTP>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"firstName": "string",
"lastName": "string",
"taxID": "string",
"clientID": "sender-id",
"email": "user@example.com"
})
};
fetch('https://FQDN/api/FE/NewClient', options)
.then(r => r.json())
.then(console.log)
.catch(console.error);import requests
url = "https://FQDN/api/FE/NewClient"
headers = {
"Authorization": "Bearer <SHORT_TERM_TOKEN>",
"X-OTP": "<X_OTP>",
"Content-Type": "application/json"
}
payload = {
"firstName": "string",
"lastName": "string",
"taxID": "string",
"clientID": "sender-id",
"email": "user@example.com"
}
resp = requests.post(url, headers=headers, json=payload)
print(resp.json()){
"id": "string",
"clientID": "sender-id",
"accountStatus": "Active",
"email": "user@example.com"
}Active means the client is verified and can transact.Register and AML-screen the recipient's address before sending.
| Field | Type | Required | Description | Value |
|---|---|---|---|---|
| address | string | optional | The wallet address. | |
| addressIdentifier | string | optional | A friendly name for the address. |
curl --request POST \
--url 'https://FQDN/api/FE/AddWalletAddress?address=recipient-wallet&addressIdentifier=Recipient' \
--header 'Authorization: Bearer <SHORT_TERM_TOKEN>' \
--header 'X-OTP: <X_OTP>'const options = {
method: 'POST',
headers: {
'Authorization': 'Bearer <SHORT_TERM_TOKEN>',
'X-OTP': '<X_OTP>'
}
};
fetch('https://FQDN/api/FE/AddWalletAddress?address=recipient-wallet&addressIdentifier=Recipient', options)
.then(r => r.json())
.then(console.log)
.catch(console.error);import requests
url = "https://FQDN/api/FE/AddWalletAddress?address=recipient-wallet&addressIdentifier=Recipient"
headers = {
"Authorization": "Bearer <SHORT_TERM_TOKEN>",
"X-OTP": "<X_OTP>"
}
resp = requests.post(url, headers=headers)
print(resp.json()){
"isSuccess": true,
"result": "approved",
"errorMessage": null
}- 1Sender AppFund in USDACH or card (see funding methods)
- RAMFiCredit USD balanceRAMFi clears funds
- 2Sender AppRequest conversionPOST /ConvertClientFunds
- RAMFiExecute conversionRAMFi converts to USDC
- 3Sender AppRequest deliveryPOST /SendFundsToAddress
- RAMFiBroadcast transferRAMFi sends on-chain
- RecipientRecipient receiveswallet, or RAMFi off-ramp to USD
Show full interaction diagram
Remittance sequence to a recipient wallet. When the recipient is a RAMFi client, the send is replaced by an internal transfer (see Delivery patterns).
AddClientFunds), see Funding methods.Bring the remittance amount in by ACH (open banking, shown) or a card pull (PullFromCard). RAMFi credits the sender's USD balance.
| Field | Type | Required | Description | Value |
|---|---|---|---|---|
| clientID | string | REQUIRED | The client to fund. | |
| amount | number | REQUIRED | USD amount to draft via ACH. | |
| transactionDate | string (date) | optional | Date to initiate the ACH draft (YYYY-MM-DD). | |
| externalReference | string | REQUIRED | Your unique reconciliation key. |
curl --request POST \
--url 'https://FQDN/api/FE/AddClientFunds' \
--header 'Authorization: Bearer <SHORT_TERM_TOKEN>' \
--header 'X-OTP: <X_OTP>' \
--header 'Content-Type: application/json' \
--data '{
"clientID": "sender-id",
"amount": 500.00,
"transactionDate": "2026-01-15",
"externalReference": "rem-001"
}'const options = {
method: 'POST',
headers: {
'Authorization': 'Bearer <SHORT_TERM_TOKEN>',
'X-OTP': '<X_OTP>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"clientID": "sender-id",
"amount": 500.00,
"transactionDate": "2026-01-15",
"externalReference": "rem-001"
})
};
fetch('https://FQDN/api/FE/AddClientFunds', options)
.then(r => r.json())
.then(console.log)
.catch(console.error);import requests
url = "https://FQDN/api/FE/AddClientFunds"
headers = {
"Authorization": "Bearer <SHORT_TERM_TOKEN>",
"X-OTP": "<X_OTP>",
"Content-Type": "application/json"
}
payload = {
"clientID": "sender-id",
"amount": 500.00,
"transactionDate": "2026-01-15",
"externalReference": "rem-001"
}
resp = requests.post(url, headers=headers, json=payload)
print(resp.json())1101Convert the cleared USD to USDC for transfer.
| Field | Type | Required | Description | Value |
|---|---|---|---|---|
| clientID | string (UUID) | REQUIRED | The client whose funds to convert. | |
| amount | number | REQUIRED | Amount to convert. | |
| fromCurrencyID | CurrencyType | REQUIRED | Source currency (see CurrencyType enum). | |
| toCurrencyID | CurrencyType | REQUIRED | Target currency (see CurrencyType enum). | |
| externalReference | string | REQUIRED | Your unique reconciliation key. |
curl --request POST \
--url 'https://FQDN/api/FE/ConvertClientFunds' \
--header 'Authorization: Bearer <SHORT_TERM_TOKEN>' \
--header 'X-OTP: <X_OTP>' \
--header 'Content-Type: application/json' \
--data '{
"clientID": "sender-id",
"amount": 500.00,
"fromCurrencyID": "USD",
"toCurrencyID": "USDC",
"externalReference": "rem-002"
}'const options = {
method: 'POST',
headers: {
'Authorization': 'Bearer <SHORT_TERM_TOKEN>',
'X-OTP': '<X_OTP>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"clientID": "sender-id",
"amount": 500.00,
"fromCurrencyID": "USD",
"toCurrencyID": "USDC",
"externalReference": "rem-002"
})
};
fetch('https://FQDN/api/FE/ConvertClientFunds', options)
.then(r => r.json())
.then(console.log)
.catch(console.error);import requests
url = "https://FQDN/api/FE/ConvertClientFunds"
headers = {
"Authorization": "Bearer <SHORT_TERM_TOKEN>",
"X-OTP": "<X_OTP>",
"Content-Type": "application/json"
}
payload = {
"clientID": "sender-id",
"amount": 500.00,
"fromCurrencyID": "USD",
"toCurrencyID": "USDC",
"externalReference": "rem-002"
}
resp = requests.post(url, headers=headers, json=payload)
print(resp.json())1102USD.USDC.Send the stablecoin to the recipient's wallet on-chain.
| Field | Type | Required | Description | Value |
|---|---|---|---|---|
| address | string | REQUIRED | Destination wallet address. Must already be whitelisted via Add Wallet Address. | |
| clientId | string | optional | The client ID. Obtain via Create Client. | |
| amount | number (double) | REQUIRED | Amount to send. Must be greater than 0.00000001 (the smallest tradeable BTC unit). | |
| currency | CurrencyType | REQUIRED | Digital-asset currency. Cannot be USD (1) or PUSD (2), and cannot be the unset default (0). See CurrencyType. | |
| externalReference | string | REQUIRED | Your transaction reference. Maximum 50 characters. |
curl --request POST \
--url 'https://FQDN/api/FE/SendFundsToAddress?clientId=sender-id&address=recipient-wallet&amount=500.00¤cy=USDC&externalReference=rem-003' \
--header 'Authorization: Bearer <SHORT_TERM_TOKEN>' \
--header 'X-OTP: <X_OTP>'const options = {
method: 'POST',
headers: {
'Authorization': 'Bearer <SHORT_TERM_TOKEN>',
'X-OTP': '<X_OTP>'
}
};
fetch('https://FQDN/api/FE/SendFundsToAddress?clientId=sender-id&address=recipient-wallet&amount=500.00¤cy=USDC&externalReference=rem-003', options)
.then(r => r.json())
.then(console.log)
.catch(console.error);import requests
url = "https://FQDN/api/FE/SendFundsToAddress?clientId=sender-id&address=recipient-wallet&amount=500.00¤cy=USDC&externalReference=rem-003"
headers = {
"Authorization": "Bearer <SHORT_TERM_TOKEN>",
"X-OTP": "<X_OTP>"
}
resp = requests.post(url, headers=headers)
print(resp.json()){
"isSuccess": true,
"result": "0xhash...",
"errorMessage": null
}USDC.SendFundsToAddress (steps 4–5). The recipient custodies the asset.NewClient, deliver into their RAMFi balance, and let them off-ramp with ConvertClientFunds → WithdrawClientFunds (see the off-ramp recipe).