Payments
Payment links
The simplest way to get paid online: create a link for an amount, share it anywhere, and BaxPay hosts the payment page.
A payment link is a single-use charge with a hosted page. No invoice, no regulation-specific fields, no checkout integration — one API call, one URL. The payer pays by card (no BaxPay account needed) or with Pay with BaxPay (they sign in to their own account; SCA included).
If the money you're collecting belongs to a regulated French e-invoice, use invoice payment links instead — same rails, but the invoice's legal lifecycle updates itself.
Create a link
/payment-linksRequires an Idempotency-Key header.
curl -X POST https://sandbox-api.baxpay.com/v1/payment-links \
-H "Authorization: Bearer bx_test_9f2a4c8e1d…" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"description": "Coaching session — July",
"amount": 120.50,
"reference": "COACH-2026-118",
"businessWide": true
}'const res = await fetch('https://sandbox-api.baxpay.com/v1/payment-links', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.BAXPAY_API_KEY}`,
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body: JSON.stringify({
description: 'Coaching session — July',
amount: 120.5,
reference: 'COACH-2026-118',
businessWide: true,
}),
});
const body = await res.json();
if (!res.ok) throw new Error(JSON.stringify(body));
console.log(JSON.stringify(body, null, 2)); // share body.data.url{
"success": true,
"data": {
"id": "1c9f4a2e-…",
"token": "plk_4f1f0c4c4e1a…",
"url": "https://pay.baxpay.com/plk_4f1f0c4c4e1a…",
"description": "Coaching session — July",
"reference": "COACH-2026-118",
"amount": 120.5,
"feeAmount": 3.62,
"chargeAmount": 120.5,
"netAmount": 116.88,
"currency": "EUR",
"feePayer": "RECEIVER",
"mode": "ONE_TIME",
"status": "OPEN",
"storeId": null,
"expiresAt": null,
"livemode": false,
"createdAt": "2026-07-16T14:02:10.000Z"
}
}Amounts are decimal euros (120.50, at most 2 decimals, at least 0.01).
Where the money is booked (one is required):
| Field | Meaning |
|---|---|
storeId | One of your locations; the payment is reported under it |
businessWide: true | The business as a whole, no location |
Optional fields:
| Field | Meaning |
|---|---|
currency | EUR (default), GBP, CHF or USD |
reference | Your own id, up to 100 characters, echoed in the webhook |
clientId | A client from your book. Optional for one-time links; required for recurring ones, and the client needs an email |
expiresAt | ISO time after which the link stops accepting payment |
feePayer | RECEIVER (default): you absorb BaxPay's fee. SENDER: the payer pays amount + fee. See chargeAmount / netAmount in the response |
mode, interval | ONE_TIME (default) or RECURRING with interval WEEKLY, MONTHLY or YEARLY |
items | Catalog lines (productId, quantity, optional variantId, modifierIds), so stock and reporting follow the sale |
payerBusinessProfileId | Ask another BaxPay business to pay: the request appears in its app |
Recurring links set up the subscription when the payer opens checkout. After the first payment the
link status becomes ACTIVE (subscription running), and each later cycle is charged and recorded
automatically.
When a link is tied to a client with an email, BaxPay emails the link on create. Unpaid links also get reminder emails on days 1, 3 and 7.
Manage links
/payment-links?status=OPEN&page=1&limit=25list (see pagination)/payment-links/{id}retrieve/payment-links/{id}/cancelcancel an open linkcurl "https://sandbox-api.baxpay.com/v1/payment-links?status=OPEN&limit=25" \
-H "Authorization: Bearer $BAXPAY_API_KEY"{
"success": true,
"data": {
"data": [{ "id": "1c9f4a2e-…", "status": "OPEN", "amount": 120.5, "url": "https://pay.baxpay.com/plk_…" }],
"total": 1,
"page": 1,
"limit": 25
}
}Filter with status and storeId; lists follow the pagination rules.
curl -X POST https://sandbox-api.baxpay.com/v1/payment-links/1c9f4a2e-…/cancel \
-H "Authorization: Bearer $BAXPAY_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"{ "success": true, "data": { "id": "1c9f4a2e-…", "status": "CANCELED" } }Statuses: OPEN → PAID (one-time) or ACTIVE (recurring), or CANCELED / EXPIRED.
Canceling an ACTIVE recurring link also cancels the subscription. A paid one-time link can't be
canceled, and a canceled or expired link can't be paid.
Resending the link email is a dashboard action (Payment links → Resend); it isn't available with an API key.
What the payer sees
url opens a hosted page showing your business name, the description, and the amount — nothing
else. The page wears your brand: set your logo and colors once in the Business dashboard
(Payment links → Personnalisation; the logo comes from your brand settings) and every hosted
page — payment links and invoice pay pages alike — uses them. Two methods:
- Card — guest payment, processed by the configured acquirer. In live mode without an
acquirer contracted the method is hidden and the endpoint answers
503; BaxPay never fakes a charge. - Pay with BaxPay — the payer signs in to their own BaxPay account and pays with their wallet, card or bank account, Strong Customer Authentication included. BaxPay verifies the captured transaction matches this exact link (merchant, amount) before anything flips to paid.
What happens on payment
- The link flips to
PAID(one-time) orACTIVE(recurring) atomically — a double payment race is structurally impossible. - A
Transactionis recorded for reconciliation (PLK-…reference;PLK-TEST-…in sandbox). - Your webhooks receive
payment_link.paid:
{
"id": "f017738f-…",
"type": "payment_link.paid",
"livemode": true,
"data": {
"paymentLinkId": "1c9f4a2e-…",
"description": "Coaching session — July",
"reference": "COACH-2026-118",
"clientId": null,
"amount": 120.5,
"currency": "EUR",
"mode": "ONE_TIME",
"interval": null,
"method": "CARD_NOT_PRESENT",
"transactionRef": "be294a82-…"
},
"createdAt": "2026-07-16T14:03:21.530Z"
}transactionRef is the id of the recorded transaction. method says how the payer paid:
CARD_NOT_PRESENT (guest card), BAXPAY_ACCOUNT (their BaxPay account), or a wallet such as
APPLE_PAY, GOOGLE_PAY or REVOLUT_PAY.
Sandbox
With a bx_test_ key everything works end to end, and nothing reaches a card network or a bank. Pay with
a test card: 4242 4242 4242 4242 succeeds, 4000 0000 0000 0002 always
declines, and others play insufficient funds, fraud or 3D Secure. The test pay page can fill one
in for you, and offers the business's other active methods (iDEAL, Apple Pay, …) as
simulated payments. Test payments only fire test-mode webhooks.
The quickstart walks this exact flow.
curl -X POST https://sandbox-api.baxpay.com/v1/pay/link/plk_4f1f0c4c4e1a…/card \
-H "Content-Type: application/json" \
-d '{ "number": "4000 0000 0000 0002", "expMonth": 12, "expYear": 2030, "cvc": "123", "holder": "MARIE DUPONT" }'{ "statusCode": 400, "message": "Your card was declined.", "error": "Bad Request", "code": "card_declined" }