curl --request POST \
--url https://production.hifibridge.com/v2/users/{userId}/virtual-accounts \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"sourceCurrency": "usd",
"externalWalletId": "<string>",
"maxBps": 5000
}
'import requests
url = "https://production.hifibridge.com/v2/users/{userId}/virtual-accounts"
payload = {
"sourceCurrency": "usd",
"externalWalletId": "<string>",
"maxBps": 5000
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({sourceCurrency: 'usd', externalWalletId: '<string>', maxBps: 5000})
};
fetch('https://production.hifibridge.com/v2/users/{userId}/virtual-accounts', 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://production.hifibridge.com/v2/users/{userId}/virtual-accounts",
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([
'sourceCurrency' => 'usd',
'externalWalletId' => '<string>',
'maxBps' => 5000
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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://production.hifibridge.com/v2/users/{userId}/virtual-accounts"
payload := strings.NewReader("{\n \"sourceCurrency\": \"usd\",\n \"externalWalletId\": \"<string>\",\n \"maxBps\": 5000\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://production.hifibridge.com/v2/users/{userId}/virtual-accounts")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"sourceCurrency\": \"usd\",\n \"externalWalletId\": \"<string>\",\n \"maxBps\": 5000\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://production.hifibridge.com/v2/users/{userId}/virtual-accounts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"sourceCurrency\": \"usd\",\n \"externalWalletId\": \"<string>\",\n \"maxBps\": 5000\n}"
response = http.request(request)
puts response.read_body{
"message": "Virtual account created successfully",
"accountInfo": {
"id": "cfbc005d-8640-57a4-89e1-539c974fa780",
"createdAt": "2025-09-27T03:08:11.548Z",
"updatedAt": "2025-09-27T03:08:11.548Z",
"userId": "840c28f2-ea7d-5c3a-9271-b10fd8b6ae6d",
"source": {
"paymentRail": [
"ach",
"wire",
"rtp"
],
"currency": "usd"
},
"destination": {
"chain": "POLYGON",
"currency": "usdc",
"walletAddress": "0xd102C4130985B7fcB95697616eaf5542c4f98d49",
"externalWalletId": null
},
"status": "activated",
"depositInstructions": {
"bankName": "Bank of NoWhere",
"bankAddress": "123 Main St, New York, NY 10001, USA",
"beneficiary": {
"name": "Henry Wu",
"address": "Example St 1., Apt 123, New York, NY, 10010, US"
},
"ach": {
"routingNumber": "028000024",
"accountNumber": "123456789"
},
"wire": {
"routingNumber": "021000021",
"accountNumber": "123456789"
},
"rtp": {
"routingNumber": "021000021",
"accountNumber": "123456789"
},
"instruction": "Please deposit usd to the bank account provided. Please ensure that the beneficiary name matches the account holder name provided, or the payment may be rejected."
},
"settlementRuleId": null
}
}{
"code": 123,
"error": "<string>",
"errorDetails": "<string>"
}{
"status": "error",
"error": {
"code": "<string>",
"message": "<string>"
}
}{
"code": 123,
"error": "<string>",
"errorDetails": "<string>"
}Create a virtual account
Generate a virtual bank account to onramp from sourceCurrency to destinationCurrency on chain destinationChain. (note: virtual accounts are billable)
curl --request POST \
--url https://production.hifibridge.com/v2/users/{userId}/virtual-accounts \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"sourceCurrency": "usd",
"externalWalletId": "<string>",
"maxBps": 5000
}
'import requests
url = "https://production.hifibridge.com/v2/users/{userId}/virtual-accounts"
payload = {
"sourceCurrency": "usd",
"externalWalletId": "<string>",
"maxBps": 5000
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({sourceCurrency: 'usd', externalWalletId: '<string>', maxBps: 5000})
};
fetch('https://production.hifibridge.com/v2/users/{userId}/virtual-accounts', 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://production.hifibridge.com/v2/users/{userId}/virtual-accounts",
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([
'sourceCurrency' => 'usd',
'externalWalletId' => '<string>',
'maxBps' => 5000
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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://production.hifibridge.com/v2/users/{userId}/virtual-accounts"
payload := strings.NewReader("{\n \"sourceCurrency\": \"usd\",\n \"externalWalletId\": \"<string>\",\n \"maxBps\": 5000\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://production.hifibridge.com/v2/users/{userId}/virtual-accounts")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"sourceCurrency\": \"usd\",\n \"externalWalletId\": \"<string>\",\n \"maxBps\": 5000\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://production.hifibridge.com/v2/users/{userId}/virtual-accounts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"sourceCurrency\": \"usd\",\n \"externalWalletId\": \"<string>\",\n \"maxBps\": 5000\n}"
response = http.request(request)
puts response.read_body{
"message": "Virtual account created successfully",
"accountInfo": {
"id": "cfbc005d-8640-57a4-89e1-539c974fa780",
"createdAt": "2025-09-27T03:08:11.548Z",
"updatedAt": "2025-09-27T03:08:11.548Z",
"userId": "840c28f2-ea7d-5c3a-9271-b10fd8b6ae6d",
"source": {
"paymentRail": [
"ach",
"wire",
"rtp"
],
"currency": "usd"
},
"destination": {
"chain": "POLYGON",
"currency": "usdc",
"walletAddress": "0xd102C4130985B7fcB95697616eaf5542c4f98d49",
"externalWalletId": null
},
"status": "activated",
"depositInstructions": {
"bankName": "Bank of NoWhere",
"bankAddress": "123 Main St, New York, NY 10001, USA",
"beneficiary": {
"name": "Henry Wu",
"address": "Example St 1., Apt 123, New York, NY, 10010, US"
},
"ach": {
"routingNumber": "028000024",
"accountNumber": "123456789"
},
"wire": {
"routingNumber": "021000021",
"accountNumber": "123456789"
},
"rtp": {
"routingNumber": "021000021",
"accountNumber": "123456789"
},
"instruction": "Please deposit usd to the bank account provided. Please ensure that the beneficiary name matches the account holder name provided, or the payment may be rejected."
},
"settlementRuleId": null
}
}{
"code": 123,
"error": "<string>",
"errorDetails": "<string>"
}{
"status": "error",
"error": {
"code": "<string>",
"message": "<string>"
}
}{
"code": 123,
"error": "<string>",
"errorDetails": "<string>"
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Path Parameters
ID of the user
Body
Create a virtual account and optionally configure its automatic USDT onramp conversion-fee threshold.
usd usdc, usdt, usdg, pyusd Either externalWalletId or destinationChain must be provided. If provided, the token will be delivered to user's HIFI wallet on the destination chain.
POLYGON, ETHEREUM, SOLANA, BASE, TRON Either externalWalletId or destinationChain must be provided.
Maximum USDT conversion fee, supplied as an integer or decimal-integer
string representing 0 through 10,000 basis points, allowed for automatic
onramps through this virtual account. Omit or use null to leave the
threshold disabled.
0 <= x <= 10000ach, wire