Payment links
An intent-first payment link is a bearer URL for immutable purchase terms. New links do not pre-create an Order; confirmation creates it exactly once.
Sessions vs payment links
| Concern | Checkout session | Payment link |
|---|---|---|
| URL shape | /s/:sessionId | /:token |
| Order exists yet? | No (created on confirm). | No (created on confirm). |
| Customer picks order type / address? | Yes | The merchant freezes these before sending; the buyer chooses only an eligible residual tender. |
| Auth flow | OTP via CheckoutElement | "Sign in to Link" or "Pay as guest" choice screen, then provider selection. |
| Use case | E-commerce / DTC checkout. | Chat sales, assisted commerce, and manual quotes. |
What the customer sees
- Immutable line, funding-allocation, and due-now terms.
- Link recognition/OTP when saved payment authorities are requested.
- Tender preparation. A raw transient Mobile Money number crosses this bounded command once; the server returns an opaque option.
- Explicit review of that option's residual principal, fee, and total customer debit.
- Confirmation using only the accepted terms revision and opaque option. Provider UI and replay remain attempt-owned.
- Success after the Order is created, or an explicit failed/unknown outcome without pretending payment succeeded.
When to use a payment link
- You sent a quote / invoice and want a one-click pay button in the email.
- You took an order via WhatsApp / phone and need to collect payment async.
- You took a Cart-backed order via WhatsApp / phone and need buyer confirmation and payment asynchronously.
- A verified staff or agent prepared a Manual purchase intent with the buyer's commercial details.
For storefronts where the customer is currently in a cart, use checkout sessions; they let the customer choose order type, fill an address, etc.
Generating a link
Create the Cart/Chat/Manual purchase intent through an authorized seller surface, then issue its link through that same surface. The public URL is https://pay.cimplify.io/<cpl_token>. Cimplify stores only a versioned token digest and re-derives the same bearer on an exact issuance replay; the raw token is never stored or logged.
For conversational commerce, the checkout.submit tool returns
intent_id, payment_link, and expires_at. It never returns a placeholder
Order. Desk/agent send surfaces use the same typed issuance service.
Resolving and confirming a link
The hosted page uses the bearer-fenced Pay API. Confirmation never accepts a raw phone number:
GET /v1/paylink/<token> # intent and current immutable terms
POST /v1/paylink/<token>/prepare # rotate only residual tender options
POST /v1/paylink/<token>/confirm # accept exact terms + opaque option
GET /v1/paylink/<token>/replay # canonical durable attempt result
POST /v1/paylink/<token>/attempts/<id>/actions # typed provider challengeStates
The hosted page mirrors the purchase-intent and confirmation state:
| UI state | When |
|---|---|
loading | Fetching the order. |
order_loaded | Intent terms are available for review. |
reviewing_terms | Buyer reviews prepared option amounts or replacement terms. |
processing | Provider charge in progress. |
awaiting_authorization | Approve-on-phone style challenge. |
success | Confirmation created the Order and collection succeeded. |
already_paid | Replay reports the existing terminal Order. |
error | Couldn't load order or hit a network failure. Retry button. |
Provider redirects
Some payment methods (cards via 3DS, certain mobile-money flows) require a hop through the provider's domain. The hosted page handles the round-trip: the customer is redirected out, completes the challenge, and lands back at pay.cimplify.io/<token>?reference=… where the page resumes polling and shows the success state.
Webhooks
Same as everywhere else: Order/payment events fire only after the shared confirmation kernel commits. Always treat webhooks as the source of truth.
Pre-convergence Order bill tokens remain read/collect-only for their live
historical population. Subscription-renewal scl_ collection links are a
separate billing authority. Neither namespace can issue a new checkout Order
link, and neither may fall through from a malformed or disabled cpl_ token.
Next
- Checkout sessions: For carts that haven't become orders yet
- Orders SDK: Read / cancel an order programmatically
Checkout sessions
A checkout session is a short-lived URL on `pay.cimplify.io` that hosts the full checkout for a specific cart. You create one server-side with your secret key, redirect the customer to the URL, and listen for the resulting webhook.
cimplify init
Scaffold a working Next.js App Router storefront from one of seven industry templates. After `bun install`, `bun dev` boots the local mock API alongside Next, and you have a real shop in 60 seconds.