> ## Documentation Index
> Fetch the complete documentation index at: https://docs.whop.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Checkout Session

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

| Endpoint                                                                                 | Request                                                                 |
| ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| [Create Checkout Session](/api-reference/beta/checkout-sessions/create-checkout-session) | <Badge color="green" size="sm" stroke>POST</Badge> `/checkout_sessions` |

## Attributes

<Columns cols={2}>
  <Column>
    <ResponseField name="id" type="string" required>
      Checkout session ID, prefixed `chs_`.
    </ResponseField>

    <ResponseField name="affiliate_code" type="string | null" required>
      The affiliate this checkout is attributed to, or `null`. Set at create only.
    </ResponseField>

    <ResponseField name="available_currencies" type="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.
    </ResponseField>

    <ResponseField name="branding" type="object | null" required>
      The seller's checkout appearance, resolved configuration first, then plan, then account. `null` when nobody set any.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="background_color" type="string | null" required>
          Page background, as a `#rrggbb` hex color.
        </ResponseField>

        <ResponseField name="background_text_color" type="string | null" required>
          `black` or `white`, whichever reads against the background.
        </ResponseField>

        <ResponseField name="border_style" type="string | null" required>
          The corner style the seller chose.

          Available options: `rounded`, `pill`, `rectangular`
        </ResponseField>

        <ResponseField name="button_color" type="string | null" required>
          Pay button fill, as a `#rrggbb` hex color.
        </ResponseField>

        <ResponseField name="button_radius" type="string | null" required>
          The CSS `border-radius` for buttons at that border style.
        </ResponseField>

        <ResponseField name="button_text_color" type="string | null" required>
          `black` or `white`, whichever reads against the button.
        </ResponseField>

        <ResponseField name="container_radius" type="string | null" required>
          The CSS `border-radius` for containers at that border style.
        </ResponseField>

        <ResponseField name="font_family" type="string | null" required>
          The font the seller chose.

          Available options: `system`, `roboto`, `open_sans`
        </ResponseField>

        <ResponseField name="font_url" type="string | null" required>
          The stylesheet to load for that font, or `null` for the system font.
        </ResponseField>

        <ResponseField name="input_radius" type="string | null" required>
          The CSS `border-radius` for inputs at that border style.
        </ResponseField>

        <ResponseField name="resolved_font_family" type="string | null" required>
          The CSS `font-family` value for that font, or `null` for the system font.
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="buyer_email" type="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.
    </ResponseField>

    <ResponseField name="buyer_id" type="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.
    </ResponseField>

    <ResponseField name="buyer_identity" type="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`
    </ResponseField>

    <ResponseField name="buyer_identity_at" type="string | null" required>
      When the buyer's identity was last established or strengthened, as an ISO 8601
      timestamp. `null` before a buyer is resolved.
    </ResponseField>

    <ResponseField name="buyer_identity_method" type="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`
    </ResponseField>

    <ResponseField name="checkout_configuration" type="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.
    </ResponseField>

    <ResponseField name="client_secret" type="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.
    </ResponseField>

    <ResponseField name="collect_tax_id" type="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.
    </ResponseField>

    <ResponseField name="created_at" type="string" required>
      When the session was created, as an ISO 8601 timestamp.
    </ResponseField>

    <ResponseField name="cta_label" type="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`
    </ResponseField>

    <ResponseField name="custom_field_responses" type="object[]" required>
      The buyer's answers to the plan's custom fields.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="id" type="string" required>
          The plan custom field this answers, prefixed `field_` — the `id` of the
          matching entry published by the `custom_fields` requirement.
        </ResponseField>

        <ResponseField name="value" type="string" required>
          The buyer's answer, as typed.
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="display_currency" type="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.
    </ResponseField>

    <ResponseField name="entry" type="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`.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="id" type="string" required>
          The waitlist entry created by the confirm, prefixed `entry_`.
        </ResponseField>

        <ResponseField name="status" type="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`
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="expires_at" type="string" required>
      When the session expires, as an ISO 8601 timestamp. An expired session cannot
      be updated or confirmed — start a new one.
    </ResponseField>

    <ResponseField name="invoice_due_at" type="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.
    </ResponseField>

    <ResponseField name="items" type="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.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="description" type="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.
        </ResponseField>

        <ResponseField name="expiration_days" type="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).
        </ResponseField>

        <ResponseField name="headline" type="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.
        </ResponseField>

        <ResponseField name="image_url" type="string | null" required>
          The item's square art image URL, or `null` when the seller uploaded none.
        </ResponseField>

        <ResponseField name="name" type="string" required>
          What this item is called, ready to render — the product's title, falling back
          to the seller's name. Never empty.
        </ResponseField>

        <ResponseField name="plan" type="string" required>
          The plan being purchased (`plan_…`). The plan is the price — sessions never
          carry client-asserted amounts.
        </ResponseField>

        <ResponseField name="quantity" type="integer" required>
          How many of the plan the buyer is purchasing. At least 1.
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="last_confirm_error" type="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.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="code" type="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`
        </ResponseField>

        <ResponseField name="message" type="string" required>
          A human-readable explanation of the failure, safe to show the buyer.
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="metadata" type="object | null" required>
      Free-form string-to-string map set at create. Whop never interprets it.
    </ResponseField>

    <ResponseField name="mode" type="string" required>
      `payment` charges the items at confirm; `setup` saves a payment method for later use.

      Available options: `payment`, `setup`
    </ResponseField>

    <ResponseField name="next_action" type="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.
    </ResponseField>

    <ResponseField name="object" type="string" required>
      Always `checkout_session`.
    </ResponseField>

    <ResponseField name="payment" type="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.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="id" type="string" required>
          The payment created by the confirm, prefixed `pay_`.
        </ResponseField>

        <ResponseField name="status" type="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`
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="payment_method_configuration" type="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.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="disabled" type="string[]" required>
          Payment methods this checkout withholds, even when the defaults would offer
          them.
        </ResponseField>

        <ResponseField name="enabled" type="string[]" required>
          Payment methods this checkout offers on top of whatever the defaults provide.
        </ResponseField>

        <ResponseField name="include_platform_defaults" type="boolean" required>
          Whether Whop's default set is the starting point. When `false`, only `enabled` is offered.
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="payment_method_required" type="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`.
    </ResponseField>

    <ResponseField name="phone_number" type="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.
    </ResponseField>

    <ResponseField name="promo" type="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.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="amount_off" type="number" required>
          What each covered charge is discounted by. Percentage discounts are
          represented as a decimal fraction; fixed-amount discounts are in `currency`.
        </ResponseField>

        <ResponseField name="code" type="string" required>
          The promo code, exactly as `promo_code` states it.
        </ResponseField>

        <ResponseField name="currency" type="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`
        </ResponseField>

        <ResponseField name="duration" type="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`
        </ResponseField>

        <ResponseField name="number_of_intervals" type="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.
        </ResponseField>

        <ResponseField name="promo_type" type="string" required>
          Whether the discount is percentage-based or a fixed amount.

          Available options: `percentage`, `flat_amount`
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="promo_code" type="string | null" required>
      The promo code applied to the quote, or `null`. Set it via update; the
      discount shows up in the quote.
    </ResponseField>

    <ResponseField name="quote" type="object" required>
      The current price of the items, computed by the server on every read. Confirm charges this number while it is fresh.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="base_amount" type="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`.
        </ResponseField>

        <ResponseField name="base_currency" type="string" required>
          The seller's own currency for these items, lowercase. Equal to `currency` when
          no conversion applied.
        </ResponseField>

        <ResponseField name="breakdown" type="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.

          <Accordion title="Properties" defaultOpen={true}>
            <ResponseField name="adjustments" type="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.

              <Accordion title="Properties" defaultOpen={true}>
                <ResponseField name="amount" type="object | null" required>
                  What this adjustment does to the total — negative for a discount. `null` only while `status` is `pending`.

                  <Accordion title="Properties" defaultOpen={true}>
                    <ResponseField name="amount" type="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.
                    </ResponseField>

                    <ResponseField name="currency" type="string" required>
                      Three-letter ISO 4217 currency code, lowercase.
                    </ResponseField>

                    <ResponseField name="decimals" type="integer" required>
                      How many decimal places the amount CARRIES — the precision the charge itself
                      runs at.
                    </ResponseField>

                    <ResponseField name="display_decimals" type="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.
                    </ResponseField>
                  </Accordion>
                </ResponseField>

                <ResponseField name="applied" type="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`
                </ResponseField>

                <ResponseField name="kind" type="string" required>
                  What changes the price: the promo's `discount`, the `buyer_fee` the charge adds, or `tax`.

                  Available options: `discount`, `buyer_fee`, `tax`
                </ResponseField>

                <ResponseField name="label" type="string" required>
                  What to show the buyer for this row.
                </ResponseField>

                <ResponseField name="rate" type="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.
                </ResponseField>

                <ResponseField name="status" type="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`
                </ResponseField>
              </Accordion>
            </ResponseField>

            <ResponseField name="currency" type="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`
            </ResponseField>

            <ResponseField name="display" type="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.

              <Accordion title="Properties" defaultOpen={true}>
                <ResponseField name="headline" type="object" required>
                  The hero: the figure (or trial length, or the word "Free") and the one-line context under it.

                  <Accordion title="Properties" defaultOpen={true}>
                    <ResponseField name="amount" type="object | null" required>
                      The figure to headline when `kind` is `amount` — already posture-correct. `null` on the other kinds.

                      <Accordion title="Properties" defaultOpen={true}>
                        <ResponseField name="amount" type="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.
                        </ResponseField>

                        <ResponseField name="currency" type="string" required>
                          Three-letter ISO 4217 currency code, lowercase.
                        </ResponseField>

                        <ResponseField name="decimals" type="integer" required>
                          How many decimal places the amount CARRIES — the precision the charge itself
                          runs at.
                        </ResponseField>

                        <ResponseField name="display_decimals" type="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.
                        </ResponseField>
                      </Accordion>
                    </ResponseField>

                    <ResponseField name="context" type="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.

                      <Accordion title="Properties" defaultOpen={true}>
                        <ResponseField name="amount" type="object | null">
                          The row's figure as a Money object, when it has one — what a surface formats in the buyer's locale.

                          <Accordion title="Properties" defaultOpen={true}>
                            <ResponseField name="amount" type="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.
                            </ResponseField>

                            <ResponseField name="currency" type="string" required>
                              Three-letter ISO 4217 currency code, lowercase.
                            </ResponseField>

                            <ResponseField name="decimals" type="integer" required>
                              How many decimal places the amount CARRIES — the precision the charge itself
                              runs at.
                            </ResponseField>

                            <ResponseField name="display_decimals" type="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.
                            </ResponseField>
                          </Accordion>
                        </ResponseField>

                        <ResponseField name="detail" type="object | null">
                          The typed parameters this row's wording is built from — the localization rail. Absent when the kind needs none.

                          <Accordion title="Properties" defaultOpen={true}>
                            <ResponseField name="access_days" type="integer">
                              How many days of access a one-time purchase grants, when it expires.
                            </ResponseField>

                            <ResponseField name="access_until" type="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.
                            </ResponseField>

                            <ResponseField name="applied" type="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`
                            </ResponseField>

                            <ResponseField name="charge_at" type="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.
                            </ResponseField>

                            <ResponseField name="code" type="string">
                              The promo code (uppercased) whose coverage this row states — "Then your first
                              month is free with FREETODAY".
                            </ResponseField>

                            <ResponseField name="initial_fee" type="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.

                              <Accordion title="Properties" defaultOpen={true}>
                                <ResponseField name="amount" type="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.
                                </ResponseField>

                                <ResponseField name="currency" type="string" required>
                                  Three-letter ISO 4217 currency code, lowercase.
                                </ResponseField>

                                <ResponseField name="decimals" type="integer" required>
                                  How many decimal places the amount CARRIES — the precision the charge itself
                                  runs at.
                                </ResponseField>

                                <ResponseField name="display_decimals" type="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.
                                </ResponseField>
                              </Accordion>
                            </ResponseField>

                            <ResponseField name="interval_days" type="integer">
                              Days between recurring charges, for wording the billing period (30 is monthly,
                              365 yearly).
                            </ResponseField>

                            <ResponseField name="invoice" type="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.
                            </ResponseField>

                            <ResponseField name="paid_trial" type="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.
                            </ResponseField>

                            <ResponseField name="rate" type="string">
                              The tax row's effective rate as a decimal fraction (`"0.0725"` is 7.25%), when
                              the calculation stated one.
                            </ResponseField>

                            <ResponseField name="remaining_payments" type="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.
                            </ResponseField>

                            <ResponseField name="total_payments" type="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.
                            </ResponseField>

                            <ResponseField name="trial_days" type="integer">
                              The free-trial length this row speaks about, in days.
                            </ResponseField>

                            <ResponseField name="without_tax" type="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.
                            </ResponseField>
                          </Accordion>
                        </ResponseField>

                        <ResponseField name="kind" type="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`
                        </ResponseField>

                        <ResponseField name="label" type="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).
                        </ResponseField>

                        <ResponseField name="status" type="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`
                        </ResponseField>

                        <ResponseField name="text" type="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`.
                        </ResponseField>
                      </Accordion>
                    </ResponseField>

                    <ResponseField name="free_until" type="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.
                    </ResponseField>

                    <ResponseField name="kind" type="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`
                    </ResponseField>

                    <ResponseField name="original_amount" type="object | null" required>
                      The pre-promo figure to strike through beside `amount`, or `null` when no discount moved today's charge.

                      <Accordion title="Properties" defaultOpen={true}>
                        <ResponseField name="amount" type="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.
                        </ResponseField>

                        <ResponseField name="currency" type="string" required>
                          Three-letter ISO 4217 currency code, lowercase.
                        </ResponseField>

                        <ResponseField name="decimals" type="integer" required>
                          How many decimal places the amount CARRIES — the precision the charge itself
                          runs at.
                        </ResponseField>

                        <ResponseField name="display_decimals" type="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.
                        </ResponseField>
                      </Accordion>
                    </ResponseField>

                    <ResponseField name="text" type="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`.
                    </ResponseField>

                    <ResponseField name="trial_days" type="integer | null" required>
                      The free-trial length when `kind` is `trial`, in days. `null` on the other kinds.
                    </ResponseField>
                  </Accordion>
                </ResponseField>

                <ResponseField name="sections" type="object" required>
                  The itemized sections below — line items, charges, totals, and the collapsible fee breakdown. All empty on a free checkout.

                  <Accordion title="Properties" defaultOpen={true}>
                    <ResponseField name="charges" type="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.

                      <Accordion title="Properties" defaultOpen={true}>
                        <ResponseField name="amount" type="object | null">
                          The row's figure as a Money object, when it has one — what a surface formats in the buyer's locale.

                          <Accordion title="Properties" defaultOpen={true}>
                            <ResponseField name="amount" type="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.
                            </ResponseField>

                            <ResponseField name="currency" type="string" required>
                              Three-letter ISO 4217 currency code, lowercase.
                            </ResponseField>

                            <ResponseField name="decimals" type="integer" required>
                              How many decimal places the amount CARRIES — the precision the charge itself
                              runs at.
                            </ResponseField>

                            <ResponseField name="display_decimals" type="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.
                            </ResponseField>
                          </Accordion>
                        </ResponseField>

                        <ResponseField name="detail" type="object | null">
                          The typed parameters this row's wording is built from — the localization rail. Absent when the kind needs none.

                          <Accordion title="Properties" defaultOpen={true}>
                            <ResponseField name="access_days" type="integer">
                              How many days of access a one-time purchase grants, when it expires.
                            </ResponseField>

                            <ResponseField name="access_until" type="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.
                            </ResponseField>

                            <ResponseField name="applied" type="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`
                            </ResponseField>

                            <ResponseField name="charge_at" type="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.
                            </ResponseField>

                            <ResponseField name="code" type="string">
                              The promo code (uppercased) whose coverage this row states — "Then your first
                              month is free with FREETODAY".
                            </ResponseField>

                            <ResponseField name="initial_fee" type="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.

                              <Accordion title="Properties" defaultOpen={true}>
                                <ResponseField name="amount" type="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.
                                </ResponseField>

                                <ResponseField name="currency" type="string" required>
                                  Three-letter ISO 4217 currency code, lowercase.
                                </ResponseField>

                                <ResponseField name="decimals" type="integer" required>
                                  How many decimal places the amount CARRIES — the precision the charge itself
                                  runs at.
                                </ResponseField>

                                <ResponseField name="display_decimals" type="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.
                                </ResponseField>
                              </Accordion>
                            </ResponseField>

                            <ResponseField name="interval_days" type="integer">
                              Days between recurring charges, for wording the billing period (30 is monthly,
                              365 yearly).
                            </ResponseField>

                            <ResponseField name="invoice" type="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.
                            </ResponseField>

                            <ResponseField name="paid_trial" type="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.
                            </ResponseField>

                            <ResponseField name="rate" type="string">
                              The tax row's effective rate as a decimal fraction (`"0.0725"` is 7.25%), when
                              the calculation stated one.
                            </ResponseField>

                            <ResponseField name="remaining_payments" type="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.
                            </ResponseField>

                            <ResponseField name="total_payments" type="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.
                            </ResponseField>

                            <ResponseField name="trial_days" type="integer">
                              The free-trial length this row speaks about, in days.
                            </ResponseField>

                            <ResponseField name="without_tax" type="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.
                            </ResponseField>
                          </Accordion>
                        </ResponseField>

                        <ResponseField name="kind" type="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`
                        </ResponseField>

                        <ResponseField name="label" type="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).
                        </ResponseField>

                        <ResponseField name="status" type="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`
                        </ResponseField>

                        <ResponseField name="text" type="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`.
                        </ResponseField>
                      </Accordion>
                    </ResponseField>

                    <ResponseField name="fee_breakdown" type="object[]" required>
                      The collapsible price breakdown: the `item_subtotal` beside the `service_fee`, present only when a fee actually charges today.

                      <Accordion title="Properties" defaultOpen={true}>
                        <ResponseField name="amount" type="object | null">
                          The row's figure as a Money object, when it has one — what a surface formats in the buyer's locale.

                          <Accordion title="Properties" defaultOpen={true}>
                            <ResponseField name="amount" type="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.
                            </ResponseField>

                            <ResponseField name="currency" type="string" required>
                              Three-letter ISO 4217 currency code, lowercase.
                            </ResponseField>

                            <ResponseField name="decimals" type="integer" required>
                              How many decimal places the amount CARRIES — the precision the charge itself
                              runs at.
                            </ResponseField>

                            <ResponseField name="display_decimals" type="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.
                            </ResponseField>
                          </Accordion>
                        </ResponseField>

                        <ResponseField name="detail" type="object | null">
                          The typed parameters this row's wording is built from — the localization rail. Absent when the kind needs none.

                          <Accordion title="Properties" defaultOpen={true}>
                            <ResponseField name="access_days" type="integer">
                              How many days of access a one-time purchase grants, when it expires.
                            </ResponseField>

                            <ResponseField name="access_until" type="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.
                            </ResponseField>

                            <ResponseField name="applied" type="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`
                            </ResponseField>

                            <ResponseField name="charge_at" type="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.
                            </ResponseField>

                            <ResponseField name="code" type="string">
                              The promo code (uppercased) whose coverage this row states — "Then your first
                              month is free with FREETODAY".
                            </ResponseField>

                            <ResponseField name="initial_fee" type="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.

                              <Accordion title="Properties" defaultOpen={true}>
                                <ResponseField name="amount" type="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.
                                </ResponseField>

                                <ResponseField name="currency" type="string" required>
                                  Three-letter ISO 4217 currency code, lowercase.
                                </ResponseField>

                                <ResponseField name="decimals" type="integer" required>
                                  How many decimal places the amount CARRIES — the precision the charge itself
                                  runs at.
                                </ResponseField>

                                <ResponseField name="display_decimals" type="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.
                                </ResponseField>
                              </Accordion>
                            </ResponseField>

                            <ResponseField name="interval_days" type="integer">
                              Days between recurring charges, for wording the billing period (30 is monthly,
                              365 yearly).
                            </ResponseField>

                            <ResponseField name="invoice" type="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.
                            </ResponseField>

                            <ResponseField name="paid_trial" type="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.
                            </ResponseField>

                            <ResponseField name="rate" type="string">
                              The tax row's effective rate as a decimal fraction (`"0.0725"` is 7.25%), when
                              the calculation stated one.
                            </ResponseField>

                            <ResponseField name="remaining_payments" type="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.
                            </ResponseField>

                            <ResponseField name="total_payments" type="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.
                            </ResponseField>

                            <ResponseField name="trial_days" type="integer">
                              The free-trial length this row speaks about, in days.
                            </ResponseField>

                            <ResponseField name="without_tax" type="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.
                            </ResponseField>
                          </Accordion>
                        </ResponseField>

                        <ResponseField name="kind" type="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`
                        </ResponseField>

                        <ResponseField name="label" type="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).
                        </ResponseField>

                        <ResponseField name="status" type="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`
                        </ResponseField>

                        <ResponseField name="text" type="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`.
                        </ResponseField>
                      </Accordion>
                    </ResponseField>

                    <ResponseField name="line_items" type="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.

                      <Accordion title="Properties" defaultOpen={true}>
                        <ResponseField name="amount" type="object | null">
                          The row's figure as a Money object, when it has one — what a surface formats in the buyer's locale.

                          <Accordion title="Properties" defaultOpen={true}>
                            <ResponseField name="amount" type="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.
                            </ResponseField>

                            <ResponseField name="currency" type="string" required>
                              Three-letter ISO 4217 currency code, lowercase.
                            </ResponseField>

                            <ResponseField name="decimals" type="integer" required>
                              How many decimal places the amount CARRIES — the precision the charge itself
                              runs at.
                            </ResponseField>

                            <ResponseField name="display_decimals" type="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.
                            </ResponseField>
                          </Accordion>
                        </ResponseField>

                        <ResponseField name="detail" type="object | null">
                          The typed parameters this row's wording is built from — the localization rail. Absent when the kind needs none.

                          <Accordion title="Properties" defaultOpen={true}>
                            <ResponseField name="access_days" type="integer">
                              How many days of access a one-time purchase grants, when it expires.
                            </ResponseField>

                            <ResponseField name="access_until" type="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.
                            </ResponseField>

                            <ResponseField name="applied" type="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`
                            </ResponseField>

                            <ResponseField name="charge_at" type="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.
                            </ResponseField>

                            <ResponseField name="code" type="string">
                              The promo code (uppercased) whose coverage this row states — "Then your first
                              month is free with FREETODAY".
                            </ResponseField>

                            <ResponseField name="initial_fee" type="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.

                              <Accordion title="Properties" defaultOpen={true}>
                                <ResponseField name="amount" type="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.
                                </ResponseField>

                                <ResponseField name="currency" type="string" required>
                                  Three-letter ISO 4217 currency code, lowercase.
                                </ResponseField>

                                <ResponseField name="decimals" type="integer" required>
                                  How many decimal places the amount CARRIES — the precision the charge itself
                                  runs at.
                                </ResponseField>

                                <ResponseField name="display_decimals" type="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.
                                </ResponseField>
                              </Accordion>
                            </ResponseField>

                            <ResponseField name="interval_days" type="integer">
                              Days between recurring charges, for wording the billing period (30 is monthly,
                              365 yearly).
                            </ResponseField>

                            <ResponseField name="invoice" type="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.
                            </ResponseField>

                            <ResponseField name="paid_trial" type="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.
                            </ResponseField>

                            <ResponseField name="rate" type="string">
                              The tax row's effective rate as a decimal fraction (`"0.0725"` is 7.25%), when
                              the calculation stated one.
                            </ResponseField>

                            <ResponseField name="remaining_payments" type="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.
                            </ResponseField>

                            <ResponseField name="total_payments" type="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.
                            </ResponseField>

                            <ResponseField name="trial_days" type="integer">
                              The free-trial length this row speaks about, in days.
                            </ResponseField>

                            <ResponseField name="without_tax" type="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.
                            </ResponseField>
                          </Accordion>
                        </ResponseField>

                        <ResponseField name="kind" type="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`
                        </ResponseField>

                        <ResponseField name="label" type="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).
                        </ResponseField>

                        <ResponseField name="status" type="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`
                        </ResponseField>

                        <ResponseField name="text" type="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`.
                        </ResponseField>
                      </Accordion>
                    </ResponseField>

                    <ResponseField name="totals" type="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`.

                      <Accordion title="Properties" defaultOpen={true}>
                        <ResponseField name="amount" type="object | null">
                          The row's figure as a Money object, when it has one — what a surface formats in the buyer's locale.

                          <Accordion title="Properties" defaultOpen={true}>
                            <ResponseField name="amount" type="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.
                            </ResponseField>

                            <ResponseField name="currency" type="string" required>
                              Three-letter ISO 4217 currency code, lowercase.
                            </ResponseField>

                            <ResponseField name="decimals" type="integer" required>
                              How many decimal places the amount CARRIES — the precision the charge itself
                              runs at.
                            </ResponseField>

                            <ResponseField name="display_decimals" type="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.
                            </ResponseField>
                          </Accordion>
                        </ResponseField>

                        <ResponseField name="detail" type="object | null">
                          The typed parameters this row's wording is built from — the localization rail. Absent when the kind needs none.

                          <Accordion title="Properties" defaultOpen={true}>
                            <ResponseField name="access_days" type="integer">
                              How many days of access a one-time purchase grants, when it expires.
                            </ResponseField>

                            <ResponseField name="access_until" type="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.
                            </ResponseField>

                            <ResponseField name="applied" type="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`
                            </ResponseField>

                            <ResponseField name="charge_at" type="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.
                            </ResponseField>

                            <ResponseField name="code" type="string">
                              The promo code (uppercased) whose coverage this row states — "Then your first
                              month is free with FREETODAY".
                            </ResponseField>

                            <ResponseField name="initial_fee" type="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.

                              <Accordion title="Properties" defaultOpen={true}>
                                <ResponseField name="amount" type="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.
                                </ResponseField>

                                <ResponseField name="currency" type="string" required>
                                  Three-letter ISO 4217 currency code, lowercase.
                                </ResponseField>

                                <ResponseField name="decimals" type="integer" required>
                                  How many decimal places the amount CARRIES — the precision the charge itself
                                  runs at.
                                </ResponseField>

                                <ResponseField name="display_decimals" type="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.
                                </ResponseField>
                              </Accordion>
                            </ResponseField>

                            <ResponseField name="interval_days" type="integer">
                              Days between recurring charges, for wording the billing period (30 is monthly,
                              365 yearly).
                            </ResponseField>

                            <ResponseField name="invoice" type="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.
                            </ResponseField>

                            <ResponseField name="paid_trial" type="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.
                            </ResponseField>

                            <ResponseField name="rate" type="string">
                              The tax row's effective rate as a decimal fraction (`"0.0725"` is 7.25%), when
                              the calculation stated one.
                            </ResponseField>

                            <ResponseField name="remaining_payments" type="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.
                            </ResponseField>

                            <ResponseField name="total_payments" type="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.
                            </ResponseField>

                            <ResponseField name="trial_days" type="integer">
                              The free-trial length this row speaks about, in days.
                            </ResponseField>

                            <ResponseField name="without_tax" type="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.
                            </ResponseField>
                          </Accordion>
                        </ResponseField>

                        <ResponseField name="kind" type="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`
                        </ResponseField>

                        <ResponseField name="label" type="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).
                        </ResponseField>

                        <ResponseField name="status" type="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`
                        </ResponseField>

                        <ResponseField name="text" type="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`.
                        </ResponseField>
                      </Accordion>
                    </ResponseField>
                  </Accordion>
                </ResponseField>
              </Accordion>
            </ResponseField>

            <ResponseField name="lines" type="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.

              <Accordion title="Properties" defaultOpen={true}>
                <ResponseField name="amount" type="object" required>
                  The line's own total — `unit_amount` × `quantity`, before any adjustment.

                  <Accordion title="Properties" defaultOpen={true}>
                    <ResponseField name="amount" type="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.
                    </ResponseField>

                    <ResponseField name="currency" type="string" required>
                      Three-letter ISO 4217 currency code, lowercase.
                    </ResponseField>

                    <ResponseField name="decimals" type="integer" required>
                      How many decimal places the amount CARRIES — the precision the charge itself
                      runs at.
                    </ResponseField>

                    <ResponseField name="display_decimals" type="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.
                    </ResponseField>
                  </Accordion>
                </ResponseField>

                <ResponseField name="description" type="string" required>
                  What to show the buyer for this line.
                </ResponseField>

                <ResponseField name="kind" type="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`
                </ResponseField>

                <ResponseField name="quantity" type="integer" required>
                  How many.
                </ResponseField>

                <ResponseField name="unit_amount" type="object" required>
                  Price of one, before any adjustment.

                  <Accordion title="Properties" defaultOpen={true}>
                    <ResponseField name="amount" type="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.
                    </ResponseField>

                    <ResponseField name="currency" type="string" required>
                      Three-letter ISO 4217 currency code, lowercase.
                    </ResponseField>

                    <ResponseField name="decimals" type="integer" required>
                      How many decimal places the amount CARRIES — the precision the charge itself
                      runs at.
                    </ResponseField>

                    <ResponseField name="display_decimals" type="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.
                    </ResponseField>
                  </Accordion>
                </ResponseField>
              </Accordion>
            </ResponseField>

            <ResponseField name="subtotal" type="object" required>
              The lines summed, before any adjustment.

              <Accordion title="Properties" defaultOpen={true}>
                <ResponseField name="amount" type="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.
                </ResponseField>

                <ResponseField name="currency" type="string" required>
                  Three-letter ISO 4217 currency code, lowercase.
                </ResponseField>

                <ResponseField name="decimals" type="integer" required>
                  How many decimal places the amount CARRIES — the precision the charge itself
                  runs at.
                </ResponseField>

                <ResponseField name="display_decimals" type="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.
                </ResponseField>
              </Accordion>
            </ResponseField>

            <ResponseField name="total" type="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`.

              <Accordion title="Properties" defaultOpen={true}>
                <ResponseField name="amount" type="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.
                </ResponseField>

                <ResponseField name="currency" type="string" required>
                  Three-letter ISO 4217 currency code, lowercase.
                </ResponseField>

                <ResponseField name="decimals" type="integer" required>
                  How many decimal places the amount CARRIES — the precision the charge itself
                  runs at.
                </ResponseField>

                <ResponseField name="display_decimals" type="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.
                </ResponseField>
              </Accordion>
            </ResponseField>

            <ResponseField name="upcoming" type="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.
            </ResponseField>
          </Accordion>
        </ResponseField>

        <ResponseField name="currency" type="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.
        </ResponseField>

        <ResponseField name="exchange_rate" type="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.
        </ResponseField>

        <ResponseField name="expires_at" type="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.
        </ResponseField>

        <ResponseField name="quoted_at" type="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.
        </ResponseField>

        <ResponseField name="trial_skipped" type="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.
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="redirect_url" type="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.
    </ResponseField>

    <ResponseField name="requirements" type="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`.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="fields" type="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.

          <Accordion title="Properties" defaultOpen={true}>
            <ResponseField name="id" type="string" required>
              The question's ID, prefixed `field_`. Echo it as the `id` of the matching
              `custom_field_responses` entry.
            </ResponseField>

            <ResponseField name="description" type="string | null" required>
              The seller's longer explanation of the question, or `null`.
            </ResponseField>

            <ResponseField name="field_type" type="string" required>
              What kind of input to render. `text` today.

              Available options: `text`
            </ResponseField>

            <ResponseField name="name" type="string" required>
              The question as the seller wrote it — the field's label.
            </ResponseField>

            <ResponseField name="placeholder" type="string | null" required>
              Placeholder text for the input, or `null`.
            </ResponseField>

            <ResponseField name="required" type="boolean" required>
              Whether confirm refuses without an answer. An unanswered required question is refused with `custom_field_invalid`.
            </ResponseField>
          </Accordion>
        </ResponseField>

        <ResponseField name="type" type="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`
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="return_url" type="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).
    </ResponseField>

    <ResponseField name="seller" type="object" required>
      The seller this checkout purchases from.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="id" type="string" required>
          Account ID, prefixed `biz_`.
        </ResponseField>

        <ResponseField name="logo_url" type="string | null" required>
          The seller's logo image URL, or `null` when they have not uploaded one.
        </ResponseField>

        <ResponseField name="redirect_purchase_url" type="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.
        </ResponseField>

        <ResponseField name="route" type="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.
        </ResponseField>

        <ResponseField name="terms" type="object" required>
          The seller's checkout legal surface: whether explicit acceptance is required, and the policy documents it covers.

          <Accordion title="Properties" defaultOpen={true}>
            <ResponseField name="eula_url" type="string | null" required>
              The seller's end-user licence agreement, or `null` if they have not published
              one.
            </ResponseField>

            <ResponseField name="privacy_policy_url" type="string | null" required>
              The seller's privacy policy, or `null` if they have not published one.
            </ResponseField>

            <ResponseField name="required" type="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.
            </ResponseField>

            <ResponseField name="return_policy_url" type="string | null" required>
              The seller's return policy, or `null` if they have not published one.
            </ResponseField>

            <ResponseField name="terms_url" type="string | null" required>
              The seller's terms of service, or `null` if they have not published one.
            </ResponseField>
          </Accordion>
        </ResponseField>

        <ResponseField name="title" type="string" required>
          The seller's public name, as the buyer knows them.
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="shipping_address" type="object | null" required>
      Where physical goods ship, or `null`. Only the keys the buyer supplied are present.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="city" type="string">
          City name.
        </ResponseField>

        <ResponseField name="country" type="string">
          ISO 3166-1 alpha-2 country code, such as `US`.
        </ResponseField>

        <ResponseField name="line1" type="string">
          First line of the street address.
        </ResponseField>

        <ResponseField name="line2" type="string">
          Second line of the street address.
        </ResponseField>

        <ResponseField name="name" type="string">
          The recipient's full name, as it should appear on the shipping label.
        </ResponseField>

        <ResponseField name="postal_code" type="string">
          Postal or ZIP code.
        </ResponseField>

        <ResponseField name="state" type="string">
          State, province, or region code, such as `CA`.
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="show_promo_code_input" type="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.
    </ResponseField>

    <ResponseField name="status" type="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`
    </ResponseField>

    <ResponseField name="tax_behavior" type="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`
    </ResponseField>

    <ResponseField name="tax_id" type="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.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="type" type="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`
        </ResponseField>

        <ResponseField name="value" type="string" required>
          The registration number, stored as the buyer entered it (whitespace removed).
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="three_ds_level" type="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`
    </ResponseField>

    <ResponseField name="top_up_membership" type="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.
    </ResponseField>

    <ResponseField name="transfer" type="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.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="code" type="string" required>
          The 40-character transfer code this checkout was opened from — the same value
          the link carried.
        </ResponseField>

        <ResponseField name="origin_expires_at" type="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.
        </ResponseField>

        <ResponseField name="origin_renewal_period_end" type="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.
        </ResponseField>
      </Accordion>
    </ResponseField>
  </Column>

  <Column>
    <div className="api-resource-sticky-example">
      ```json CheckoutSession theme={null}
      {
      	"id": "chs_xxxxxxxxxxxxxx",
      	"object": "checkout_session",
      	"status": "open",
      	"mode": "payment",
      	"seller": {
      		"id": "biz_xxxxxxxxxxxxxx",
      		"title": "Pickaxe",
      		"logo_url": null,
      		"route": "pickaxe",
      		"redirect_purchase_url": null,
      		"terms": {
      			"required": false,
      			"terms_url": null,
      			"privacy_policy_url": null,
      			"return_policy_url": null,
      			"eula_url": null
      		}
      	},
      	"checkout_configuration": null,
      	"items": [
      		{
      			"plan": "plan_xxxxxxxxxxxxx",
      			"name": "Pickaxe Analytics",
      			"headline": "Real-time data analytics for creators",
      			"description": "Track your revenue, members, and growth in real time.",
      			"image_url": null,
      			"quantity": 1,
      			"expiration_days": null
      		}
      	],
      	"invoice_due_at": null,
      	"display_currency": "usd",
      	"available_currencies": ["usd"],
      	"quote": {
      		"currency": "usd",
      		"breakdown": {
      			"currency": "usd",
      			"lines": [
      				{
      					"kind": "plan",
      					"description": "Pickaxe Analytics",
      					"quantity": 1,
      					"unit_amount": {
      						"amount": "9.99",
      						"currency": "usd",
      						"decimals": 2,
      						"display_decimals": 2
      					},
      					"amount": {
      						"amount": "9.99",
      						"currency": "usd",
      						"decimals": 2,
      						"display_decimals": 2
      					}
      				}
      			],
      			"subtotal": {
      				"amount": "9.99",
      				"currency": "usd",
      				"decimals": 2,
      				"display_decimals": 2
      			},
      			"adjustments": [
      				{
      					"kind": "discount",
      					"label": "Discount",
      					"amount": {
      						"amount": "-2.00",
      						"currency": "usd",
      						"decimals": 2,
      						"display_decimals": 2
      					},
      					"applied": "added"
      				}
      			],
      			"total": {
      				"amount": "7.99",
      				"currency": "usd",
      				"decimals": 2,
      				"display_decimals": 2
      			},
      			"upcoming": [
      				{
      					"type": "recurring",
      					"description": "Subscription",
      					"amount": {
      						"amount": "9.99",
      						"currency": "usd",
      						"decimals": 2,
      						"display_decimals": 2
      					},
      					"charge_at": "2026-02-01T12:00:00.000Z",
      					"interval_days": 30
      				}
      			],
      			"display": {
      				"headline": {
      					"kind": "amount",
      					"text": "$7.99",
      					"amount": {
      						"amount": "7.99",
      						"currency": "usd",
      						"decimals": 2,
      						"display_decimals": 2
      					},
      					"original_amount": {
      						"amount": "9.99",
      						"currency": "usd",
      						"decimals": 2,
      						"display_decimals": 2
      					},
      					"trial_days": null,
      					"free_until": null,
      					"context": [
      						{
      							"kind": "due_today",
      							"text": "Due today"
      						}
      					]
      				},
      				"sections": {
      					"line_items": [
      						{
      							"kind": "renewal_fee",
      							"label": "Subscription",
      							"text": "$9.99",
      							"amount": {
      								"amount": "9.99",
      								"currency": "usd",
      								"decimals": 2,
      								"display_decimals": 2
      							}
      						}
      					],
      					"charges": [
      						{
      							"kind": "tax_today",
      							"label": "Estimated tax due today",
      							"text": "$0.00",
      							"amount": {
      								"amount": "0.00",
      								"currency": "usd",
      								"decimals": 2,
      								"display_decimals": 2
      							}
      						}
      					],
      					"totals": [
      						{
      							"kind": "total_due_today",
      							"label": "Total due today",
      							"text": "$7.99",
      							"amount": {
      								"amount": "7.99",
      								"currency": "usd",
      								"decimals": 2,
      								"display_decimals": 2
      							}
      						}
      					],
      					"fee_breakdown": [
      						{
      							"kind": "item_subtotal",
      							"label": "Subtotal",
      							"text": "$9.99",
      							"amount": {
      								"amount": "9.99",
      								"currency": "usd",
      								"decimals": 2,
      								"display_decimals": 2
      							}
      						}
      					]
      				}
      			}
      		},
      		"base_currency": "usd",
      		"base_amount": 9.99,
      		"exchange_rate": null,
      		"quoted_at": "2026-01-01T12:00:00.000Z",
      		"expires_at": "2026-01-01T12:15:00.000Z",
      		"trial_skipped": false
      	},
      	"transfer": null,
      	"top_up_membership": null,
      	"payment_method_required": true,
      	"cta_label": "pay",
      	"tax_behavior": null,
      	"buyer_id": null,
      	"buyer_email": null,
      	"buyer_identity": null,
      	"buyer_identity_method": null,
      	"buyer_identity_at": null,
      	"promo_code": null,
      	"promo": null,
      	"show_promo_code_input": true,
      	"affiliate_code": null,
      	"custom_field_responses": [
      		{
      			"id": "field_xxxxxxxxxxxxxx",
      			"value": "buyer#1234"
      		}
      	],
      	"shipping_address": null,
      	"phone_number": null,
      	"tax_id": null,
      	"collect_tax_id": false,
      	"metadata": null,
      	"return_url": null,
      	"redirect_url": null,
      	"three_ds_level": null,
      	"payment_method_configuration": null,
      	"branding": null,
      	"payment": null,
      	"entry": null,
      	"requirements": [
      		{
      			"type": "email",
      			"fields": null
      		}
      	],
      	"next_action": null,
      	"last_confirm_error": null,
      	"created_at": "2026-01-01T12:00:00.000Z",
      	"expires_at": "2026-01-02T12:00:00.000Z"
      }
      ```
    </div>
  </Column>
</Columns>
