How it works
- Create the merchant. VelaFi returns a
merchantIdand a hostedkycLink. - Send your customer to the
kycLinkto complete KYC or KYB. - Poll the merchant’s status until it is
2(Normal). - Activate a currency account (channel) for each currency the customer needs.
- Optionally create virtual accounts so each of the customer’s payers gets its own deposit details.
- Use the
merchantIdin every order, payout, transfer and query for that customer.
Before you start
- API access, an API key with an IP whitelist, and a token. See Authentication. All calls on this page go from your server, with the
X-BH-TOKENheader. - Your own account approved. Merchants you create sit under your VelaFi account. See Merchants for the multi-merchant model.
- The customer’s data ready. Decide whether each customer is
INDIVIDUALorBUSINESS, and collect a merchant name and an email address for each. - A page to return users to. You pass it as
callbackUrl. For individual verification, VelaFi redirects the user’s browser to this URL when they finish the hosted flow.
Step by step
1
Create the merchant
Call Create Merchant (Store
POST /v2/merchants) with merchantName, email, merchantType (INDIVIDUAL or BUSINESS) and callbackUrl. Send industryType too (and industryTypeRemark when it is other). For individuals, flow selects the KYC flow (PROFESSIONALS by default, or CONSUMERS), and languageCode sets the language of the hosted page (en, es, pt, zh).merchantId against the customer in your system right away. The merchant exists from this point, even before verification.Common rejections:2
Send the customer to the verification link
Redirect the customer’s browser to This does not create a second merchant. It fails with
kycLink, or open it in an iframe in your app. Individuals complete KYC; businesses complete KYB. See Create a Merchant for both display options.The link is time-limited. If the customer did not finish, or the link expired, get a new one by calling POST /v2/merchants again with the existing merchantId, the same merchantType you used at creation, and callbackUrl:-5062 while the merchant’s verification is under review and with -5063 once it has been approved.Reaching your
callbackUrl only means the customer left the hosted flow. It does not mean they were approved. Always check the status in the next step.3
Check the merchant status
Call List Merchants (
GET /v2/merchants) and read status and rejectReason. Pass status=-1: without it the list returns only approved merchants. Filter with email or merchantName to find one merchant.There is no webhook for merchant verification. Poll at a modest interval, for example every few minutes while the customer is onboarding and less often after that.
4
Activate currency accounts
For each currency the customer needs, call Handle the returned
POST /v2/merchant/accounts with merchantId, fiat and trench (the channel name), plus the channel’s fieldList. The request differs by merchant type:- Individuals: Activate Individual
- Businesses: Activate Business
status:Then poll
GET /v2/merchant/accounts?merchantId=100001 until the channel shows status: 2. Each record also returns the channel’s paymentId, which you need for virtual accounts, payouts and orders.Some channels have extra requirements. BRL Pix - Woovi needs a liveness check first for individuals (Get Woovi Liveness URL) and full company and UBO data for businesses. Documents must be uploaded with Upload File. See Activate a Merchant Account for every channel.Common rejections: -5073 (the merchant has not passed KYC yet), -5074 (already active), -5062 (activation already pending), -5079 (no activation permission for this channel), -4010 (a required fieldList field is missing or invalid).5
Optional: create virtual accounts
If the customer collects from many payers, give each payer its own deposit details with Create Virtual Accounts (
POST /v2/merchant/virtual/accounts). Send merchantId, fiat, the channel’s paymentId and an alias of letters and digits. Virtual accounts are available for MXN, ARS, BRL and COP, and the currency account must already be active.Read the deposit details with List Virtual Accounts. Deposits to a virtual account carry its alias as depositAlias. See Collect local payments with virtual accounts for the full collection flow.Use the merchant ID in every other call
ThemerchantId decides whose balance, limits and accounts a call uses. Send the customer’s MID, not your own, on every call you make for that customer:
Keep a one-to-one mapping between your customer ID and the VelaFi MID, and never let a customer-supplied value choose the MID.
Webhooks to handle
Merchant verification and channel activation have no webhook. PollGET /v2/merchants and GET /v2/merchant/accounts as described above.
Webhooks are registered per VelaFi account, not per merchant: one registration per event type receives events for all of your merchants. Order, funding, crypto withdrawal and stablecoin payment events carry a merchantId, so route them by it. For events without one, look up the record by its ID. See Webhook Setup.
Handle failures
- Verification rejected (
status: 3). ShowrejectReasonto your customer, then request a new link with the samemerchantIdandmerchantType. - Customer abandons the flow (
status: 4). Send a reminder with a fresh link. Do not create a new merchant; the name and email are already taken by the first one. - Activation failed (
status: 3). ReadfailReasonin the activation response or in List Merchant Accounts. Fix thefieldListdata or contact VelaFi. - Activation pending for a long time. Pending channels depend on the provider. Keep polling and contact VelaFi if the channel does not become active.
- Timeouts and outcome-unknown errors (
-1001,-1006,-1007). The merchant or channel may have been created. Check with List Merchants or List Merchant Accounts before you call again. See Error Codes.
Reconcile
GET /v2/merchantswithstatus=-1is the source of truth for verification status and for each merchant’s daily and monthly limit usage.GET /v2/merchant/accountsis the source of truth for which channels are active, theirpaymentId, balance, and monthly buy/sell limits.
Test in the sandbox
Your sandbox account comes with pre-configured test merchants, and no real KYC/KYB takes place in the sandbox. Use those merchants to test activation results, virtual accounts and the payment flows that follow. Write your status handling against every status code in the tables above, because you cannot make a real reviewer approve or reject a sandbox merchant. See Sandbox.Go-live checklist
- Store
merchantIdas soon asPOST /v2/merchantsreturns, and map it one-to-one to your customer. - Handle every merchant status (
1,2,3,4) and every activation status (0to4), includingverifyLinkredirects. - Poll with
status=-1, so merchants that are not approved yet are not missing from your results. - Re-request expired links with the existing
merchantIdandmerchantTypeinstead of creating a duplicate merchant. - Wait for the channel to show
status: 2before you create virtual accounts or send payments for that currency. - Pass the customer’s MID on every downstream call, and route webhook events by
merchantId.