Payment links
A reusable link you can post anywhere; every payer who opens it gets an invoice of their own.
A payment link is a URL you share in a chat, an email or on social media. You create it once; each payer who opens it gets their own invoice, so payments never mix.
Creating one
{
"amount_type": "fixed",
"amount": "25.00",
"currency": "USD",
"description": "Workshop ticket",
"quantity_limit": 40
}amount_type:fixed(you setamount) orpayer_chosen(the payer types the amount, optionally betweenmin_amountandmax_amount; good for donations and tips). When you leave it out it isfixedif you gave anamount, otherwisepayer_chosen.quantity_limit: how many payers may pay, 1 to 1,000,000, ornullfor unlimited.expires_at: optional; after it the link stops creating invoices. It must be in the future.description(shown to payers),metadata(yours; copied to every invoice) andassets(default: yourdefault_assetsat the time each invoice is created) work as on invoices.
The response has an id (plink_…), a random, unguessable slug and a url. Payers open the URL
with your publishable key added: https://pay.example.com/?link=<slug>&key=cp_live_pk_….
What payers see
- The checkout reads the link (
GET /v1/checkout/links/{slug}) and lets the payer enter an amount if you allowed it. - It creates the payer's invoice (
POST /v1/checkout/links/{slug}/invoices). The invoice copies the link's description, assets and metadata, and itspayment_linkfield names the link: that is how you match payments to links in your webhooks. - The payer picks a network (
POST /v1/checkout/invoices/{id}/payment_option), and only then does the invoice get a deposit address. Opening a public link therefore uses none of your addresses. A payer who does not pick a network within 30 minutes finds the invoice expired.
From there the checkout runs exactly as for any invoice.
Status and quantity
| Status | When |
|---|---|
active | Payers can open it. |
inactive | You switched it off (active: false). Switch it back on any time. |
expired | expires_at has passed. |
sold_out | quantity_used reached quantity_limit. |
Creating a payer's invoice reserves a unit, in the same step, so concurrent payers can never pay for
more than quantity_limit. While the invoice is open and unpaid the unit counts in quantity_reserved;
once a payment is seen it moves to quantity_used; if the invoice expires or is cancelled, it comes back.
While every remaining unit is reserved, a new payer gets 409 payment_link_fully_reserved.
invoices_created counts every invoice.
To keep a busy public link from piling up, a link holds at most 50 open unpaid invoices, and your account
at most 200 across all links. Beyond that, new payers get 409 payment_link_busy until earlier invoices
are paid or expire.
Changing and switching off
POST /v1/payment_links/{id} changes a link (omitted fields stay, null clears). Changes apply to
invoices created afterwards; invoices that already exist keep their terms. There is no delete: switch a
link off with {"active": false}.
Each change sends a webhook: payment_link.created, payment_link.updated or
payment_link.deactivated (with invoice_id: null). Every payer's invoice sends the normal
invoice.* events.