Automate Fiat-to-Crypto Transfers
This guide explains how to create a rule on a Fiat Virtual Account to automatically convert from fiat to crypto, and then send those crypto funds to a crypto address.
An on-ramp is the process of moving value from traditional finance (fiat currency) into digital assets (cryptocurrency). Within BVNK, this is enabled through the payment rules endpoint, which allows you to define rules on a fiat Virtual Account (VA). These rules automatically convert funds deposited into the VA into cryptocurrency and transfer them to a designated wallet.
By serving as a bridge between fiat accounts and crypto wallets, the endpoint provides a seamless, automated flow of funds. For embedded partners, on-ramp functionality provides a reliable way to offer customers greater financial flexibility by giving them direct access to crypto from fiat payments without manual steps.

Prerequisites
Before configuring the payment rules, make sure you have prepared the following:
- Created Embedded Partner Customer. This customer entity will be the owner of both the Fiat Virtual Account and the associated crypto wallet destination.
- Created and assigned Fiat Virtual Account to the Embedded Partner Customer. This virtual account serves as the bridge for the crypto wallet destination.
- Added Customer fee wallet, if you are planning to charge fees from customers. This requirement is optional.
Failure to meet these prerequisites will result in an error when attempting to use the Payment Rules endpoint.
Create payment rule
To create a rule that links a crypto wallet to a fiat Virtual Account, send the POST /payment/v1/rules
request with the following body:
Example Requests
{
"reference": "REF558628",
"trigger": "event:payment:payin",
"walletId": "a:24145329329347:HsdJVhW:1",
"fees": {
"customerFee": {
"amount": 0.5,
"currency": "USD"
}
},
"beneficiary": {
"currency": "USDT",
"entity": {
"customerIdentifier": "9401203948572394595",
"legalName": "3Com",
"type": "COMPANY",
"relationshipType": "SELF_OWNED",
"registrationNumber": "ABC21D21FZC",
"address": {
"addressLine1": "Champs-Élysées 101",
"addressLine2": "Apartment 3B",
"city": "Paris",
"region": "Île-de-France",
"postCode": "75008",
"country": "FR"
}
},
"cryptoAddress": {
"network": "ETHEREUM",
"address": "0x12323542636474747",
"tag": "332455"
}
}
}
{
"reference": "REF7658628",
"walletId": "a:25031045518203:IUMTTAY:1",
"trigger": "event:payment:payin",
"fees": {
"customerFee": {
"amount": 1,
"currency": "USD"
}
},
"paidCurrency": "ETH",
"beneficiary": {
"entity": {
"type": "INDIVIDUAL",
"customerIdentifier": "9401203948572394595",
"firstName": "John",
"lastName": "Doe",
"dateOfBirth": "1990-05-15",
"relationshipType": "SELF_OWNED",
"address": {
"addressLine1": "1600 Amphitheatre Parkway",
"addressLine2": "Building 43",
"city": "Mountain View",
"region": "California",
"postCode": "94043",
"country": "US"
}
},
"cryptoAddress": {
"network": "Ethereum",
"address": "0xDDCD0Aa2C21d2d02ec0977565D037aBC67F7F151"
}
}
}
For the detailed description of each field, refer to Create Payment Rule. Note the following parameters:
trigger
: Specifies the originating event which triggers this automated action:- For on-ramp fiat → crypto:
payment:payin:fiat
- For on-ramp fiat → crypto:
customerIdentifier
: unique identifier of the customer.
Wallet ValidationWhen you create a payment rule to automatically on-ramp funds to a wallet, we validate the destination wallet address. This ensures that newly converted crypto funds settle to a valid wallet.
Upon successful linking of the crypto wallet to the Fiat Virtual Account, the API returns an HTTP 200 OK status code along with a JSON object confirming the operation.
Example Response
{
"id": "98c0bb03-567f-11f0-b26e-6b1848874a27",
"reference": "REF558628",
"trigger": "event:payment:payin",
"status": "ACTIVE",
"fees": {
"customerFee": {
"amount": 0.5,
"currency": "USD"
}
},
"originator": {
"currency": "USD",
"walletId": "acc:22041242429000:3MPpU:0"
},
"beneficiary": {
"currency": "USDT",
"entity": {
"legalName": "3Com",
"type": "COMPANY",
"relationshipType": "SELF_OWNED",
"registrationNumber": "ABC21D21FZC",
"address": {
"addressLine1": "Champs-Élysées 101",
"addressLine2": "Apartment 3B",
"city": "Paris",
"region": "Île-de-France",
"postCode": "75008",
"country": "FR"
}
},
"cryptoAddresses": {
"network": "ETHEREUM",
"addresses": [
"0x12323542636474747"
],
"tag": "332455"
}
},
"metadata": {},
"updatedAt": "2025-07-01T13:31:02.52.000000000Z",
"createdAt": "2025-07-01T13:30:02.52.000000000Z"
}
If the operation was not successful, the API returns an HTTP 400 BAD REQUEST status code along with a JSON error code bvnk:payment:rules:40**
or bvnk:payment:rules:50**
.
{
"code": "bvnk:payment:rules:4002",
"status": "BAD_REQUEST",
"message": "Address validation error"
}
Update payment rule
To change a previously created payment rule, send the PATCH payment/v1/rules/{id}
request with the id
received the successful response earlier, here, 98c0bb03-567f-11f0-b26e-6b1848874a27
.
In the request body, specify only properties that you want to update. The omitted fields will remain unchanged, and sending a null for a nullable property will clear it.
You can update the following properties:
beneficiary.cryptoAddress.address
beneficiary.cryptoAddress.network
beneficiary.cryptoAddress.tag
beneficiary.entity.address.addressLine1
beneficiary.entity.address.addressLine2
beneficiary.entity.address.city
beneficiary.entity.address.country
beneficiary.entity.address.postCode
beneficiary.entity.address.region
beneficiary.entity.customerIdentifier
beneficiary.entity.dateOfBirth (Individual)
beneficiary.entity.firstName (Individual)
beneficiary.entity.lastName (Individual)
beneficiary.entity.legalName (Company)
beneficiary.entity.registrationNumber (Company)
beneficiary.entity.relationshipType
beneficiary.entity.type
fees.customerFee.amount
fees.customerFee.currency
paidCurrency
See the example payloads for different use cases:
{
"fees": {
"customerFee": {
"amount": 3.5,
"currency": "USD"
}
}
}
{
"beneficiary": {
"entity": {
"type": "COMPANY",
"legalName": "APEX Ltd."
}
}
}
{
"beneficiary": {
"cryptoAddress": {
"address": "0x742d35cc6634C0532925a3b844Bc9e7595f0bEA5",
"network": "Ethereum"
}
}
}
Receive notifications
To receive notifications about operations, use the following webhooks:
For more information about webhooks, refer to Receive Webhook Notifications.
Updated about 2 hours ago