Skip to content
BaxPayDevelopers

Payments

Invoice payment links

Turn any emitted e-invoice into money in the bank: one link, a hosted pay page, card or "Pay with BaxPay" — and the lifecycle plus e-reporting update themselves.

A payment link is an unguessable URL (https://pay.baxpay.com/pl_…) pointing to a hosted page that shows the payer only what they need — seller, invoice number, due date, amount — and lets them pay. No BaxPay account is required for card payment.

POST/einvoices/{id}/payment-linkIdempotency-Key required

Works on any sent OUTBOUND invoice that isn't paid yet; calling it again returns the same link. In sandbox, first emit an invoice to collect:

INVOICE=$(curl -s -X POST https://sandbox-api.baxpay.com/v1/einvoices \
  -H "Authorization: Bearer $BAXPAY_API_KEY" -H "Idempotency-Key: $(uuidgen)" -H "Content-Type: application/json" \
  -d '{
    "invoiceNumber": "FA-2026-0050", "issueDate": "2026-09-01", "dueDate": "2026-09-30",
    "buyerName": "ACME SAS", "buyerSiren": "552100554", "buyerVatId": "FR96552100554",
    "buyerAddress": { "line1": "12 rue de la Paix", "city": "Paris", "postalCode": "75002", "countryCode": "FR" },
    "lines": [{ "lineNumber": 1, "description": "Conseil", "quantity": 3, "unitCode": "DAY", "unitPrice": 650, "vatRate": 20 }]
  }' | jq -r .data.id)
 
curl -X POST "https://sandbox-api.baxpay.com/v1/einvoices/$INVOICE/send" \
  -H "Authorization: Bearer $BAXPAY_API_KEY" -H "Idempotency-Key: $(uuidgen)"

Then create its link:

curl -X POST https://sandbox-api.baxpay.com/v1/einvoices/0d1f9b1e-…/payment-link \
  -H "Authorization: Bearer $BAXPAY_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
{
  "success": true,
  "data": {
    "token": "pl_4f1f0c4c4e1a…",
    "url": "https://pay.baxpay.com/pl_4f1f0c4c4e1a…"
  }
}

Share the URL however you like: it is also the natural thing to print on the PDF or paste into a payment-terms email.

What the payer sees

The hosted page offers up to two methods:

  • Card — a guest card form, processed by the configured acquirer. If no acquirer is contracted on your live environment the method is hidden and the API answers 503 — BaxPay never fakes a live charge.
  • Pay with BaxPay — the payer signs in to their own BaxPay account and pays with their wallet, card or account. Strong Customer Authentication (SCA) applies exactly as in the standard payments flow; BaxPay then verifies the captured transaction matches the invoice (right seller, right amount) before marking anything paid.

What happens on success

  1. The invoice is stamped paid (paidAt, method, transaction reference) — atomically, so a double payment race is impossible.
  2. The lifecycle advances PAYMENT_TRANSMITTED → COLLECTED (encaissée — a mandatory status of the reform). BaxPay may assert it because it processed the encaissement itself.
  3. The COLLECTED event flows into your PAYMENT_DATA e-reporting.
  4. Your webhooks receive einvoice.paid:
{
  "id": "5d0c4e2a-…",
  "type": "einvoice.paid",
  "livemode": true,
  "data": {
    "invoiceId": "0d1f9b1e-…",
    "invoiceNumber": "FA-2026-0042",
    "amount": 2340,
    "currency": "EUR",
    "method": "CARD_NOT_PRESENT",
    "transactionRef": "a7c9…"
  },
  "createdAt": "2026-09-12T09:14:03.000Z"
}

method names the card or wallet method the payer used.

Public endpoints behind the page

You normally never call these — the hosted page does — but they are public and documented for completeness:

GET/pay/einvoice/{token}
curl https://sandbox-api.baxpay.com/v1/pay/einvoice/pl_4f1f0c4c4e1a…
{
  "success": true,
  "data": {
    "sellerName": "…",
    "invoiceNumber": "FA-2026-0001",
    "amountDue": 2340,
    "currency": "EUR",
    "status": "PAYABLE",
    "livemode": false,
    "methods": {}
  }
}

The payer-safe summary: seller name, invoice number, dates, amounts, lines, the payment methods on offer, and whether it can be paid (status: PAYABLE, PAID or NOT_PAYABLE). Never artifacts or buyer data.

POST/pay/einvoice/{token}/card

Guest card charge, tightly rate-limited. When the merchant's card payments go through BaxPay's hosted checkout it answers 400, and the page takes the payer through that checkout instead.

POST/pay/einvoice/{token}/confirm-baxpay

Called by BaxPay's own hosted page on behalf of the signed-in payer — never by your integration. It links the payer's captured transaction to the invoice after verifying merchant, amount and ownership.

Sandbox

On a test invoice the card form takes the test cards: 4242 4242 4242 4242 succeeds and 4000 0000 0000 0002 always declines, so you can test both paths. Nothing reaches a card network, a bank or the e-invoicing network:

curl -X POST https://sandbox-api.baxpay.com/v1/pay/einvoice/pl_4f1f0c4c4e1a…/card \
  -H "Content-Type: application/json" \
  -d '{ "number": "4000 0000 0000 0002", "expMonth": 12, "expYear": 2030, "cvc": "123", "holder": "ACME SAS" }'
curl -X POST https://sandbox-api.baxpay.com/v1/pay/einvoice/pl_4f1f0c4c4e1a…/card \
  -H "Content-Type: application/json" \
  -d '{ "number": "4242 4242 4242 4242", "expMonth": 12, "expYear": 2030, "cvc": "123", "holder": "ACME SAS" }'
{ "success": true, "data": { "status": "PAID", "maskedInstrument": "•••• 4242" } }

Test payments fire test-mode webhooks only, and the invoice moves to COLLECTED.