Skip to main content
A Checkout Session is a server-priced offer for one plan: item, total, currency, and an expiry. Use the Checkout Sessions API to open a session, poll the quote, collect buyer requirements, and confirm payment.

Endpoints

Attributes

string
required
Checkout session ID, prefixed chs_.
string | null
required
The affiliate this checkout is attributed to, or null. Set at create only.
string[]
required
Every value display_currency accepts: the seller’s own currency, plus the buyer’s local one when the seller has adaptive pricing on and Whop can price in it. Anything else is refused. A checkout that takes no money — a free plan, a transfer, a promo code that makes every charge free — offers the seller’s currency alone: there is nothing to pay, so there is no currency to choose.
object | null
required
The seller’s checkout appearance, resolved configuration first, then plan, then account. null when nobody set any.

Properties

string | null
required
Page background, as a #rrggbb hex color.
string | null
required
black or white, whichever reads against the background.
string | null
required
The corner style the seller chose.Available options: rounded, pill, rectangular
string | null
required
Pay button fill, as a #rrggbb hex color.
string | null
required
The CSS border-radius for buttons at that border style.
string | null
required
black or white, whichever reads against the button.
string | null
required
The CSS border-radius for containers at that border style.
string | null
required
The font the seller chose.Available options: system, roboto, open_sans
string | null
required
The stylesheet to load for that font, or null for the system font.
string | null
required
The CSS border-radius for inputs at that border style.
string | null
required
The CSS font-family value for that font, or null for the system font.
string | null
required
The buyer’s email, once one has been resolved for this checkout — null until then. Read-only, and read it together with buyer_identity: an address alone does not mean the person holds it.
string | null
required
The buyer’s user account (user_…), once one has been resolved for this checkout — null until then. Read-only, and read it together with buyer_identity: attributed names the account the purchase is for and proves nothing about who is at the keyboard.
string | null
required
How well this checkout knows its buyer, or null before one is resolved. attributed means an account was matched from what the buyer typed — it says who the purchase is for and nothing about who is at the keyboard. authenticated means the person proved they hold that account during this checkout. Only authenticated may be handed anything that acts as the buyer, and the value only strengthens.Available options: attributed, authenticated
string | null
required
When the buyer’s identity was last established or strengthened, as an ISO 8601 timestamp. null before a buyer is resolved.
string | null
required
How the buyer’s identity was established — the mechanism behind buyer_identity, so a checkout stays explicable long after it completed. null before a buyer is resolved. New mechanisms are added over time.Available options: confirmation_token_email, buyer_email, saved_payment_method, session_intent, post_purchase_claim
string | null
required
The seller’s checkout configuration this session was mounted from (ch_…), or null when it was opened directly from a plan. Its presets seeded this session at create.
string
The session’s one credential — returned by create, and echoed on a session read authenticated with it (or with the checkout’s own resume cookie, which holds the same value). Every other call authenticates with it; treat it like a password for this checkout.
boolean
required
Whether this seller offers tax ID entry on checkout (their VAT ID setting). When false, hide the input — a stored tax_id still applies either way.
string
required
When the session was created, as an ISO 8601 timestamp.
string
required
The verb for the button that confirms this checkout, so every surface names the act the same way: pay, subscribe, start_trial, join_waitlist, or continue when nothing is charged today (a free checkout, setup mode saving a payment method, or a transfer that charges nothing). Render your own wording for each value — this is a key, never display text — and fall back to a generic label on a value you do not recognize.Available options: accept_transfer, pay, continue, start_trial, subscribe, join_waitlist
object[]
required
The buyer’s answers to the plan’s custom fields.

Properties

string
required
The plan custom field this answers, prefixed field_ — the id of the matching entry published by the custom_fields requirement.
string
required
The buyer’s answer, as typed.
string
required
The currency this checkout is priced AND charged in, lowercase. Seeded at create from where the buyer is; update it to one of available_currencies to price and charge in that currency instead.
object | null
required
The waitlist entry the confirm created, or null. Only a waitlist plan produces one: joining charges nothing — the payment method is saved and the seller charges it if they accept the entry — so a completed waitlist session carries an entry and a null payment. Read it with its status: succeeded means the join stands; failed (the card save died — the buyer is not on the waitlist) is transient, reopening the session on the next read with the failure on last_confirm_error.

Properties

string
required
The waitlist entry created by the confirm, prefixed entry_.
string
required
Where the join stands. succeeded — the join stands (whether the seller accepts it is the entry resource’s own story). requires_action — the card save has a step left, carried by next_action. processing — the save is being decided; hold. failed — the card save died: the buyer is NOT on the waitlist, and needs a fresh checkout to join.Available options: requires_action, processing, succeeded, failed
string
required
When the session expires, as an ISO 8601 timestamp. An expired session cannot be updated or confirmed — start a new one.
string | null
required
When this checkout’s invoice is due, as an ISO 8601 timestamp — null for everything that is not an invoice checkout, and for an invoice without a due date. Present when the plan collects a seller-issued invoice; a surface should state the date, and a date in the past reads as overdue.
object[]
required
What the buyer is purchasing. Exactly one entry today — the array shape is the contract, and more entries are refused until multi-item checkout ships.

Properties

string | null
required
The seller’s longer description of the item, or null. Multi-line text as the seller wrote it, suited to a collapsible details block.
integer | null
required
How many days of access a one-time purchase grants, or null when access does not expire (a renewing plan’s access follows its billing instead).
string | null
required
One line describing the item, or null. The checkout link’s own description when the seller wrote one, otherwise the product’s headline.
string | null
required
The item’s square art image URL, or null when the seller uploaded none.
string
required
What this item is called, ready to render — the product’s title, falling back to the seller’s name. Never empty.
string
required
The plan being purchased (plan_…). The plan is the price — sessions never carry client-asserted amounts.
integer
required
How many of the plan the buyer is purchasing. At least 1.
object | null
required
Why the most recent confirm attempt did not complete, or null. Only terminal refusals land here — anything the buyer can resolve is a next_action instead. The session stays open; fix what the code names and confirm again.

Properties

string
required
What stopped the confirm. The session: session_expired, session_completed, confirm_in_progress, attestation_required. The price: quote_expired (already refreshed), quote_changed (the stored quote is not what this confirm would charge — the buyer who resolved at confirm prices differently, e.g. a returning buyer skipped past the plan’s free trial; the session is already re-quoted, so re-read it, show the new total, and confirm again), rate_expired (the exchange rate behind a local-currency price aged out — re-read the session for a fresh one). The payment method: token_invalid, payment_method_unsupported, payment_method_unavailable (a saved method the token names no longer exists in the buyer’s wallet — collect a fresh one). What is being sold, and whether it may still be sold: seller_unavailable, promo_invalid, shipping_address_required, custom_field_invalid (a required question is unanswered, or an answer names a question this product does not ask), plan_archived, product_archived, out_of_stock, purchases_disabled, blocked_country, custom_password (the plan’s purchase password is unanswered — update the session’s password and confirm again), waitlist_unavailable (this waitlist cannot be joined as asked — the message says why). The buyer: user_suspended, user_banned_from_whop, email_required, free_plan_already_owned, waitlist_entry_pending, waitlist_already_member, and buyer_ineligible — an account-state refusal read by someone who never proved they hold that account, so which state stays undisclosed. The payment itself: payment_failed. And engine_unavailable for a session whose mode this checkout cannot charge yet. Every one of these is terminal for this attempt as it stands — a refusal the buyer can resolve by doing something arrives as next_action instead.Available options: session_expired, session_completed, attestation_required, quote_expired, quote_changed, rate_expired, token_invalid, confirm_in_progress, engine_unavailable, seller_unavailable, promo_invalid, payment_method_unsupported, payment_method_unavailable, shipping_address_required, custom_field_invalid, payment_failed, waitlist_unavailable, purchases_disabled, plan_archived, product_archived, out_of_stock, custom_password, blocked_country, user_suspended, user_banned_from_whop, email_required, free_plan_already_owned, waitlist_entry_pending, waitlist_already_member, buyer_ineligible
string
required
A human-readable explanation of the failure, safe to show the buyer.
object | null
required
Free-form string-to-string map set at create. Whop never interprets it.
string
required
payment charges the items at confirm; setup saves a payment method for later use.Available options: payment, setup
object | null
required
The one thing to do now, or null when there is nothing. Do it, re-read the session, and repeat until it is null. A completed session with no next_action has nothing left to do — whether the checkout WENT THROUGH is the result’s own status (payment.status, or entry.status for a waitlist join): a charge that decisively dies REOPENS the session on the next read, with the failure on last_confirm_error — so a failed result is a transient reading, never a resting state, and nothing about it may be presented as a success. type picks the shape, and each type carries only its own fields: switch on type and the payload it needs is there; a type you do not recognize is safe to skip when it is not blocking. blocking says whether the flow may move past it — read it rather than inferring it from the type. Before the charge, blocking means the buyer cannot pay until it is done. complete is the attempt’s own unfinished ceremony — a 3D Secure challenge, a bank redirect — and one executor serves it whatever its kind: hand its client_secret to the payments element’s handleNextAction. After it, wait_for_payment is blocking because the money is still moving and everything past that point would tell the buyer their order landed — hold, wait poll_after_seconds, and read again. The post-completion actions (upgrade_authentication, redirect, await_claim) are advisory: the purchase stands either way. After completion the action can also depend on WHO is reading: a signed-in buyer may be handed the redirect where an anonymous read of the same session gets await_claim — told to check their email to claim the purchase, or that the checkout finished on another device — and a read from outside whop.com’s own pages (an embedded element) may be handed a redirect whose destination is whop.com’s checkout-finish page instead of the seller’s: execute it like any other redirect, and treat the URL as the credential it carries. This is an instruction, never the gate: confirm re-checks everything for itself, so a client that skips a blocking action is refused all the same. upgrade_authentication carries its own recipe (email, sign_in_intent); when its session_intent_id is non-null, the reader’s own mid-checkout sign-in already proved the first factor and the recipe collapses to its last step — call that session intent’s upgrade endpoint directly (the credential the sign-in installed authorizes it) and collect only what the login still owes.
string
required
Always checkout_session.
object | null
required
The payment the confirm created, or null while none exists. Read it with its status: a completed session’s payment can still be requires_action (a step remains) or processing (accepted, settling). failed is a transient reading — a charge that decisively dies reopens the session on the next read, unbinding the dead payment and recording the failure on last_confirm_error. Anything the charge still needs comes through next_action, which is also where the payment’s own credential lives.

Properties

string
required
The payment created by the confirm, prefixed pay_.
string
required
Where the payment stands, and the only honest reading of a completed checkout’s outcome. requires_action — a step remains and next_action carries it. processing — accepted and settling (or deciding); hold. succeeded — the money moved. failed — the charge died (declined, expired, voided): the checkout did not go through, whatever the session’s own status says, and the buyer needs a fresh checkout to try again.Available options: requires_action, processing, succeeded, failed
object | null
required
The configuration governing this session, resolved through every layer — the checkout configuration it was mounted from, the plan’s, and the account’s. Apply it over the payment method types catalogue for the offerable set. null means nothing is configured at any layer: platform defaults apply.

Properties

string[]
required
Payment methods this checkout withholds, even when the defaults would offer them.
string[]
required
Payment methods this checkout offers on top of whatever the defaults provide.
boolean
required
Whether Whop’s default set is the starting point. When false, only enabled is offered.
boolean
required
Whether confirm needs a confirmation_token. false when no charge will ever take money — a free plan, a transfer of a non-renewing plan, or an applied promo code that makes every charge free, now and forever: collect no payment method there and confirm without a token. Live like every session fact: applying or removing a code can flip it, so mount your payment surface off this field, never off a zero total — a checkout that charges nothing today but something later (a trial, a first-charge-only code) stays true.
string | null
required
The buyer’s phone number, or null. Collected when the session publishes a phone_number requirement (the seller collects numbers), set through update, and recorded against the order. Buyer-typed and unverified — sellers who VERIFY numbers get the verify_phone next action instead, which writes to the buyer’s account.
object | null
required
What the applied code takes off and which charges it covers, or null when no code applies. promo_code is the writable field; this is its resolved semantics — the duration says which future charges the breakdown’s upcoming amounts have the discount in.

Properties

number
required
What each covered charge is discounted by. Percentage discounts are represented as a decimal fraction; fixed-amount discounts are in currency.
string
required
The promo code, exactly as promo_code states it.
string | null
required
Currency of a fixed-amount discount; null for a percentage one.Available options: usd, sgd, inr, aud, brl, cad, dkk, eur, nok, gbp, sek, chf, hkd, huf, jpy, mxn, myr, pln, czk, nzd, aed, eth, ape, cop, ron, thb, bgn, idr, dop, php, try, krw, twd, vnd, pkr, clp, uyu, ars, zar, dzd, tnd, mad, kes, kwd, jod, all, xcd, amd, bsd, bhd, bob, bam, khr, crc, xof, egp, etb, gmd, ghs, gtq, gyd, ils, jmd, mop, mga, mur, mdl, mnt, nad, ngn, mkd, omr, pyg, pen, qar, rwf, sar, rsd, lkr, tzs, ttd, uzs, rub, btc, cny, usdt, kzt, awg, whop_usd, xau
string
required
Which charges the discount covers: forever discounts every charge; once covers only the charge at purchase — the code is spent then even when it made that charge free, except on a free trial with nothing due today, where it holds until the trial’s first real charge; repeating covers every charge landing within number_of_intervals calendar months of purchase.Available options: forever, once, repeating
integer | null
required
How many calendar months of charges a repeating promo covers, counted from purchase — a renewal scheduled past that window bills full price however few charges came before it. null for the other durations.
string
required
Whether the discount is percentage-based or a fixed amount.Available options: percentage, flat_amount
string | null
required
The promo code applied to the quote, or null. Set it via update; the discount shows up in the quote.
object
required
The current price of the items, computed by the server on every read. Confirm charges this number while it is fresh.

Properties

number
required
The total in base_currency, before conversion — what the seller prices in. The figure that is actually charged is breakdown.total, in currency.
string
required
The seller’s own currency for these items, lowercase. Equal to currency when no conversion applied.
object
required
The same total, itemized — what is being bought, what changes the price, and what is owed later. The tax adjustment arrives pending here and resolves through calculate_tax, which answers with this same shape: render whichever you hold, preferring the calculated one.

Properties

object[]
required
WHAT changes the price, in application order — the charge discounts, then adds its fee, then taxes the lot. An adjustment that does not apply is ABSENT, never zero — a zero would claim it was computed and found to be nothing. The buyer_fee row assumes a payment method that carries the fee (all of them except buy-now-pay-later): re-call calculate_breakdown with the chosen method’s supports_buyer_fee and the row drops out for a method that carries none, exactly as the charge will.

Properties

object | null
required
What this adjustment does to the total — negative for a discount. null only while status is pending.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
string
required
added counts toward the total; included is already inside the lines and is shown for disclosure only (inclusive-tax markets).Available options: added, included
string
required
What changes the price: the promo’s discount, the buyer_fee the charge adds, or tax.Available options: discount, buyer_fee, tax
string
required
What to show the buyer for this row.
string
The tax row’s effective rate as a decimal fraction ("0.0725" is 7.25%) — the tax as a share of the base it was priced on, stated so a surface can label the row with the percentage. Present only on a resolved tax adjustment from calculate_breakdown or calculate_tax; absent on other kinds, on a pending row, and on a completed session’s settled row.
string
Present only on an adjustment with no figure yet — render its row in a loading state and expect calculate_breakdown to resolve it. An adjustment that does not apply is absent from the list entirely, never a zero row.Available options: pending
string
required
ISO currency every figure below is in, lowercase. Every amount here is a Money object, never a bare number — see subtotal.Available options: usd, sgd, inr, aud, brl, cad, dkk, eur, nok, gbp, sek, chf, hkd, huf, jpy, mxn, myr, pln, czk, nzd, aed, eth, ape, cop, ron, thb, bgn, idr, dop, php, try, krw, twd, vnd, pkr, clp, uyu, ars, zar, dzd, tnd, mad, kes, kwd, jod, all, xcd, amd, bsd, bhd, bob, bam, khr, crc, xof, egp, etb, gmd, ghs, gtq, gyd, ils, jmd, mop, mga, mur, mdl, mnt, nad, ngn, mkd, omr, pyg, pen, qar, rwf, sar, rsd, lkr, tzs, ttd, uzs, rub, btc, cny, usdt, kzt, awg, whop_usd, xau
object
required
WHAT TO RENDER — the summary’s headline and itemized sections, decided server-side from the same computation as the figures above so the two cannot disagree. Render this rather than re-deriving rows from the figures; the figures stay authoritative for arithmetic.

Properties

object
required
The hero: the figure (or trial length, or the word “Free”) and the one-line context under it.

Properties

object | null
required
The figure to headline when kind is amount — already posture-correct. null on the other kinds.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
object[]
required
The lines under the headline, in render order — the billing period, “Due today”, or what follows the trial (“Then … starting …”); a stepping promo adds the price the schedule returns to, with its own start date; a waitlist face ends with its no-charge-until-accepted notice. Empty when the headline stands alone.

Properties

object | null
The row’s figure as a Money object, when it has one — what a surface formats in the buyer’s locale.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
object | null
The typed parameters this row’s wording is built from — the localization rail. Absent when the kind needs none.

Properties

integer
How many days of access a one-time purchase grants, when it expires.
string
When a transferred membership’s access ends, as an ISO 8601 timestamp — the recipient gets the origin’s REMAINING time, never a fresh grant of the plan’s window.
string
The tax row’s application: added counts toward the total; included is already inside the prices and is disclosed, never added.Available options: added, included
string
The instant this row’s charge lands, as an ISO 8601 timestamp — format it in the buyer’s locale rather than deriving a date client-side.
string
The promo code (uppercased) whose coverage this row states — “Then your first month is free with FREETODAY”.
object
The one-off fee inside today’s due_today charge — name it (“Due today — includes a one-time $50.00 fee”) so the figure does not read as the recurring rate.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
integer
Days between recurring charges, for wording the billing period (30 is monthly, 365 yearly).
boolean
Present (and true) when this one-time payment collects a seller-issued invoice — word it as a bill (“Invoice — one-time payment.”) beside the session’s own due date, never as a storefront purchase.
boolean
Present (and true) when the trial this row follows charges a fee today — the wording drops the word “trial” for the neutral “after N days”, exactly as the legacy checkout worded a paid trial.
string
The tax row’s effective rate as a decimal fraction ("0.0725" is 7.25%), when the calculation stated one.
integer
How many payments are still AHEAD at this row’s amount — today’s paying receipt already consumed one of the plan’s total, exactly as billing counts receipts. Word it as the future stream (“for 3 more payments”), never as the plan’s total.
integer
An installment plan’s PLAN-WIDE payment count, today’s paying charge included — word it as the plan’s total (“for a total of 4 payments”). Mutually exclusive with remaining_payments: a row states whichever count it means.
integer
The free-trial length this row speaks about, in days.
boolean
Present (and true) when this row’s amount is stated before tax and the wording must say so — the checkout adds exclusive tax the future charge will carry on top.
string
required
Which row this is. Render a kind you know from detail in your own wording; render one you do not from label and text verbatim — never drop it.Available options: then_starting, then_after_trial, due_today, period, one_time_payment, access_window, access_until, trial_window, waitlist_notice, waitlist_trial_notice, free_forever, tax_included, promo_free_period, initial_fee, renewal_fee, tax_today, total_due_today, total_if_accepted, total_due_starting, total_after_trial, post_promo, item_subtotal, service_fee
string
The row’s left side in English — the fallback for a kind the surface cannot name. Absent on a row that is a single line rather than a label/value pair (the headline’s context).
string
Present only on a row whose figure is still being calculated — render it in a loading state and expect calculate_breakdown to resolve it.Available options: pending
string
The row’s value (or its whole line) in English — the fallback for a kind the surface cannot name. Absent while status is pending.
string | null
required
When kind is free on a renewing membership transfer: the instant the transferred paid period ends and the takeover starts billing, as an ISO 8601 timestamp — word the headline “Free until …”. null everywhere else.
string
required
The headline’s face: amount headlines the figure in amount; trial headlines the free-trial length off trial_days; free headlines the word — the served free signal or a membership transfer collecting nothing today (a renewing transfer states when its free stretch ends in free_until), never derived from zero prices (a promo covering the whole first charge is not a free plan).Available options: amount, trial, free
object | null
required
The pre-promo figure to strike through beside amount, or null when no discount moved today’s charge.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
string
required
The headline in English — the fallback for a kind the surface cannot name. A surface that knows the kind renders its own wording from amount/trial_days/free_until.
integer | null
required
The free-trial length when kind is trial, in days. null on the other kinds.
object
required
The itemized sections below — line items, charges, totals, and the collapsible fee breakdown. All empty on a free checkout.

Properties

object[]
required
What is added to (or disclosed inside) today’s charge — the tax_today row once tax is priced, pending while it is being priced, absent when this checkout taxes nothing.

Properties

object | null
The row’s figure as a Money object, when it has one — what a surface formats in the buyer’s locale.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
object | null
The typed parameters this row’s wording is built from — the localization rail. Absent when the kind needs none.

Properties

integer
How many days of access a one-time purchase grants, when it expires.
string
When a transferred membership’s access ends, as an ISO 8601 timestamp — the recipient gets the origin’s REMAINING time, never a fresh grant of the plan’s window.
string
The tax row’s application: added counts toward the total; included is already inside the prices and is disclosed, never added.Available options: added, included
string
The instant this row’s charge lands, as an ISO 8601 timestamp — format it in the buyer’s locale rather than deriving a date client-side.
string
The promo code (uppercased) whose coverage this row states — “Then your first month is free with FREETODAY”.
object
The one-off fee inside today’s due_today charge — name it (“Due today — includes a one-time $50.00 fee”) so the figure does not read as the recurring rate.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
integer
Days between recurring charges, for wording the billing period (30 is monthly, 365 yearly).
boolean
Present (and true) when this one-time payment collects a seller-issued invoice — word it as a bill (“Invoice — one-time payment.”) beside the session’s own due date, never as a storefront purchase.
boolean
Present (and true) when the trial this row follows charges a fee today — the wording drops the word “trial” for the neutral “after N days”, exactly as the legacy checkout worded a paid trial.
string
The tax row’s effective rate as a decimal fraction ("0.0725" is 7.25%), when the calculation stated one.
integer
How many payments are still AHEAD at this row’s amount — today’s paying receipt already consumed one of the plan’s total, exactly as billing counts receipts. Word it as the future stream (“for 3 more payments”), never as the plan’s total.
integer
An installment plan’s PLAN-WIDE payment count, today’s paying charge included — word it as the plan’s total (“for a total of 4 payments”). Mutually exclusive with remaining_payments: a row states whichever count it means.
integer
The free-trial length this row speaks about, in days.
boolean
Present (and true) when this row’s amount is stated before tax and the wording must say so — the checkout adds exclusive tax the future charge will carry on top.
string
required
Which row this is. Render a kind you know from detail in your own wording; render one you do not from label and text verbatim — never drop it.Available options: then_starting, then_after_trial, due_today, period, one_time_payment, access_window, access_until, trial_window, waitlist_notice, waitlist_trial_notice, free_forever, tax_included, promo_free_period, initial_fee, renewal_fee, tax_today, total_due_today, total_if_accepted, total_due_starting, total_after_trial, post_promo, item_subtotal, service_fee
string
The row’s left side in English — the fallback for a kind the surface cannot name. Absent on a row that is a single line rather than a label/value pair (the headline’s context).
string
Present only on a row whose figure is still being calculated — render it in a loading state and expect calculate_breakdown to resolve it.Available options: pending
string
The row’s value (or its whole line) in English — the fallback for a kind the surface cannot name. Absent while status is pending.
object[]
required
The collapsible price breakdown: the item_subtotal beside the service_fee, present only when a fee actually charges today.

Properties

object | null
The row’s figure as a Money object, when it has one — what a surface formats in the buyer’s locale.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
object | null
The typed parameters this row’s wording is built from — the localization rail. Absent when the kind needs none.

Properties

integer
How many days of access a one-time purchase grants, when it expires.
string
When a transferred membership’s access ends, as an ISO 8601 timestamp — the recipient gets the origin’s REMAINING time, never a fresh grant of the plan’s window.
string
The tax row’s application: added counts toward the total; included is already inside the prices and is disclosed, never added.Available options: added, included
string
The instant this row’s charge lands, as an ISO 8601 timestamp — format it in the buyer’s locale rather than deriving a date client-side.
string
The promo code (uppercased) whose coverage this row states — “Then your first month is free with FREETODAY”.
object
The one-off fee inside today’s due_today charge — name it (“Due today — includes a one-time $50.00 fee”) so the figure does not read as the recurring rate.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
integer
Days between recurring charges, for wording the billing period (30 is monthly, 365 yearly).
boolean
Present (and true) when this one-time payment collects a seller-issued invoice — word it as a bill (“Invoice — one-time payment.”) beside the session’s own due date, never as a storefront purchase.
boolean
Present (and true) when the trial this row follows charges a fee today — the wording drops the word “trial” for the neutral “after N days”, exactly as the legacy checkout worded a paid trial.
string
The tax row’s effective rate as a decimal fraction ("0.0725" is 7.25%), when the calculation stated one.
integer
How many payments are still AHEAD at this row’s amount — today’s paying receipt already consumed one of the plan’s total, exactly as billing counts receipts. Word it as the future stream (“for 3 more payments”), never as the plan’s total.
integer
An installment plan’s PLAN-WIDE payment count, today’s paying charge included — word it as the plan’s total (“for a total of 4 payments”). Mutually exclusive with remaining_payments: a row states whichever count it means.
integer
The free-trial length this row speaks about, in days.
boolean
Present (and true) when this row’s amount is stated before tax and the wording must say so — the checkout adds exclusive tax the future charge will carry on top.
string
required
Which row this is. Render a kind you know from detail in your own wording; render one you do not from label and text verbatim — never drop it.Available options: then_starting, then_after_trial, due_today, period, one_time_payment, access_window, access_until, trial_window, waitlist_notice, waitlist_trial_notice, free_forever, tax_included, promo_free_period, initial_fee, renewal_fee, tax_today, total_due_today, total_if_accepted, total_due_starting, total_after_trial, post_promo, item_subtotal, service_fee
string
The row’s left side in English — the fallback for a kind the surface cannot name. Absent on a row that is a single line rather than a label/value pair (the headline’s context).
string
Present only on a row whose figure is still being calculated — render it in a loading state and expect calculate_breakdown to resolve it.Available options: pending
string
The row’s value (or its whole line) in English — the fallback for a kind the surface cannot name. Absent while status is pending.
object[]
required
What today’s charge is made of, when the headline alone cannot say: a renewal’s one-off initial_fee, and the renewal_fee beside it.

Properties

object | null
The row’s figure as a Money object, when it has one — what a surface formats in the buyer’s locale.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
object | null
The typed parameters this row’s wording is built from — the localization rail. Absent when the kind needs none.

Properties

integer
How many days of access a one-time purchase grants, when it expires.
string
When a transferred membership’s access ends, as an ISO 8601 timestamp — the recipient gets the origin’s REMAINING time, never a fresh grant of the plan’s window.
string
The tax row’s application: added counts toward the total; included is already inside the prices and is disclosed, never added.Available options: added, included
string
The instant this row’s charge lands, as an ISO 8601 timestamp — format it in the buyer’s locale rather than deriving a date client-side.
string
The promo code (uppercased) whose coverage this row states — “Then your first month is free with FREETODAY”.
object
The one-off fee inside today’s due_today charge — name it (“Due today — includes a one-time $50.00 fee”) so the figure does not read as the recurring rate.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
integer
Days between recurring charges, for wording the billing period (30 is monthly, 365 yearly).
boolean
Present (and true) when this one-time payment collects a seller-issued invoice — word it as a bill (“Invoice — one-time payment.”) beside the session’s own due date, never as a storefront purchase.
boolean
Present (and true) when the trial this row follows charges a fee today — the wording drops the word “trial” for the neutral “after N days”, exactly as the legacy checkout worded a paid trial.
string
The tax row’s effective rate as a decimal fraction ("0.0725" is 7.25%), when the calculation stated one.
integer
How many payments are still AHEAD at this row’s amount — today’s paying receipt already consumed one of the plan’s total, exactly as billing counts receipts. Word it as the future stream (“for 3 more payments”), never as the plan’s total.
integer
An installment plan’s PLAN-WIDE payment count, today’s paying charge included — word it as the plan’s total (“for a total of 4 payments”). Mutually exclusive with remaining_payments: a row states whichever count it means.
integer
The free-trial length this row speaks about, in days.
boolean
Present (and true) when this row’s amount is stated before tax and the wording must say so — the checkout adds exclusive tax the future charge will carry on top.
string
required
Which row this is. Render a kind you know from detail in your own wording; render one you do not from label and text verbatim — never drop it.Available options: then_starting, then_after_trial, due_today, period, one_time_payment, access_window, access_until, trial_window, waitlist_notice, waitlist_trial_notice, free_forever, tax_included, promo_free_period, initial_fee, renewal_fee, tax_today, total_due_today, total_if_accepted, total_due_starting, total_after_trial, post_promo, item_subtotal, service_fee
string
The row’s left side in English — the fallback for a kind the surface cannot name. Absent on a row that is a single line rather than a label/value pair (the headline’s context).
string
Present only on a row whose figure is still being calculated — render it in a loading state and expect calculate_breakdown to resolve it.Available options: pending
string
The row’s value (or its whole line) in English — the fallback for a kind the surface cannot name. Absent while status is pending.
object[]
required
The totals block, in render order: what today collects (total_due_today, a waitlist’s total_if_accepted, or a renewing transfer’s total_due_starting), then total_after_trial, then post_promo.

Properties

object | null
The row’s figure as a Money object, when it has one — what a surface formats in the buyer’s locale.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
object | null
The typed parameters this row’s wording is built from — the localization rail. Absent when the kind needs none.

Properties

integer
How many days of access a one-time purchase grants, when it expires.
string
When a transferred membership’s access ends, as an ISO 8601 timestamp — the recipient gets the origin’s REMAINING time, never a fresh grant of the plan’s window.
string
The tax row’s application: added counts toward the total; included is already inside the prices and is disclosed, never added.Available options: added, included
string
The instant this row’s charge lands, as an ISO 8601 timestamp — format it in the buyer’s locale rather than deriving a date client-side.
string
The promo code (uppercased) whose coverage this row states — “Then your first month is free with FREETODAY”.
object
The one-off fee inside today’s due_today charge — name it (“Due today — includes a one-time $50.00 fee”) so the figure does not read as the recurring rate.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
integer
Days between recurring charges, for wording the billing period (30 is monthly, 365 yearly).
boolean
Present (and true) when this one-time payment collects a seller-issued invoice — word it as a bill (“Invoice — one-time payment.”) beside the session’s own due date, never as a storefront purchase.
boolean
Present (and true) when the trial this row follows charges a fee today — the wording drops the word “trial” for the neutral “after N days”, exactly as the legacy checkout worded a paid trial.
string
The tax row’s effective rate as a decimal fraction ("0.0725" is 7.25%), when the calculation stated one.
integer
How many payments are still AHEAD at this row’s amount — today’s paying receipt already consumed one of the plan’s total, exactly as billing counts receipts. Word it as the future stream (“for 3 more payments”), never as the plan’s total.
integer
An installment plan’s PLAN-WIDE payment count, today’s paying charge included — word it as the plan’s total (“for a total of 4 payments”). Mutually exclusive with remaining_payments: a row states whichever count it means.
integer
The free-trial length this row speaks about, in days.
boolean
Present (and true) when this row’s amount is stated before tax and the wording must say so — the checkout adds exclusive tax the future charge will carry on top.
string
required
Which row this is. Render a kind you know from detail in your own wording; render one you do not from label and text verbatim — never drop it.Available options: then_starting, then_after_trial, due_today, period, one_time_payment, access_window, access_until, trial_window, waitlist_notice, waitlist_trial_notice, free_forever, tax_included, promo_free_period, initial_fee, renewal_fee, tax_today, total_due_today, total_if_accepted, total_due_starting, total_after_trial, post_promo, item_subtotal, service_fee
string
The row’s left side in English — the fallback for a kind the surface cannot name. Absent on a row that is a single line rather than a label/value pair (the headline’s context).
string
Present only on a row whose figure is still being calculated — render it in a loading state and expect calculate_breakdown to resolve it.Available options: pending
string
The row’s value (or its whole line) in English — the fallback for a kind the surface cannot name. Absent while status is pending.
object[]
required
WHAT is being bought, priced the way the charge prices it — one entry per charged item. A renewing plan’s first cycle is its own line, because the charge builds it that way and a collapsed subtotal diverges from what is charged by a rounding unit.

Properties

object
required
The line’s own total — unit_amount × quantity, before any adjustment.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
string
required
What to show the buyer for this line.
string
required
What this line is — plan today. New kinds arrive as checkout learns to sell more than one thing at once.Available options: plan
integer
required
How many.
object
required
Price of one, before any adjustment.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
object
required
The lines summed, before any adjustment.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
object
required
What confirm charges: the subtotal plus every RESOLVED added adjustment. A pending adjustment is deliberately NOT in it, so the number is never inflated by a figure the buyer cannot yet see itemized — with exclusive tax it therefore grows once tax resolves, and with inclusive tax it does not move at all. Once the session is completed it is what WAS charged: the fee and tax on the order’s own receipt, and nothing is pending.

Properties

string
required
The amount in major units, as an exact decimal string — "10.00" is ten dollars. A string so no float rounds it in transit.
string
required
Three-letter ISO 4217 currency code, lowercase.
integer
required
How many decimal places the amount CARRIES — the precision the charge itself runs at.
integer
required
How many decimal places to SHOW. Usually equal to decimals, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is 2 and 0. Format the number in your own locale using this.
object[]
required
WHEN the rest is owed — empty for a purchase that is settled today. type picks the shape and each variant carries only its own fields. An order can carry several at once (a split-pay plan alongside a subscription upsell), which is why it is a list.
string
required
ISO currency the confirm will charge in, lowercase. This is the buyer’s own currency whenever adaptive pricing applies — the card is charged in it, not shown a conversion of it.
number | null
required
The locked rate base_currency was converted at, or null when the charge is in the seller’s own currency. Fixed for the life of the quote.
string
required
When this quote stops being chargeable, as an ISO 8601 timestamp. A converted quote expires with its exchange rate, which is sooner than an unconverted one.
string
required
When this quote was computed, as an ISO 8601 timestamp. A confirm against a stale quote is refused with quote_expired and the quote refreshes for the retry.
boolean
required
Whether this quote priced the plan’s free trial as SKIPPED: the resolved buyer has held this plan before, so no trial applies and the full first price is due today. Tell the buyer so before they pay — the trial they can see on the plan is not theirs to start. false for a plan with no trial, and for a session whose buyer is not resolved yet: a returning buyer resolving at confirm is refused with quote_changed and this re-prices to true for the retry.
string | null
required
Where the SELLER sends the buyer after a completed purchase, when the checkout configuration this session was mounted from sets one. Always an absolute HTTP or HTTPS URL — anything else serializes as null. Distinct from return_url, which is the payment provider’s return leg.
object[]
required
What this checkout’s form must collect — render every entry together on one screen. Derived on every read, not fixed when the session was created: it changes as the seller’s settings change, as the session is updated, and as a buyer is resolved. Empty once the session is no longer open.

Properties

object[] | null
required
The seller’s questions, on the custom_fields requirement only — null on every other type. Each entry says what to render and whether an answer is mandatory.

Properties

string
required
The question’s ID, prefixed field_. Echo it as the id of the matching custom_field_responses entry.
string | null
required
The seller’s longer explanation of the question, or null.
string
required
What kind of input to render. text today.Available options: text
string
required
The question as the seller wrote it — the field’s label.
string | null
required
Placeholder text for the input, or null.
boolean
required
Whether confirm refuses without an answer. An unanswered required question is refused with custom_field_invalid.
string
required
What to collect. custom_password — the plan is password-protected: send the buyer’s answer through update, and the entry disappears once it is right; confirm refuses while it stands. email — the buyer’s email address; it identifies who the purchase is for, and confirm has no other way to resolve them. terms — explicit acceptance, sent as the tos_accepted attestation on confirm; show the seller’s documents from account.terms. custom_fields — the seller’s own questions, published in fields; answer them through custom_field_responses. shipping_address — a postal address for physical goods, set through shipping_address. phone_number — the seller collects buyer phone numbers: set one through update and it is recorded against the order; a missing number never refuses the confirm. The list is closed; new entries are added deliberately, so an unrecognized type is safe to skip.Available options: custom_password, email, terms, custom_fields, shipping_address, phone_number
string | null
required
Where the buyer lands after an off-site payment step. Must be an absolute https URL without credentials (http is allowed for localhost).
object
required
The seller this checkout purchases from.

Properties

string
required
Account ID, prefixed biz_.
string | null
required
The seller’s logo image URL, or null when they have not uploaded one.
string | null
required
Where this seller sends buyers after any purchase, or null. The plan’s and the checkout configuration’s own redirects take precedence over it.
string
required
The seller’s store-page slug — the :route in whop.com/joined/:route, which is where a purchase lands when nothing more specific is configured.
object
required
The seller’s checkout legal surface: whether explicit acceptance is required, and the policy documents it covers.

Properties

string | null
required
The seller’s end-user licence agreement, or null if they have not published one.
string | null
required
The seller’s privacy policy, or null if they have not published one.
boolean
required
Whether the buyer must explicitly accept the seller’s terms before confirming. true means hold the confirm behind a deliberate act of acceptance; false means the buyer paying through a visible disclosure is the acceptance.
string | null
required
The seller’s return policy, or null if they have not published one.
string | null
required
The seller’s terms of service, or null if they have not published one.
string
required
The seller’s public name, as the buyer knows them.
object | null
required
Where physical goods ship, or null. Only the keys the buyer supplied are present.

Properties

string
City name.
string
ISO 3166-1 alpha-2 country code, such as US.
string
First line of the street address.
string
Second line of the street address.
string
The recipient’s full name, as it should appear on the shipping label.
string
Postal or ZIP code.
string
State, province, or region code, such as CA.
boolean
required
Whether to offer promo code entry on this checkout: false on a membership transfer, a checkout with nothing due, or a one-off purchase — no code can apply — and when the seller disabled codes for it, or none exists to enter. A code already on the session still discounts either way.
string
required
open until a confirm succeeds (completed) or the session ages out (expired). Only an open session can be updated or confirmed. A completed session whose charge later decisively dies returns to open with the failure on last_confirm_error — the same session takes the retry.Available options: open, completed, expired
string | null
required
Whether this checkout collects tax, and how its price reads when it does. null means no tax is collected here — skip calculate_tax entirely and ask for no more address than the payment method itself needs. exclusive means tax is ADDED to the quote, inclusive that the quote already contains it. Present before any address is known, so a surface can decide what to collect up front; the value is what this checkout expects to price with, and calculate_tax answers with the authoritative one once a location is known (tax behaviour varies by country).Available options: inclusive, exclusive
object | null
required
The buyer’s tax registration for a business purchase, or null. Set it via update (null clears it); a stored registration re-prices the quote’s tax row — a valid EU B2B id reverse-charges EU VAT — and confirm charges tax under the same registration, so the shown total and the taken one agree.

Properties

string
required
The registration’s type, such as eu_vat.Available options: ad_nrt, ao_tin, ar_cuit, al_tin, am_tin, aw_tin, au_abn, au_arn, eu_vat, az_tin, bs_tin, bh_vat, bd_bin, bb_tin, by_tin, bj_ifu, bo_tin, ba_tin, br_cnpj, br_cpf, bg_uic, bf_ifu, kh_tin, cm_niu, ca_bn, ca_gst_hst, ca_pst_bc, ca_pst_mb, ca_pst_sk, ca_qst, cv_nif, cl_tin, cn_tin, co_nit, cd_nif, cr_tin, hr_oib, do_rcn, ec_ruc, eg_tin, sv_nit, et_tin, eu_oss_vat, ge_vat, gh_tin, de_stn, gb_vat, gn_nif, hk_br, hu_tin, is_vat, in_gst, id_npwp, il_vat, jp_cn, jp_rn, jp_trn, kz_bin, ke_pin, kg_tin, la_tin, li_uid, li_vat, my_frp, my_itn, my_sst, mr_nif, mx_rfc, md_vat, me_pib, ma_vat, np_pan, nz_gst, ng_tin, mk_vat, no_vat, no_voec, om_vat, pe_ruc, ph_tin, pl_nip, ro_tin, ru_inn, ru_kpp, sa_vat, sn_ninea, rs_pib, sg_gst, sg_uen, si_tin, za_vat, kr_brn, es_cif, ch_uid, ch_vat, tw_vat, tj_tin, tz_vat, th_vat, tr_tin, ug_tin, ua_vat, ae_trn, us_ein, uy_ruc, uz_tin, uz_vat, ve_rif, vn_tin, zm_tin, zw_tin, sr_fin, xi_vat
string
required
The registration number, stored as the buyer entered it (whitespace removed).
string | null
required
The 3D Secure behavior the checkout configuration asks for, or null to use the plan’s or the account’s default.Available options: mandate_challenge, frictionless
string | null
required
The membership this checkout tops up (mem_…), or null for an ordinary purchase. Set at create only. Confirming charges the plan’s price against that existing membership instead of creating a new one — no stock is taken, and for an expiring plan the paid time stacks onto what is left. The buyer must own it: confirm resolves it against the resolved buyer’s own memberships and refuses anything else as not found.
object | null
required
The membership transfer this checkout performs, or null for an ordinary purchase. Present when the session was mounted from a transfer link: confirming moves the linked membership to this buyer instead of creating a fresh purchase, the quote prices zero due today, and for a renewing plan the collected payment method takes over the origin’s future renewals.

Properties

string
required
The 40-character transfer code this checkout was opened from — the same value the link carried.
string | null
required
When the transferred membership’s access expires, as an ISO 8601 timestamp, or null when it does not. The recipient inherits this — a transfer moves the remaining time, it does not restart it.
string | null
required
When the transferred membership’s current billing period ends, as an ISO 8601 timestamp, or null for a non-renewing membership. The recipient’s first renewal charge falls here — nothing is charged at the transfer itself.
CheckoutSession