Prerequisites
Complete these once per customer before running either ramp. They are not part of the numbered flow below.
PRESubmit the customer for onboardingPOST
/api/FE/NewClient

Your app sends the customer's details; RAMFi runs KYC, opens the account, and returns a client record with Active status when verification passes.

Request Body Parameters — enter values to build the request
FieldTypeRequiredDescriptionValue
firstNamestringREQUIREDClient's legal first name.
lastNamestringREQUIREDClient's legal last name.
addressstringREQUIREDStreet address.
citystringREQUIREDCity.
statestringREQUIREDState code.
zipstringREQUIREDZIP code.
taxIDstringREQUIREDSSN (or EIN for business accounts).
dobstring (date)REQUIREDDate of birth (YYYY-MM-DD).
clientIDstringREQUIREDYour external identifier for this client.
emailstringREQUIREDEmail 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": "customer-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": "customer-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": "customer-id", "email": "user@example.com" } resp = requests.post(url, headers=headers, json=payload) print(resp.json())
{ "id": "string", "clientID": "customer-id", "accountStatus": "Active", "email": "user@example.com" }
firstName / lastName
Customer's legal name, used for KYC.
taxID
SSN / tax identifier for identity verification.
clientID
Your unique identifier for this customer, used on every later call.
email
Customer contact email.
accountStatus
Active means the client is verified and can transact.
PREWhitelist the wallet addressPOST
/api/FE/AddWalletAddress?address=0x...&addressIdentifier=Customer%20wallet

Register the external wallet with RAMFi. Every address must be whitelisted and AML-screened before it can send funds to or receive funds from RAMFi — the destination wallet for on-ramp sends, and the customer’s sending wallet for off-ramp deposits. Parameters are sent as query string.

Query Parameters — enter values to build the request
FieldTypeRequiredDescriptionValue
addressstringoptionalThe wallet address.
addressIdentifierstringoptionalA friendly name for the address.
curl --request POST \ --url 'https://FQDN/api/FE/AddWalletAddress?address=0x...&addressIdentifier=Customer%20wallet' \ --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=0x...&addressIdentifier=Customer%20wallet', options) .then(r => r.json()) .then(console.log) .catch(console.error);
import requests url = "https://FQDN/api/FE/AddWalletAddress?address=0x...&addressIdentifier=Customer%20wallet" 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 }
address
The destination wallet address (query parameter).
addressIdentifier
A friendly label for the address (query parameter).
On-Ramp: fiat to digital asset
Fund in USD, convert, and send to a customer-controlled wallet.
  • 1
    YouFund in USD
    ACH (see Funding methods)
  • RAMFiCredit USD balance
    RAMFi clears funds; USD tradable
  • 2
    YouRequest conversion
    POST /ConvertClientFunds
  • RAMFiExecute conversion
    RAMFi converts at market rate
  • 3
  • RAMFiBroadcast transaction
    RAMFi signs & submits on-chain
  • ChainSettles on-chain
    confirmed on the blockchain
Show full interaction diagram
Your ApplicationRAMFiBlockchain1Fund in USDACH (see Funding methods)Credit USD balanceRAMFi clears funds; USD tradable2Request conversioncall POST /ConvertClientFundsExecute conversionRAMFi converts at market rate3Request sendcall POST /SendFundsToAddressBroadcast transactionRAMFi signs & submits on-chainSettles on-chainconfirmed on the blockchain

On-ramp sequence. App-lane boxes are API calls; RAMFi performs the work; the Blockchain lane is where the transaction confirms.

Your application orchestrates; RAMFi performs. Every call below runs against RAMFi. RAMFi performs KYC, moves the money, AML-screens addresses, and settles. Your app issues the requests; it never performs KYC or holds funds or keys itself.
Funding methods: fund in USD
Two ways to bring fiat in: pull it from a linked bank by ACH, or have the customer push it to RAMFi by wire or RTP.

ACH, bank account

  • 1
    YouLink bank account
    launch Bank Connection SDK (open banking)
    Open SDK →
  • RAMFiVerify & store bank
    RAMFi saves the linked account
  • 2
  • RAMFiDraft & clear (ACH)
    ~2 business days, then credit USD
Show full interaction diagram
Your ApplicationRAMFi1Link bank accountlaunch Bank Connection SDK (openbanking)Verify & store bankRAMFi saves the linked account2Pull fundscall POST /AddClientFundsDraft & clear (ACH)~2 business days, then credit USD

Link the bank once via the open-banking SDK, then pull with AddClientFunds.

2Pull funds via ACHPOST
/api/FE/AddClientFunds

Draft the linked bank. Funds are pending ~2 business days before they are tradable.

Request Body Parameters — enter values to build the request
FieldTypeRequiredDescriptionValue
clientIDstringREQUIREDThe client to fund.
amountnumberREQUIREDUSD amount to draft via ACH.
transactionDatestring (date)optionalDate to initiate the ACH draft (YYYY-MM-DD).
externalReferencestringREQUIREDYour 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": "customer-id", "amount": 250.00, "transactionDate": "2026-01-15", "externalReference": "ext-001" }'
const options = { method: 'POST', headers: { 'Authorization': 'Bearer <SHORT_TERM_TOKEN>', 'X-OTP': '<X_OTP>', 'Content-Type': 'application/json' }, body: JSON.stringify({ "clientID": "customer-id", "amount": 250.00, "transactionDate": "2026-01-15", "externalReference": "ext-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": "customer-id", "amount": 250.00, "transactionDate": "2026-01-15", "externalReference": "ext-001" } resp = requests.post(url, headers=headers, json=payload) print(resp.json())
1024
clientID
The customer to credit.
amount
USD amount to draft. Include decimals.
transactionDate
Date to initiate the ACH draft.
externalReference
Your unique reference for reconciliation.
(response)
Returns the numeric transaction ID.

Wire / RTP

  • 1
    YouGet deposit instructions
    GET /GetDepositInfo
  • RAMFiReturn bank details + memo ID
    give these to the customer to wire against
  • 2
    YouRecord the incoming wire
    POST /AddPendingFunds
  • RAMFiMatch wire, credit USD
    credited once the wire lands
Show full interaction diagram
Your ApplicationRAMFi1Get deposit instructionscall GET /GetDepositInfoReturn bank details + memo IDwire coordinates for the customer2Record the incoming wirecall POST /AddPendingFundsMatch wire, credit USDcredited once the wire lands
1Get the deposit instructionsGET
/api/FE/GetDepositInfo?clientId=customer-id

Returns the receiving bank coordinates and a memoID. Show these to the customer — the wire must carry the memoID so the funds can be attributed to them.

Query Parameters — enter values to build the request
FieldTypeRequiredDescriptionValue
clientIdstringoptionalThe client ID. Obtain via Create Client.
curl --request GET \ --url 'https://FQDN/api/FE/GetDepositInfo?clientId=customer-id' \ --header 'Authorization: Bearer <SHORT_TERM_TOKEN>' \ --header 'X-OTP: <X_OTP>'
const options = { method: 'GET', headers: { 'Authorization': 'Bearer <SHORT_TERM_TOKEN>', 'X-OTP': '<X_OTP>' } }; fetch('https://FQDN/api/FE/GetDepositInfo?clientId=customer-id', options) .then(r => r.json()) .then(console.log);
import requests url = "https://FQDN/api/FE/GetDepositInfo" headers = { "Authorization": "Bearer <SHORT_TERM_TOKEN>", "X-OTP": "<X_OTP>" } resp = requests.get(url, headers=headers, params={"clientId": "customer-id"}) print(resp.json())
{ "bankAccount": "string", "routing": "string", "bankName": "string", "address": "string", "city": "string", "state": "string", "zip": "string", "memoID": "string" }
memoID
Reference the customer must include on the wire.
bankAccount / routing
Destination account for ACH, Wire or RTP.
bankName / address
Receiving bank details some banks require to send a wire.
2Record the incoming wirePOST
/api/FE/AddPendingFunds

Tell RAMFi a deposit is on its way so it can be matched and attributed when it lands. Set clientReference to the memoID from the previous call.

Request Body Parameters — enter values to build the request
FieldTypeRequiredDescriptionValue
clientIDstringREQUIREDThe client the pending deposit is for.
externalTransactionIDstringREQUIREDExternal transaction/processor reference, known in advance.
amountnumberREQUIREDExpected deposit amount.
expectedDepositDatestring (date)optionalWhen the deposit is expected to clear (YYYY-MM-DD).
clientReferencestringoptionalYour reference for this pending deposit.
curl --request POST \ --url 'https://FQDN/api/FE/AddPendingFunds' \ --header 'Authorization: Bearer <SHORT_TERM_TOKEN>' \ --header 'X-OTP: <X_OTP>' \ --header 'Content-Type: application/json' \ --data '{ "clientID": "customer-id", "externalTransactionID": "wire-001", "amount": 25000.00, "expectedDepositDate": "2026-07-24", "clientReference": "MEMO-8842" }'
const options = { method: 'POST', headers: { 'Authorization': 'Bearer <SHORT_TERM_TOKEN>', 'X-OTP': '<X_OTP>', 'Content-Type': 'application/json' }, body: JSON.stringify({ "clientID": "customer-id", "externalTransactionID": "wire-001", "amount": 25000.00, "expectedDepositDate": "2026-07-24", "clientReference": "MEMO-8842" }) }; fetch('https://FQDN/api/FE/AddPendingFunds', options) .then(r => r.json()) .then(console.log);
import requests url = "https://FQDN/api/FE/AddPendingFunds" headers = { "Authorization": "Bearer <SHORT_TERM_TOKEN>", "X-OTP": "<X_OTP>", "Content-Type": "application/json" } payload = { "clientID": "customer-id", "externalTransactionID": "wire-001", "amount": 25000.00, "expectedDepositDate": "2026-07-24", "clientReference": "MEMO-8842" } resp = requests.post(url, headers=headers, json=payload) print(resp.json())
Success - no response body is returned.
externalTransactionID
Required. Your unique reference for the deposit.
clientReference
The memoID the customer put on the wire.
expectedDepositDate
Helps RAMFi match the deposit when it arrives.
amount
Expected amount; the credit follows the funds that actually land.
On-ramp steps
From onboarding to an on-chain send.
1Fund in USD

Bring fiat in using the funding method above (ACH). RAMFi credits the USD balance.

2Request the conversionPOST
/api/FE/ConvertClientFunds

Convert the USD balance to USDC at the market rate at time of conversion.

Request Body Parameters — enter values to build the request
FieldTypeRequiredDescriptionValue
clientIDstring (UUID)REQUIREDThe client whose funds to convert.
amountnumberREQUIREDAmount to convert.
fromCurrencyIDCurrencyTypeREQUIREDSource currency (see CurrencyType enum).
toCurrencyIDCurrencyTypeREQUIREDTarget currency (see CurrencyType enum).
externalReferencestringREQUIREDYour 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": "customer-id", "amount": 250.00, "fromCurrencyID": "USD", "toCurrencyID": "USDC", "externalReference": "ext-003" }'
const options = { method: 'POST', headers: { 'Authorization': 'Bearer <SHORT_TERM_TOKEN>', 'X-OTP': '<X_OTP>', 'Content-Type': 'application/json' }, body: JSON.stringify({ "clientID": "customer-id", "amount": 250.00, "fromCurrencyID": "USD", "toCurrencyID": "USDC", "externalReference": "ext-003" }) }; 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": "customer-id", "amount": 250.00, "fromCurrencyID": "USD", "toCurrencyID": "USDC", "externalReference": "ext-003" } resp = requests.post(url, headers=headers, json=payload) print(resp.json())
2048
fromCurrencyID
Source currency: USD.
toCurrencyID
Target stablecoin: USDC.
amount
Amount of the source currency to convert.
(response)
Returns the numeric conversion transaction ID.
3Request the sendPOST
/api/FE/SendFundsToAddress?clientId=customer-id&address=0x...&amount=250.00&currency=USDC&externalReference=ext-005

Send the converted digital asset on-chain to the whitelisted address. RAMFi signs and broadcasts.

Query Parameters — enter values to build the request
FieldTypeRequiredDescriptionValue
addressstringREQUIREDDestination wallet address. Must already be whitelisted via Add Wallet Address.
clientIdstringoptionalThe client ID. Obtain via Create Client.
amountnumber (double)REQUIREDAmount to send. Must be greater than 0.00000001 (the smallest tradeable BTC unit).
currencyCurrencyTypeREQUIREDDigital-asset currency. Cannot be USD (1) or PUSD (2), and cannot be the unset default (0). See CurrencyType.
externalReferencestringREQUIREDYour transaction reference. Maximum 50 characters.
curl --request POST \ --url 'https://FQDN/api/FE/SendFundsToAddress?clientId=customer-id&address=0x...&amount=250.00&currency=USDC&externalReference=ext-005' \ --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=customer-id&address=0x...&amount=250.00&currency=USDC&externalReference=ext-005', options) .then(r => r.json()) .then(console.log) .catch(console.error);
import requests url = "https://FQDN/api/FE/SendFundsToAddress?clientId=customer-id&address=0x...&amount=250.00&currency=USDC&externalReference=ext-005" headers = { "Authorization": "Bearer <SHORT_TERM_TOKEN>", "X-OTP": "<X_OTP>" } resp = requests.post(url, headers=headers) print(resp.json())
{ "isSuccess": true, "result": "0xabc...hash", "errorMessage": null }
clientId
The customer sending funds (query parameter).
address
Destination wallet, must be whitelisted first (query parameter).
amount
Amount of digital asset to send.
currency
Asset to send, e.g. USDC.
externalReference
Your unique reference.
Whitelist first. SendFundsToAddress fails for any address not previously registered via AddWalletAddress.

Off-Ramp: digital asset to fiat
Receive digital asset, convert to USD, and disburse by ACH or to a card.
ℹ️
Fiat legs run on either rail in both directions: fund with an ACH pull (Bank Connection SDK) or a card pull (PullFromCard), and pay out by ACH (WithdrawClientFunds) or a card push (PushToCard).
Show full interaction diagram
Your ApplicationRAMFiBlockchainCustomer sends digital assetdeposit confirmed on-chain1Ledger the depositcall POST /AddFundsFromAddress (tx hash)Credit asset balanceRAMFi records the deposit2Request conversioncall POST /ConvertClientFundsExecute conversionRAMFi converts at market rate3Request withdrawalcall POST /WithdrawClientFundsDisburse USD (ACH)RAMFi sends ACH to linked bank

Off-ramp sequence. App-lane boxes are API calls; RAMFi screens, records, converts, and disburses. The deposit confirms in the Blockchain lane.

1Ledger the inbound depositPOST
/api/FE/AddFundsFromAddress

After the customer sends digital asset on-chain, record it against the client using the transaction hash for verification.

Request Body Parameters — enter values to build the request
FieldTypeRequiredDescriptionValue
clientIDstringREQUIREDThe client the deposit is for.
externalTransactionIDstringREQUIREDYour external transaction reference.
amountnumberREQUIREDExpected deposit amount.
fromAddressstringREQUIREDExternal whitelisted source address.
toAddressstringREQUIREDRAMFi custody receiving address (must be whitelisted).
fundsTypeCurrencyTypeREQUIREDDigital-asset currency of the deposit (CurrencyType enum, e.g. 6 = BTC).
curl --request POST \ --url 'https://FQDN/api/FE/AddFundsFromAddress' \ --header 'Authorization: Bearer <SHORT_TERM_TOKEN>' \ --header 'X-OTP: <X_OTP>' \ --header 'Content-Type: application/json' \ --data '{ "clientID": "customer-id", "externalTransactionID": "0xhash...", "amount": 250.00, "fromAddress": "sending-wallet", "toAddress": "ramfi-address", "fundsType": "USDC" }'
const options = { method: 'POST', headers: { 'Authorization': 'Bearer <SHORT_TERM_TOKEN>', 'X-OTP': '<X_OTP>', 'Content-Type': 'application/json' }, body: JSON.stringify({ "clientID": "customer-id", "externalTransactionID": "0xhash...", "amount": 250.00, "fromAddress": "sending-wallet", "toAddress": "ramfi-address", "fundsType": "USDC" }) }; fetch('https://FQDN/api/FE/AddFundsFromAddress', options) .then(r => r.json()) .then(console.log) .catch(console.error);
import requests url = "https://FQDN/api/FE/AddFundsFromAddress" headers = { "Authorization": "Bearer <SHORT_TERM_TOKEN>", "X-OTP": "<X_OTP>", "Content-Type": "application/json" } payload = { "clientID": "customer-id", "externalTransactionID": "0xhash...", "amount": 250.00, "fromAddress": "sending-wallet", "toAddress": "ramfi-address", "fundsType": "USDC" } resp = requests.post(url, headers=headers, json=payload) print(resp.json())
{ "isSuccess": true, "result": "ledgered", "errorMessage": null }
externalTransactionID
The on-chain transaction hash.
fromAddress
Whitelisted source address.
toAddress
The RAMFi deposit address that received funds.
fundsType
Asset received, a CurrencyType value, e.g. USDC.
2Convert digital asset to USDPOST
/api/FE/ConvertClientFunds

Convert the credited digital-asset balance back to USD at the market rate.

Request Body Parameters — enter values to build the request
FieldTypeRequiredDescriptionValue
clientIDstring (UUID)REQUIREDThe client whose funds to convert.
amountnumberREQUIREDAmount to convert.
fromCurrencyIDCurrencyTypeREQUIREDSource currency (see CurrencyType enum).
toCurrencyIDCurrencyTypeREQUIREDTarget currency (see CurrencyType enum).
externalReferencestringREQUIREDYour 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": "customer-id", "amount": 250.00, "fromCurrencyID": "USDC", "toCurrencyID": "USD", "externalReference": "ext-013" }'
const options = { method: 'POST', headers: { 'Authorization': 'Bearer <SHORT_TERM_TOKEN>', 'X-OTP': '<X_OTP>', 'Content-Type': 'application/json' }, body: JSON.stringify({ "clientID": "customer-id", "amount": 250.00, "fromCurrencyID": "USDC", "toCurrencyID": "USD", "externalReference": "ext-013" }) }; 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": "customer-id", "amount": 250.00, "fromCurrencyID": "USDC", "toCurrencyID": "USD", "externalReference": "ext-013" } resp = requests.post(url, headers=headers, json=payload) print(resp.json())
2049
fromCurrencyID
Source asset: USDC.
toCurrencyID
Target: USD.
(response)
Numeric conversion transaction ID.
3Withdraw to bankPOST
/api/FE/WithdrawClientFunds

Disburse the USD to the client's linked bank account by ACH, or push to a debit card with PushToCard. Both are fiat-out legs; pick the rail your product offers.

Request Body Parameters — enter values to build the request
FieldTypeRequiredDescriptionValue
clientIDstringREQUIREDThe client to withdraw from.
amountnumberREQUIREDAmount to withdraw. Digital-asset withdrawals are backed by a custody transfer.
externalReferencestringREQUIREDYour unique reconciliation key.
notesstringoptionalFree-form notes recorded with the withdrawal.
curl --request POST \ --url 'https://FQDN/api/FE/WithdrawClientFunds' \ --header 'Authorization: Bearer <SHORT_TERM_TOKEN>' \ --header 'X-OTP: <X_OTP>' \ --header 'Content-Type: application/json' \ --data '{ "clientID": "customer-id", "amount": 250.00, "externalReference": "ext-014" }'
const options = { method: 'POST', headers: { 'Authorization': 'Bearer <SHORT_TERM_TOKEN>', 'X-OTP': '<X_OTP>', 'Content-Type': 'application/json' }, body: JSON.stringify({ "clientID": "customer-id", "amount": 250.00, "externalReference": "ext-014" }) }; fetch('https://FQDN/api/FE/WithdrawClientFunds', options) .then(r => r.json()) .then(console.log) .catch(console.error);
import requests url = "https://FQDN/api/FE/WithdrawClientFunds" headers = { "Authorization": "Bearer <SHORT_TERM_TOKEN>", "X-OTP": "<X_OTP>", "Content-Type": "application/json" } payload = { "clientID": "customer-id", "amount": 250.00, "externalReference": "ext-014" } resp = requests.post(url, headers=headers, json=payload) print(resp.json())
3072
amount
USD amount to withdraw.
externalReference
Your unique reference.
(response)
Numeric withdrawal ID.
Reconciliation: store your externalReference / externalTransactionID on every movement and pull GET /Reporting/Transactions or ClientLedger/{{clientId}} to reconcile.
Rates & fees: conversions execute at the market rate at time of conversion. RAMFi's documentation does not specify spreads, network fees, or quote-lock windows, confirm those commercial details with RAMFi.
RAMFi Developer Documentation · Version 1.1