Payment links
Take a payment with no integration — create a link, share it, get paid
Overview
A payment link is a shareable URL that opens the hosted payment page. It needs no code on your side beyond one API call (or a click in the dashboard's Payment Links page): send it by email, chat or invoice, and the customer pays on our hosted page (your PCI scope stays SAQ A).
curl -X POST https://api.settleflow.io/v2/payment-links \
-H "X-Api-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"amount": 4999,
"currency": "EUR",
"description": "Invoice #1234",
"reference": "inv_1234",
"customer": { "first_name": "Alice", "last_name": "Martin", "email": "alice@example.com" }
}'The response contains the url to share. Payments made through a link land in
GET /v2/transactions like any other payment, and trigger your webhooks.
Behaviour
| Option | Effect |
|---|---|
amount omitted | Open amount — the customer enters the amount on the payment page |
reusable: false (default) | Single-use — after one successful payment the link becomes completed and further attempts are rejected (409) |
reusable: true | The link can be paid any number of times until disabled or expired |
expires_at | The link stops accepting payments after this time (expired). Defaults to 30 days |
description | Shown to the payer on the payment page — often their only clue about what they are buying |
reference | Your own reference. Generated if omitted, and echoed on every payment the link mints |
customer | Whoever you already know about the payer. See below |
customer.country | Also sets the payment's country, used for routing and risk. Defaults to FR when omitted |
Prefilling the customer
Anything you send under customer is shown to the payer as text, not as an
editable field, and they are only asked for what you left out:
{ "customer": { "first_name": "Alice", "last_name": "Martin", "email": "alice@example.com" } }Send nothing and the page asks for all of it. The email is always required of the payer — it is where the receipt goes — so either you supply it or they type it. The street address, city and postcode are always the payer's to fill in; we do not ask you for those here.
Fields you supply cannot be changed from the payment page, and not merely because the input is read-only: the server refuses to overwrite them.
customer.country
The one field worth setting even when you are happy to let the payer type the rest, because it does more than prefill:
{ "customer": { "email": "alice@example.com", "country": "BE" } }It is the payer's billing country (ISO 3166-1 alpha-2), and it sets the
payment's own country — which we use to route the payment and to evaluate your
risk rules. Omit it and that defaults to FR, whoever is paying. If you know
where your customer is, this is the place to say so.
Fields your account requires
If your account is configured to require customer fields (address, city, postcode, country, name, phone…), the payment page asks the payer for them and refuses the payment if they are missing — the same rule the direct API applies. Supply them on the link and the payer sees them read-only; leave them out and the payer has to fill them in before they can pay.
What the customer can pay with
A link opens the hosted payment page, so it offers whatever your account is configured for — the card form, plus any wallet you have enabled. See what the customer can pay with.
Lifecycle
active → (completed when a single-use link is paid) · (disabled after
POST /v2/payment-links/{id}/disable, idempotent) · (expired past expires_at).
Only a payment completes a link — not a page view. A customer who opens a
single-use link, hesitates, reloads or comes back from their banking app lands on
the same payment session and can still pay; a declined card does not burn the
link either. So the link stays active until one payment actually succeeds.
That session is payable for as long as the link is. A hosted checkout session
normally expires 24 hours after it is created, but one minted by a single-use link
takes the link's own expires_at instead — a link you send with a 30-day window
is payable for all 30 days, not just the first day after the customer first opened
it. Reusable links mint one 24-hour session per open, since each open is a
different customer.
Disabling never deletes anything: the link and its payments remain visible in
GET /v2/payment-links. It does close any payment the link had opened and nobody
submitted — those move to expired, because a link you have taken down should not
leave payable sessions behind. A payment already submitted is untouched: it is in
flight at the provider and will resolve on its own.
Notes
- The URL contains only an opaque link id — no amount, no customer data, nothing to tamper with.
- Merchant users can create and manage links without the API from the dashboard's
Payment Links page (virtual terminal), governed by the
payment-links:*permissions.