Skip to main content
A payment session is how you collect money from one of your customers. Every incoming payment belongs to exactly one session: you create it with POST /v1/checkout/hosted, redirect your customer to the url it returns, and StableMint tells you by webhook what happened.
Accepting payments is enabled per partner, and is off by default. It is not provisioned automatically with your account, so this flow does not work out of the box — until it is switched on for you, POST /v1/checkout/hosted answers 403 with code: feature_not_enabled, however correct your credentials are. Request it from your StableMint contact before building against this page.
Every example on this page is a signed request. $SIGNATURE is computed per request over a canonical string — see Authentication. Bearer tokens are not accepted.

How a session runs

1

You create the session

Send the amount, the currency, who the customer is, and the four URLs you want them returned to. You get back a url, a reference and an expiresAt.
2

Your customer pays

Redirect them to url. The checkout is hosted by StableMint — it handles the payment method, the bank redirect and the result screens, so none of that lives in your application.
3

They come back to you

The customer lands on whichever of your URLs matches the outcome: success, exit, or error.
4

You act on the webhook

The redirect is not the source of truth. Credit the customer when the deposit event arrives — see Event types.
Never treat a redirect to your successUrl as proof of payment. A browser redirect is under the customer’s control and says only that they reached the end of the flow. The money is confirmed by partner.customer.deposit.completed, and that is the event to act on.

Create a session

Required fields

string
required
Your own identifier for the customer paying. Reuse it across sessions to keep one identity — see You identify the customer.
string
required
The customer’s email address.
string
required
ISO 3166-1 alpha-2, e.g. FI.
string
required
The currency to collect, e.g. EUR.
number
required
The amount to collect.
string
required
Where the customer lands after paying. Proof of payment is the webhook, not this redirect.
string
required
Where the customer lands if they abandon the flow.
string
required
Where the customer lands if the payment fails.
string
required
Your support page, linked from the checkout.

Optional fields

string
Retrying with the same key returns the original session instead of creating a second one — see Idempotency.
string
Your own reference. Echoed back on the webhook payloads for this payment.
object
Arbitrary JSON carried through to the webhook payloads untouched.
string
Selects which saved checkout configuration to apply — theming, labels and behaviour. Set these up in the dashboard. Omit it to use your default.
object
Optional KYC details: fullName, citizenshipCountryCode, residenceAddress, dateOfBirth (YYYY-MM-DD), placeOfBirth, gender, mobilePhone, personalIdentificationNumber. Every subfield is optional.

Response

Store reference against your order before you redirect. It is how you match the deposit events to the thing the customer was buying.

What happens next

The customer pays, returns to one of your URLs, and the deposit events arrive: partner.customer.deposit.initiated, then accepted, then completed — or expired if the session is never funded. Credit your customer on completed. See Event types for the payloads and Receiving webhooks for registering an endpoint and verifying signatures.

You identify the customer

You own the customer relationship; StableMint never contacts them. That means every session carries your own identification of who is paying — userId, userEmail and userCountryCode — and the payment is attributed to that customer. Pass the same userId each time and the customer’s payments accumulate under one identity, which is what makes their transaction history and balance meaningful. See Customers. You may optionally send KYC details with the session. Whether you need to depends on your configuration — if you are unsure, you do not need to send them.

Sessions expire

expiresAt is a Unix timestamp in seconds. After it passes, the url no longer starts a payment and the customer must be sent through a fresh session. A session that is never funded ends as partner.customer.deposit.expired. That event is terminal — it is your signal to release anything you were holding against the pending payment.

Idempotency

Send an idempotencyKey and a retried create returns the original session instead of opening a second one. Generate it from something stable in your own system — an order id — rather than a random value that changes on retry.