The route is where the durable configuration lives. It fixes the beneficiary, the rail, the crypto asset and the fiat currency — so an actual pay-out request carries almost nothing: a route, an amount, and an idempotency key.
Setup
1
Give the recipient party a PAYOUT_RECIPIENT role
Before anything else, the party who owns the destination bank account needs an
ACTIVE
PAYOUT_RECIPIENT role on the
paying account, with cleared KYC/KYB.A party can hold PAYOUT_RECIPIENT and ACCOUNT_HOLDER on the same account — that’s the
self-payout case, where a user withdraws to their own bank account.This is the “recipient gate”. It’s checked when you create a route and again when you request each pay-out, so revoking the role stops future pay-outs immediately.
2
Register the beneficiary bank account
POST /parties/{partyId}/payout-bank-accountsaccountNumberLast4. The ABA routing number is a public bank identifier, so it comes back in full.The account starts PENDING and becomes ACTIVE once activated for pay-outs.3
Create a route
POST /accounts/{accountId}/payout-routesPENDING and moves REGISTERING → ACTIVE as registration completes, or
REJECTED on terminal failure.It can also stop at AWAITING_OWNERSHIP_PROOF, which is the one status that needs something
from you — see Proving you control the source wallet.Proving you control the source wallet
A route can pause atAWAITING_OWNERSHIP_PROOF. That happens when the destination requires a Travel-Rule proof that you control the wallet the funds leave from, and that wallet is self-custody. Venly holds no key for it, so only its owner can sign.
Registration doesn’t fail — it waits. Nothing else moves until you complete this step.
1
Ask for the message
POST /accounts/{accountId}/payout-routes/{routeId}/ownership-proof/prepare — no body needed.Nothing is stored and there’s no expiry token, so this is safe to repeat.2
Have the owner sign it verbatim
3
Submit it
POST .../ownership-proof/complete with message and signature. The route leaves AWAITING_OWNERSHIP_PROOF and registration resumes.A
200 from complete means the proof was accepted, not that the route is ready. It continues to ACTIVE asynchronously — poll the route or register a webhook. Only an ACTIVE route has a depositAddress.Requesting a pay-out (PULL)
With anACTIVE route, a pay-out is a small request:
fundingMode: PULL.
A 201 is not success
This is the single most important thing to get right in a pay-out integration.
So don’t treat the 201 as “money sent”. Track the real outcome by
registering a webhook or polling
Get a payout.
The pay-out lifecycle
COMPLETED is not the end of the story. A fiat leg can still bounce afterwards — a closed account, a
name mismatch at the receiving bank — moving the pay-out to RETURNED. If you release goods or credit
a ledger on COMPLETED, handle RETURNED as a reversal.settledFiatAmount is the fiat the provider actually paid, and is null until COMPLETED. Expect it
to be lower than the crypto you sent, net of fees — reconcile against this field rather than assuming
a 1:1 conversion.
PUSH pay-outs
Not every pay-out starts with an API call. On a self-custody account, a customer can send crypto to the route’sdepositAddress themselves. Venly observes that deposit and creates the pay-out for
you, with fundingMode: PUSH.
depositAddress is exposed only for an ACTIVE route on a SELF_CUSTODY account — read it from
List payout routes and show it to your
customer.
Both kinds appear in the same read endpoints, so
List payouts gives you the complete picture.
Filter on fundingMode if you need to treat them differently.
Idempotency
idempotencyKey is required and must be unique per company across all idempotent endpoints — not
just across pay-outs. The full replay behaviour is in
Idempotency.
Common errors
Next steps
Webhooks
Get pay-out status changes pushed to you instead of polling.
Permits & allowances
The permit that makes PULL pay-outs possible on self-custody wallets.
Virtual bank accounts
The pay-in direction: fiat in, crypto out.
Idempotency
Safe retries across every write endpoint.

