cimplify
Cimplify Pay

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.

ConcernCheckout sessionPayment link
URL shape/s/:sessionId/:token
Order exists yet?No (created on confirm).No (created on confirm).
Customer picks order type / address?YesThe merchant freezes these before sending; the buyer chooses only an eligible residual tender.
Auth flowOTP via CheckoutElement"Sign in to Link" or "Pay as guest" choice screen, then provider selection.
Use caseE-commerce / DTC checkout.Chat sales, assisted commerce, and manual quotes.

What the customer sees

  1. Immutable line, funding-allocation, and due-now terms.
  2. Link recognition/OTP when saved payment authorities are requested.
  3. Tender preparation. A raw transient Mobile Money number crosses this bounded command once; the server returns an opaque option.
  4. Explicit review of that option's residual principal, fee, and total customer debit.
  5. Confirmation using only the accepted terms revision and opaque option. Provider UI and replay remain attempt-owned.
  6. Success after the Order is created, or an explicit failed/unknown outcome without pretending payment succeeded.
  • 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.

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.

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 challenge

States

The hosted page mirrors the purchase-intent and confirmation state:

UI stateWhen
loadingFetching the order.
order_loadedIntent terms are available for review.
reviewing_termsBuyer reviews prepared option amounts or replacement terms.
processingProvider charge in progress.
awaiting_authorizationApprove-on-phone style challenge.
successConfirmation created the Order and collection succeeded.
already_paidReplay reports the existing terminal Order.
errorCouldn'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

On this page