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:

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
  • customerIdentifier: unique identifier of the customer.
📘

Wallet Validation

When 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.