SettleFlow API

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

OptionEffect
amount omittedOpen 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: trueThe link can be paid any number of times until disabled or expired
expires_atThe link stops accepting payments after this time (expired). Defaults to 30 days
descriptionShown to the payer on the payment page — often their only clue about what they are buying
referenceYour own reference. Generated if omitted, and echoed on every payment the link mints
customerWhoever you already know about the payer. See below
customer.countryAlso 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.

On this page