Appearance
Payment links
A payment link is a URL that collects a payment. Fill a small form in the dashboard, get https://…/pay/<id> and a QR code, and share it anywhere — a chat, an email, an invoice PDF, a sticker on the counter. The customer opens it and pays from any chain; no integration on your side.
Creating one
Dashboard → Sell → Payment links. A link sells one of two things:
- Line items — an ad-hoc mini-invoice: name × quantity × unit price, the total priced on the spot. For the things that never belonged in a catalog: a custom job, a one-off invoice, a tip.
- A catalog price — the link sells exactly what your catalog does, discount code optionally pre-applied. Pointing it at a recurring price makes the link a subscription sign-up.
Everything else is defaults you can change:
| Setting | Default | |
|---|---|---|
| Type | one-time | The link dies after its first confirmed payment. Reusable keeps collecting — a tip jar, a donation page |
| Expires | 1 day | 1 day / 1 week / 1 month / never |
| Reference | auto-generated | Your order id; it lands in each payment's metadata |
| Description | — | Shown to the payer above the amount |
How it behaves
The link is a recipe, not a payment. Deposit addresses and quotes have lifetimes measured in minutes; links shouldn't. So the actual payment is created the moment a customer opens the page — each visitor gets a fresh quote at the link's price.
The link is also the pricing authority: whatever a client sends alongside linkId at checkout, the amount comes from the link. And because the unguessable id names its own merchant, the pay page needs no publishable key.
States: active → paid (one-time, first confirmed payment) / expired (its timestamp passed) / disabled (you clicked disable — terminal). Non-active links still render a page that says what happened, which beats a bare 404 for the person holding the link.
Payments collected through a link carry linkId and reference in their metadata, so your webhook receiver can attribute them.
API
Everything the dashboard does is these endpoints, with your secret key:
bash
# create
curl -X POST https://…/v1/links \
-H "authorization: Bearer $SECRET_KEY" -H "content-type: application/json" \
-d '{"items":[{"name":"Invoice #42","quantity":1,"unitPriceUsd":250}],
"description":"Design work","expiresAt":"2026-09-01T00:00:00Z"}'
# list (status, payments collected)
curl https://…/v1/links -H "authorization: Bearer $SECRET_KEY"
# kill-switch — disabling is terminal
curl -X DELETE https://…/v1/links/link_… -H "authorization: Bearer $SECRET_KEY"The public side is GET /v1/pay/:id (what the pay page renders) and the standard checkout with linkId in place of priceId. The <Checkout> component does the same with a prop:
tsx
<Checkout baseUrl="https://…" linkId="link_…" customerId={visitorId} />