Creating a payout

When creating a payout, there are two possible flows:

  1. You already know the crypto address of the destination of the payout and can enter it on the API call.
  2. You don't know the crypto address of the destination of the payout, and will redirect the user to the hosted page to collect it.

In the same way as the payments workflow, you will be provided with a redirect URL to collect the details if necessary. For this guide, we will presume you have the address already.

Validating the crypto address

If integrated directly with our API, before making a payout, it is recommended to validate the crypto address with the Validate address endpoint. This checks that all required data is present in order achieve a successful payout. This improves end user experience by providing this feedback ahead of creating the payout. If you're using the hosted page the address will be validated when inputted by the end user.

For example, tag is required for XRP payouts to exchanges, ensuring the funds are allocated to the correct customer.

❗️

If the address is invalid the payout request will fail and you'll see an error like the following:

{
  "errorList": [
    {
      "parameter": "payOutInstruction",
      "code": "invalidPayout",
      "message": "Invalid Instruction for Payout"
    }
  ]
}

Setting a unique reference

Make sure you are setting a unique reference for the payout, otherwise you'll see an error like the following:

{
  "errorList": [
    {
      "parameter": "reference",
      "code": "unique",
      "message": "Duplicate Reference"
    }
  ]
}

Making the request

Here's an example payout request using the Create payment endpoint.

curl --location 'https://api.sandbox.bvnk.com/api/v1/pay/summary' \
--header 'Content-Type: application/json' \
--header 'Authorization: Hawk id="vbfc61D890wg6LAAVbkR11qP9O6cXeMNmKWgcUNZaOHPiQeebp9cl6h02tWv84R8", ts="1728648264", nonce="uBmULV", mac="Z5hY60DlvCVq/WpIEXN4OhAlg1FwZb6DcDJP6TVGHjI="' \
--data '{
    "merchantId": "86955f40-8f4e-464c-be2b-583635bf1c62",
    "type": "OUT",
    "amount": 10,
    "currency": "USD",
    "expiryMinutes": 30,
    "reference": "test_reference_out_ka7Lyo",
    "returnUrl": "https://your-url-here.com/status",
    "payOutDetails": {
        "code": "crypto",
        "currency": "ETH",
        "protocol": "ETH",
        "address": "0x02ae6765C6991813a3EAa86fe63ebBCA1c9EC156",
        "tag": ""
    },
    "customerId": "8e5563ee-7516-4957-a724-067e0c1675af",
    "complianceDetails": {
        "requesterIpAddress": "77.71.188.87",
        "partyDetails": [
            {
                "type": "BENEFICIARY",
                "entityType": "INDIVIDUAL",
                "firstName": "John",
                "lastName": "Doe",
                "dateOfBirth": "1984-06-30",
                "relationshipType": "THIRD_PARTY",
                "countryCode": "DE"
            }
        ]
    }
}'

Let's go through the details you'll supply in the payout request.

ParameterTypeDescription
merchantIdstringYour Merchant ID. You can find it on the Merchant Details page in your account.

See this guide for creating one
referencestringYour unique reference for the payout.
amountbig decimalThe amount to payout in the display currency.
currencystringThe currency code for the currency you'd like to display the payout value in - which will be debited from your merchant account.
typestringSet to OUT to define this as a payout.
payoutDetails.addressstringAn optional field to collect the crypto address and prevent the user from needing to enter it into a hosted page.
payoutDetails.currencystringAn optional field to collect the currency the user wants to be paid out. If you'd like to let them select, then leave this field out and send them to the hosted page to select.
payoutDetails.codestringSet to crypto.
payoutDetails.protocolstringRequired field for currencies that use multiple networks (USDT,USDC)
payoutDetails.tagstringRequired field for currencies that use a destination tag (XRP)
complianceDetails.requesterIpAddressstringThe IP of the payout requester (optional)

🚧

Currencies that can be sent via more than one network:

USDT and USDC

USDT can be sent over the ERC20, TRC20 and BEP20 networks.
USDC can be sent over ERC20, POLYGON and BEP20 networks.

When sending the payout request for these currencies it is mandatory to include the "protocol":in the payoutDetails object.

Here's an example payout request using the Create payment endpoint for USDT:
Notice the PROTOCOL string.

curl --location 'https://api.sandbox.bvnk.com/api/v1/pay/summary' \
--header 'Content-Type: application/json' \
--header 'Authorization: Hawk id="vbfc61D890wg6LAAVbkR11qP9O6cXeMNmKWgcUNZaOHPiQeebp9cl6h02tWv84R8", ts="1728648387", nonce="4M06cZ", mac="PSNDZjPHV0gnxuhwBZ0HMYGPctOwP3gj4E3cO2d0hT8="' \
--data '{
    "merchantId": "86955f40-8f4e-464c-be2b-583635bf1c62",
    "type": "OUT",
    "amount": 10,
    "currency": "USD",
    "expiryMinutes": 30,
    "reference": "test_reference_out_KmkrUm",
    "returnUrl": "https://your-url-here.com/status",
    "payOutDetails": {
        "code": "crypto",
        "currency": "USDT",
        "protocol": "ERC20",
        "address": "0x02ae6765C6991813a3EAa86fe63ebBCA1c9EC156",
        "tag": ""
    },
    "customerId": "c1076fbf-f7a7-4c55-bd8c-046da277bc7b",
    "complianceDetails": {
        "requesterIpAddress": "77.71.188.87",
        "partyDetails": [
            {
                "type": "BENEFICIARY",
                "entityType": "INDIVIDUAL",
                
                
                
                "firstName": "John",
                "lastName": "Doe",
                "dateOfBirth": "1984-06-30",
                "relationshipType": "THIRD_PARTY",
                "countryCode": "DE"
            }
        ]
    }
}'