Skip to content

Take card, bank and crypto payments from your own site with one hosted link.

Your server creates a checkout link, the buyer pays on a page we host, and a signed webhook tells you when the money has arrived. Checkout uses the same API key, webhook endpoint and event feed as payouts. Its contract is its own file, partner-checkout.openapi.yaml.

  1. Set up verification, card payments, an API key and a webhook endpoint (Set up checkout).
  2. Create a product with one fixed price, or put a one-off amount on the link itself.
  3. Publish a link and redirect the buyer to its shareUrl.
  4. Fulfil on checkout_payment.paid, joined to your order by clientReferenceId.
  5. Reverse the fulfilment on checkout_payment.refunded or checkout_payment.reversed. A paid card payment can still be refunded or charged back.

A link without methods takes cards, and the card page also offers Apple Pay, Google Pay and PayPal. Pass methods to offer bank or crypto, each naming the account or address to pay into.

Cards are processed by Whop and are in pilot, opening to verified businesses a few at a time. Buyers see WHOP* and your business name on their statement. Bank and stablecoin payments go live once business verification is approved.

paid means the acceptor has the money. Card payments collect in your card balance with the processor, which you withdraw from Checkout → Balance. Bank and crypto payments arrive in the account or address the link names.

Checkout payments never touch your Avvio ledger. They get no GET /balance_transactions row, card money never appears in GET /balance, and settledAt is always null in this version.

A link’s status is spelled cancelled, unlike a payout’s canceled.

status Meaning
draft Not publicly readable. Edit it with PATCH or delete it
sent Live. shareUrl serves the page
cancelled Paused. The page answers 410 and every rail behind it stops. Permanent in this version
expired Past its expiresAt. The page answers 410 from that instant, and the stored status follows within a minute. Terminal

Publish a draft with POST /links/{linkId}/publish. A live link’s price is fixed, because a buyer may already be looking at it. The only allowed PATCH sets expiresAt alone (a later instant, or null); anything else is a 400. To change the price, pause the link and create another. A link that has been live cannot be deleted, and an expired one cannot be revived. API-made links carry source: "api", and GET /links?source=api (or dashboard) filters on it.

Treat paid as provisional. Card payments can be refunded at any time and charged back weeks later. Bank and stablecoin payments cannot be reversed at the source; send the payer a payout to return one. Two changes raise no event. An open dispute sets disputeSubstatus until it resolves. A bank deposit short of the total stays pending with a reviewReason until someone accepts it in the dashboard. See Refund a payment.

Create and publish a link in the dashboard and paste shareUrl anywhere. Appending ?client_reference_id=<value> carries a per-buyer reference on the card rail only, and only best effort. The hosted-fallback and 3DS-restore paths drop it, and a bank payer types the link’s slug instead. One link per order, with its own clientReferenceId, is the join that works on every rail.

Embedding is not supported in this version, so redirect to shareUrl and back. The payer page sends X-Frame-Options: DENY and Content-Security-Policy: frame-ancestors 'none'. The card form is already the processor’s iframe, 3-D Secure and Apple Pay need the top window, browsers partition framed storage, and with no origin allowlist a framed card page invites clickjacking.

Stripe Here
POST /v1/checkout/sessions, session.url POST /checkout/organizations/{orgId}/links with publish: true, shareUrl
Payment Links A link created in the dashboard, or without publish
success_url, cancel_url successUrl, cancelUrl
client_reference_id, metadata clientReferenceId, metadata (same alphabets and limits)
checkout.session.completed checkout_payment.paid
POST /v1/refunds, refund.reason POST …/payments/{paymentId}/refund, reason (requested_by_customer, duplicate, fraudulent, or our own other)
charge.refunded checkout_payment.refunded or checkout_payment.partially_refunded
charge.dispute.closed (lost) checkout_payment.reversed
payment_link.active = false POST /links/{linkId}/pause (permanent)
expires_at expiresAt on the link
line_items, price_data productId, or currency + items
payment_method_types methods (omitted means card)
Amounts in minor units Decimal strings on links and events; base units with decimals on payment rows

There are no subscriptions and no embeddable checkout.

A test key pays links with a simulated buyer instead of test card numbers, and the total picks the outcome. That includes chargebacks, which no card processor’s sandbox can produce (Environments & sandbox).

Was this page helpful?