Skip to main content
POST
Create a fiat-to-crypto payment session
Coming soon — not yet available. Hosted pay-in sessions are documented ahead of launch. Until they’re enabled for your company, creating one is refused with 400 no-suitable-provider. To receive fiat today, use a virtual bank account.
Requires scope: manage:pay-in-sessions — see Required scopes. Creates a hosted pay-in session. Redirect the payer to the returned paymentUrl; on completion the fiat is converted to the chosen cryptocurrency and credited to the account’s wallet. Provide a callbackUrl and a unique idempotencyKey (safe retries).
The account must be verified before a pay-in session can be created. See Account verification.
Retries. A replay with the same idempotencyKey and an identical body returns the original session — never a second payment link. Change anything and it’s refused with 422 idempotency-conflict: the amount and currency decide what the link collects, so a corrected value is a new request under a new key. Bodies are compared by value — "5", "5.0" and "5.00" are the same inAmount, and currency codes ignore case. A failed attempt (409 vba-not-ready, 502, 503) uses the key up, so retry those with a new one. A session is an initiation-only record: it ends at PAYMENT_RECEIVED, and the conversion and crypto credit are a separate pay-in signalled by PAY_IN_SETTLED. Read it back with Get a pay-in session.

Errors

The codes this endpoint can return, in addition to the standard errors. Branch on code, never the message.

Authorizations

Headers

x-tenant-id
string<uuid>

Which tenant the request is scoped to, among those your token grants. Omit it when the token grants exactly one tenant; it is required when the token grants more than one. A supplied value must exactly match a tenant the token grants.

Absent when required, blank, malformed, or naming a tenant the token does not grant — each gets the same generic 403 forbidden, which reveals neither whether a tenant exists nor which ones you may use. Send the header once: a repeated header is rejected the same way.

Example:

"3fa85f64-5717-4562-b3fc-2c963f66afa6"

Path Parameters

accountId
string<uuid>
required

Unique account identifier

Body

application/json
inAmount
string
required

Fiat amount to pay in

Pattern: ^\d+(\.\d{1,2})?$
inCurrency
string
required

Fiat currency of the incoming payment (e.g. EUR)

Minimum string length: 1
outCryptocurrency
string
required

Cryptocurrency to convert the incoming fiat to (e.g. USDC)

Minimum string length: 1
callbackUrl
string
required

HTTPS URL to receive payment status callbacks

Pattern: ^https://.*
idempotencyKey
string<uuid>
required

Unique UUID key to prevent duplicate operations on retry

successRedirectUrl
string

URL to redirect the user to on successful payment (at most 2000 characters)

Maximum string length: 2000
failureRedirectUrl
string

URL to redirect the user to on failed payment (at most 2000 characters)

Maximum string length: 2000
externalRef
string

Optional external reference

Maximum string length: 255
metadata
object

Response

Payment session created

success
boolean

Indicates whether the request was successful

result
object