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

# How Checkout works

> The lifecycle, section ordering, and submit flow of the Checkout element.

Checkout wraps every element you would otherwise mount separately into a single lifecycle. This page walks through what happens between `overflow.checkout(...)` and `onSubmit`.

## Lifecycle

1. **Create.** `overflow.checkout(options)` returns a handle. No network calls yet.
2. **Mount.** `checkout.mount('#host')` renders a loading skeleton, then fetches your merchant payment settings from the Overflow API.
3. **Ready.** Once configuration loads, Checkout renders the configured sections and fires `onReady`.
4. **Interact.** As the shopper types or selects fields, `onChange` fires with the aggregated `{ value, complete, errors }`.
5. **Submit.** The submit button inside Checkout (or your programmatic `checkout.submit()` call) validates every section, tokenizes the selected payment method, and fires `onSubmit` with the payload.
6. **Authorize.** Forward the payload to your server, which calls the Overflow API to authorize the charge with your secret key.

## Section order

Sections render in this default order:

1. Contact
2. Shipping address
3. Billing address
4. Payment methods
5. Custom elements

Reorder with `options.order`. Unlisted sections fall through in default order after the ones you listed:

```javascript theme={null}
overflow.checkout({
  paymentMethods: ['card', 'bank'],
  order: ['paymentMethods'],   // Picker first, then the rest.
});
```

Entries for sections you did not configure are no-ops at render time; they do not force a section to appear.

## Payment method order

Payment methods render in the order you pass:

```javascript theme={null}
overflow.checkout({
  paymentMethods: ['applePay', 'googlePay', 'card', 'bank'],
});
```

Methods that fail a runtime check (a wallet on `http://`, a wallet that reports unavailable, a missing configuration) are hidden without shifting siblings. If a method becomes available later in the session, it slots back into its original position.

`defaultPaymentMethod`, when set, overrides the initial selection. If the default is unavailable at runtime, the first available method wins.

## Contact block

Contact is opt-in. Omit `contact` (or pass `{}`) to render Checkout with no contact fields.

```javascript theme={null}
overflow.checkout({
  paymentMethods: ['card'],
  contact: {
    email: {},
    fullName: { splitMode: 'horizontal' },
    phone: { defaultCountry: 'US' },
    companyName: {},
  },
});
```

Any key you include with an object value is enabled. Order inside the contact block is `email → fullName → companyName → phone`; override with `contact.order`.

## Addresses

Set `billingAddress` and/or `shippingAddress` to enable those sections. Each accepts every option the standalone element accepts.

```javascript theme={null}
overflow.checkout({
  paymentMethods: ['card'],
  billingAddress: {},
  shippingAddress: {
    header: { text: 'Shipping address' },
    fields: {
      fullName: {},
      country: { supportedCountries: ['US', 'CA'] },
    },
  },
});
```

## Custom elements

Custom elements slot in via `customElements`. Each entry is one mounted child managed by Checkout.

```javascript theme={null}
overflow.checkout({
  paymentMethods: ['card'],
  customElements: {
    giftMessage: { elementType: 'text', label: 'Gift message (optional)' },
    coverFee: { elementType: 'checkbox', label: 'Cover the processing fee' },
  },
});
```

The default position of the custom block is after Payment methods. Reorder via `order: ['contact', 'customElements', 'paymentMethods']`.

## Submit flow

Calling `checkout.submit()` (or the internal submit button firing) does the following in one pass:

1. Flush any pending debounced validation on every mounted child.
2. Collect per-section errors, tagged by `source`.
3. If there are errors, fire `onError` with the aggregated `fieldErrors` and stop.
4. Otherwise, tokenize the selected payment method.
5. Fire `onSubmit` with `{ value }` where `value` carries the method, the tokenized payment payload, and every configured section (contact, addresses, custom elements).

Wallets follow a slightly different path: the wallet button opens its own sheet, and the tokenized payload arrives on `onSubmit` from the sheet directly. Contact and address data collected inside the wallet sheet are folded into `value` alongside the payment payload.

## Update in place

You can change Checkout options after mount:

```javascript theme={null}
checkout.update({
  paymentMethods: ['card', 'bank', 'applePay'],
  card: { fields: { postalCode: { hidden: true } } },
});
```

The SDK diffs the new options and re-renders only the affected sections. Shopper input in unaffected fields is preserved.

## Programmatic access to custom elements

Reach into a configured custom slot with `checkout.getCustomElement(name)`:

```javascript theme={null}
const gift = checkout.getCustomElement('giftMessage');
gift?.on('onChange', ({ value }) => console.log(value));
```

Returns `null` if the slot is not configured. Built-in sub-elements (email, card, etc.) are not exposed this way; their values are already on the aggregated envelope.

## Next steps

<CardGroup cols={2}>
  <Card title="Best practices" icon="lightbulb" href="/payment-elements/elements/checkout/best-practices">
    Recommendations for real integrations.
  </Card>

  <Card title="Sections" icon="layer-group" href="/payment-elements/elements/checkout/sections/overview">
    Per-section configuration.
  </Card>
</CardGroup>
