Skip to content
BaxPayDevelopers

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.

POST/payment-links

Requires 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
  }'
{
  "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):

FieldMeaning
storeIdOne of your locations; the payment is reported under it
businessWide: trueThe business as a whole, no location

Optional fields:

FieldMeaning
currencyEUR (default), GBP, CHF or USD
referenceYour own id, up to 100 characters, echoed in the webhook
clientIdA client from your book. Optional for one-time links; required for recurring ones, and the client needs an email
expiresAtISO time after which the link stops accepting payment
feePayerRECEIVER (default): you absorb BaxPay's fee. SENDER: the payer pays amount + fee. See chargeAmount / netAmount in the response
mode, intervalONE_TIME (default) or RECURRING with interval WEEKLY, MONTHLY or YEARLY
itemsCatalog lines (productId, quantity, optional variantId, modifierIds), so stock and reporting follow the sale
payerBusinessProfileIdAsk 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.

GET/payment-links?status=OPEN&page=1&limit=25list (see pagination)
GET/payment-links/{id}retrieve
POST/payment-links/{id}/cancelcancel an open link
curl "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

  1. The link flips to PAID (one-time) or ACTIVE (recurring) atomically — a double payment race is structurally impossible.
  2. A Transaction is recorded for reconciliation (PLK-… reference; PLK-TEST-… in sandbox).
  3. 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" }