Skip to main content
This guide walks the Finance API end-to-end — from creating your first party to settling a transfer. Every step uses real request and response shapes. Run it against staging and you’ll have a working integration.
Base URL (staging): https://api-staging.venlyfinance.com/v1 Auth: OAuth2 Bearer token in the Authorization header. Tokens expire after 5 minutes — see the Authentication guide.

What you’ll build

  1. Onboard a party (your customer) — created ACTIVE immediately
  2. Open an account for them (its custodial wallet is provisioned automatically)
  3. Get the party verified through the API
  4. Have the customer accept the partner terms on a hosted page
  5. Issue a EUR IBAN so they can fund via SEPA
  6. Send an outbound transfer
The big gate to design around: an account is created unverified (kycStatus: VERIFICATION_PENDING) and its party must complete verification before it can move money. A party’s status is ACTIVE right away, which is not the same as being verified. See Account verification.

Prerequisites

1

Staging credentials

A client_id and client_secret from your Venly contact. Staging calls don’t move real money.
2

An HTTP client

All examples use curl. Postman, HTTPie, or any SDK works equally well.
3

A UUID generator

Money-moving endpoints require an idempotencyKey (UUID v4) — uuidgen, [guid]::NewGuid(), or crypto.randomUUID().

Step 1 — Authenticate

Exchange your client credentials for a Bearer token. Every subsequent call needs it in the Authorization header.
Response
Cache the token. Refresh on 401 Unauthorized or a few seconds before expires_in elapses — don’t request a new token on every call.

Step 2 — Create a party

A party is the person or organisation behind an account — INDIVIDUAL (natural person) or ORGANISATION (company). It’s created ACTIVE immediately — creating a party does not verify it, and status: ACTIVE is not a verification result. Verification happens later, in Step 4.
Response (201)
For an organisation, swap the body:

Step 3 — Open an account

An account holds the wallet, IBANs, and transfer history. Link the party from Step 2 with partyId (it becomes the ACCOUNT_HOLDER). The custodial wallet is provisioned automatically — there’s no separate “create wallet” call. The only difference between company types is the wallet address:
  • Venly-managed — Venly creates and holds the wallet. Omit address.
  • Self-custody — the customer controls the wallet. Send their address (required).
Response (201)
Set a meaningful externalId — your own user/customer ID. It doubles as a receiver shortcut in transfers (receiverExternalId), so you don’t have to look up the Venly UUID every time.

Add a second account holder (optional)


Step 4 — Get the account verified

The account is created with kycStatus: VERIFICATION_PENDING. Mint a hosted link with POST /parties/{partyId}/verification and hand it to the end-user, or forward an existing Sumsub verification at account creation. The verdict arrives asynchronously and kycStatus becomes VERIFIED. See Onboarding & Verification. Poll the account until it flips:
Response (200)
Until then, creating IBANs, transfers, and pay-in sessions all fail with a KYC error — the exact code and HTTP status vary by operation (e.g. 400 kyc-not-verified for IBANs, 422 kyc-required for pay-in sessions). See Account verification for the full list of what’s gated.

Step 5 — Have the customer accept the partner terms

Verification proves who your customer is. It does not cover the terms our partners require them to accept — and they must accept those themselves, on a page we hand you a link to. Until they do, issuing an IBAN in the next step is blocked. Read the party’s consent state:
Response (200)
REQUIRED means hand consentUrl to your customer. You cannot complete this for them. Once they accept, the status becomes ACCEPTED and onboarding continues.
You can get ahead of this instead of waiting for it to block you: POST /parties/{partyId}/partner-terms/link mints a link immediately, so the customer accepts every partner’s terms before any of their data is sent to a partner. Collecting consent during your own onboarding is usually the better experience.
ACCEPTED is not permanent. Adding a partner, or a partner publishing a new terms version, moves the party back to REQUIRED. Re-read it rather than recording it once. See Partner-terms consent.

Step 6 — View the wallet

The wallet was created with the account. Read it (and its balances) any time:
Response (200)
Balance amounts are decimal strings. type is VENLY_MANAGED or SELF_CUSTODY depending on your company (this example shows self-custody). A wallet has no status field — readiness shows as amlStatus: APPROVED (Venly-managed) or a CONFIRMED permit (self-custody).
Venly-managed: nothing to do here — the wallet is ready once its amlStatus is APPROVED (handled during onboarding).Self-custody: before this wallet can send funds, the customer signs a one-time permit so Venly can move their tokens (do this once after the account is set up). The wallet is ready once that permit is CONFIRMED.

Step 7 — Issue a virtual bank account (IBAN)

Once the account is VERIFIED and its partner-terms consent is ACCEPTED, attach an IBAN so it can be funded via SEPA. Incoming euros are auto-converted to the targetCryptocurrency and credited to the wallet — read GET /supported-assets for the assets your tenant can settle in.
Response (201)
Surface the referenceCode to your end user when they initiate a SEPA transfer — it’s what links the incoming wire to this account. Without it, settlement falls back to manual reconciliation.

Step 8 — Fund the account

Option A — SEPA transfer to the IBAN

The customer sends EUR from their bank to the IBAN from Step 7, including the referenceCode in the payment reference. On receipt, Venly converts EUR → the target crypto and credits the wallet.

Option B — Hosted fiat-to-crypto pay-in

Create a pay-in session and redirect the customer to the returned paymentUrl.
The response carries a paymentUrl. When the customer completes payment, the wallet is credited and your callbackUrl is invoked.

Step 9 — Send a transfer

Transfers move funds between two Venly accounts — identify the receiver by receiverAccountId or by your own receiverExternalId. Both the sender and the receiver accounts must be VERIFIED; sending to an unverified receiver fails with 422 receiver-kyc-not-verified.

Crypto transfer

Response (201)

Fiat transfer

A fiat-denominated transfer settles in the underlying stablecoin and returns a fiatOrigin block with the original currency and exchange rate.
Self-custody senders also need a CONFIRMED permit and a granted allowance before a transfer succeeds — see Approving transfers without gas. Venly-managed accounts don’t.

Step 10 — Track the transfer

Crypto and fiat transfers usually complete synchronously, but you can always fetch the latest state:
List all transfers for an account with GET /accounts/{accountId}/transfers plus pagination parameters. Retrying a create with the same idempotencyKey returns the original transfer — no double-spend.

Common pitfalls

Verification is not the last gate. Check the party’s partner-terms consent — if status is REQUIRED, your customer still has to accept on the hosted page, and no amount of retrying will clear it. Hand them the consentUrl. This one is easy to mistake for a KYC problem because the account looks fully verified.
The account is still VERIFICATION_PENDING. Its party must complete verification first — poll GET /accounts/{id} until kycStatus is VERIFIED. (The party’s status being ACTIVE is not enough.)
The customer hasn’t signed the token permit yet, so Venly has no allowance to move funds. Run the permit flow once, then retry.
Self-custody accounts must include the customer’s wallet address on creation. Venly-managed accounts must not.
The receiverAccountId / receiverExternalId doesn’t resolve to an account in your company. Transfers are account-to-account — both sides must be Venly accounts you own.
Tokens last 5 minutes. Catch 401, refresh, and retry the original call. Don’t pre-authenticate every request — cache the token.

Next steps

Getting started

The condensed party → account → verify → IBAN flow.

Browse the API reference

Every endpoint, field, and error code.

Permits & allowances

Gasless token approvals for self-custody accounts.

Contact support

Stuck? Get in touch with your accountId and the failing request.