# `LatticeStripe.Checkout.Session`
[🔗](https://github.com/szTheory/lattice_stripe/blob/v1.1.0/lib/lattice_stripe/checkout/session.ex#L1)

Operations on Stripe Checkout Session objects.

Checkout Sessions represent a one-time payment page hosted by Stripe. They support
three modes:

- **payment** — one-time payment with line items
- **subscription** — recurring payment linked to a subscription
- **setup** — collect payment method details without charging

## Key behaviors

- The `mode` parameter is required when creating a session — an `ArgumentError` is
  raised immediately (pre-network) if it is missing.
- Checkout Sessions cannot be updated after creation. Use `expire/4` to cancel
  an open session.
- Some fields can be modified via the Stripe Dashboard but not through the API.
- The `client_secret` field is hidden from `Inspect` output for security.
- PII fields (`customer_email`, `customer_details`, `shipping_details`) are hidden
  from `Inspect` output.

## Usage

    client = LatticeStripe.Client.new!(api_key: "sk_live_...", finch: MyApp.Finch)

    # Create a payment mode session
    {:ok, session} = LatticeStripe.Checkout.Session.create(client, %{
      "mode" => "payment",
      "success_url" => "https://example.com/success?session_id={CHECKOUT_SESSION_ID}",
      "cancel_url" => "https://example.com/cancel",
      "line_items" => [%{"price" => "price_...", "quantity" => 1}]
    })

    # Create a subscription mode session
    {:ok, session} = LatticeStripe.Checkout.Session.create(client, %{
      "mode" => "subscription",
      "success_url" => "https://example.com/success",
      "line_items" => [%{"price" => "price_monthly_...", "quantity" => 1}]
    })

    # Create a setup mode session (collect payment method, no charge)
    {:ok, session} = LatticeStripe.Checkout.Session.create(client, %{
      "mode" => "setup",
      "success_url" => "https://example.com/success",
      "customer" => "cus_..."
    })

    # Retrieve a session
    {:ok, session} = LatticeStripe.Checkout.Session.retrieve(client, session.id)

    # Expire an open session
    {:ok, expired} = LatticeStripe.Checkout.Session.expire(client, session.id)

    # List line items
    {:ok, resp} = LatticeStripe.Checkout.Session.list_line_items(client, session.id)
    items = resp.data.data  # [%LineItem{}, ...]

    # Stream all sessions lazily
    client
    |> LatticeStripe.Checkout.Session.stream!()
    |> Stream.take(100)
    |> Enum.each(&process_session/1)

## Stripe API Reference

See the [Stripe Checkout Session API](https://docs.stripe.com/api/checkout/sessions) for
the full object reference and available parameters.

# `t`

```elixir
@type t() :: %LatticeStripe.Checkout.Session{
  adaptive_pricing: map() | nil,
  after_expiration: map() | nil,
  allow_promotion_codes: boolean() | nil,
  amount_subtotal: integer() | nil,
  amount_total: integer() | nil,
  automatic_tax: map() | nil,
  billing_address_collection: String.t() | nil,
  cancel_url: String.t() | nil,
  client_reference_id: String.t() | nil,
  client_secret: String.t() | nil,
  consent: map() | nil,
  consent_collection: map() | nil,
  created: integer() | nil,
  currency: String.t() | nil,
  currency_conversion: map() | nil,
  custom_fields: [map()] | nil,
  custom_text: map() | nil,
  customer: String.t() | nil,
  customer_creation: String.t() | nil,
  customer_details: map() | nil,
  customer_email: String.t() | nil,
  discounts: [map()] | nil,
  expires_at: integer() | nil,
  extra: map(),
  id: String.t() | nil,
  invoice: String.t() | nil,
  invoice_creation: map() | nil,
  line_items: map() | nil,
  livemode: boolean() | nil,
  locale: String.t() | nil,
  metadata: map() | nil,
  mode: String.t() | nil,
  object: String.t(),
  payment_intent: String.t() | nil,
  payment_link: String.t() | nil,
  payment_method_collection: String.t() | nil,
  payment_method_configuration_details: map() | nil,
  payment_method_options: map() | nil,
  payment_method_types: [String.t()] | nil,
  payment_status: String.t() | nil,
  phone_number_collection: map() | nil,
  recovered_from: String.t() | nil,
  redirect_on_completion: String.t() | nil,
  return_url: String.t() | nil,
  setup_intent: String.t() | nil,
  shipping_address_collection: map() | nil,
  shipping_cost: map() | nil,
  shipping_details: map() | nil,
  shipping_options: [map()] | nil,
  status: String.t() | nil,
  submit_type: String.t() | nil,
  subscription: String.t() | nil,
  success_url: String.t() | nil,
  tax_id_collection: map() | nil,
  total_details: map() | nil,
  ui_mode: String.t() | nil,
  url: String.t() | nil
}
```

A Stripe Checkout Session object.

See the [Stripe Checkout Session API](https://docs.stripe.com/api/checkout/sessions/object) for field definitions.

# `create`

```elixir
@spec create(LatticeStripe.Client.t(), map(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}
```

Creates a new Checkout Session.

Sends `POST /v1/checkout/sessions` with the given params and returns
`{:ok, %Checkout.Session{}}`. The `mode` param is required — an `ArgumentError`
is raised immediately (before any network call) if it is missing.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `params` - Map of session attributes. **Required:** `"mode"` (`"payment"`, `"subscription"`, or `"setup"`).
- `opts` - Per-request overrides (e.g., `[idempotency_key: "..."]`)

## Returns

- `{:ok, %Checkout.Session{}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

## Notes

- For `"payment"` and `"subscription"` modes, `"success_url"` is typically required.
- For embedded mode sessions (`ui_mode: "embedded"`), use `"return_url"` instead.
- The hosted Checkout page URL is in `session.url`.

## Examples

    # Payment mode
    {:ok, session} = LatticeStripe.Checkout.Session.create(client, %{
      "mode" => "payment",
      "success_url" => "https://example.com/success",
      "cancel_url" => "https://example.com/cancel",
      "line_items" => [%{"price" => "price_...", "quantity" => 1}]
    })

    # Subscription mode
    {:ok, session} = LatticeStripe.Checkout.Session.create(client, %{
      "mode" => "subscription",
      "success_url" => "https://example.com/success",
      "line_items" => [%{"price" => "price_monthly_...", "quantity" => 1}]
    })

    # Setup mode (collect payment method, no charge)
    {:ok, session} = LatticeStripe.Checkout.Session.create(client, %{
      "mode" => "setup",
      "success_url" => "https://example.com/success",
      "customer" => "cus_..."
    })

# `create!`

```elixir
@spec create!(LatticeStripe.Client.t(), map(), keyword()) :: t()
```

Like `create/3` but raises `LatticeStripe.Error` on failure.
Also raises `ArgumentError` when `mode` param is missing.

# `expire`

```elixir
@spec expire(LatticeStripe.Client.t(), String.t(), map(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}
```

Expires an open Checkout Session.

Sends `POST /v1/checkout/sessions/:id/expire` and returns `{:ok, %Checkout.Session{status: "expired"}}`.
Only sessions with `status: "open"` can be expired.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The session ID string
- `params` - Optional params (typically empty `%{}`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %Checkout.Session{status: "expired"}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

## Example

    {:ok, session} = LatticeStripe.Checkout.Session.expire(client, "cs_...")

# `expire!`

```elixir
@spec expire!(LatticeStripe.Client.t(), String.t(), map(), keyword()) :: t()
```

Like `expire/4` but raises `LatticeStripe.Error` on failure.

# `from_map`

```elixir
@spec from_map(map()) :: t()
```

Converts a decoded Stripe API map to a `%Checkout.Session{}` struct.

Maps all known Stripe Checkout Session fields. Any unrecognized fields are
collected into the `extra` map so no data is silently lost.

## Example

    session = LatticeStripe.Checkout.Session.from_map(%{
      "id" => "cs_...",
      "object" => "checkout.session",
      "mode" => "payment",
      "status" => "open"
    })

# `list`

```elixir
@spec list(LatticeStripe.Client.t(), map(), keyword()) ::
  {:ok, LatticeStripe.Response.t()} | {:error, LatticeStripe.Error.t()}
```

Lists Checkout Sessions with optional filters.

Sends `GET /v1/checkout/sessions` and returns `{:ok, %Response{data: %List{}}}` with
typed `%Checkout.Session{}` items. All params are optional.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `params` - Filter params (e.g., `%{"limit" => "20", "customer" => "cus_..."}`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %Response{data: %List{data: [%Checkout.Session{}, ...]}}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

# `list!`

```elixir
@spec list!(LatticeStripe.Client.t(), map(), keyword()) :: LatticeStripe.Response.t()
```

Like `list/3` but raises `LatticeStripe.Error` on failure.

# `list_line_items`

```elixir
@spec list_line_items(LatticeStripe.Client.t(), String.t(), map(), keyword()) ::
  {:ok, LatticeStripe.Response.t()} | {:error, LatticeStripe.Error.t()}
```

Lists the line items for a Checkout Session.

Sends `GET /v1/checkout/sessions/:session_id/line_items` and returns typed
`%LineItem{}` items in the list.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `session_id` - The session ID string (e.g., `"cs_..."`)
- `params` - Filter params (e.g., `%{"limit" => "100"}`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %Response{data: %List{data: [%LineItem{}, ...]}}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

## Example

    {:ok, resp} = LatticeStripe.Checkout.Session.list_line_items(client, "cs_...")
    items = resp.data.data  # [%LineItem{}, ...]

# `list_line_items!`

```elixir
@spec list_line_items!(LatticeStripe.Client.t(), String.t(), map(), keyword()) ::
  LatticeStripe.Response.t()
```

Like `list_line_items/4` but raises `LatticeStripe.Error` on failure.

# `retrieve`

```elixir
@spec retrieve(LatticeStripe.Client.t(), String.t(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}
```

Retrieves a Checkout Session by ID.

Sends `GET /v1/checkout/sessions/:id` and returns `{:ok, %Checkout.Session{}}`.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The session ID string (e.g., `"cs_..."`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %Checkout.Session{}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

# `retrieve!`

```elixir
@spec retrieve!(LatticeStripe.Client.t(), String.t(), keyword()) :: t()
```

Like `retrieve/3` but raises `LatticeStripe.Error` on failure.

# `search`

```elixir
@spec search(LatticeStripe.Client.t(), String.t(), keyword()) ::
  {:ok, LatticeStripe.Response.t()} | {:error, LatticeStripe.Error.t()}
```

Searches Checkout Sessions using Stripe's search query language.

Sends `GET /v1/checkout/sessions/search` with the query string and returns typed results.
Note: search results have eventual consistency — newly created sessions may not
appear immediately.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `query` - Stripe search query string (e.g., `"status:'open'"`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %Response{data: %List{data: [%Checkout.Session{}, ...]}}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

## Example

    {:ok, resp} = LatticeStripe.Checkout.Session.search(client, "status:'open'")

# `search!`

```elixir
@spec search!(LatticeStripe.Client.t(), String.t(), keyword()) ::
  LatticeStripe.Response.t()
```

Like `search/3` but raises `LatticeStripe.Error` on failure.

# `search_stream!`

```elixir
@spec search_stream!(LatticeStripe.Client.t(), String.t(), keyword()) ::
  Enumerable.t()
```

Returns a lazy stream of Checkout Sessions matching the search query (auto-pagination).

Emits individual `%Checkout.Session{}` structs, fetching additional search pages as needed.
Raises `LatticeStripe.Error` if any page fetch fails.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `query` - Stripe search query string
- `opts` - Per-request overrides

## Returns

An `Enumerable.t()` of `%Checkout.Session{}` structs.

# `stream!`

```elixir
@spec stream!(LatticeStripe.Client.t(), map(), keyword()) :: Enumerable.t()
```

Returns a lazy stream of all Checkout Sessions matching the given params (auto-pagination).

Emits individual `%Checkout.Session{}` structs, fetching additional pages as needed.
Raises `LatticeStripe.Error` if any page fetch fails.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `params` - Filter params (e.g., `%{"limit" => "100"}`)
- `opts` - Per-request overrides

## Returns

An `Enumerable.t()` of `%Checkout.Session{}` structs.

## Example

    client
    |> LatticeStripe.Checkout.Session.stream!()
    |> Stream.take(500)
    |> Enum.to_list()

# `stream_line_items!`

```elixir
@spec stream_line_items!(LatticeStripe.Client.t(), String.t(), map(), keyword()) ::
  Enumerable.t()
```

Returns a lazy stream of line items for a Checkout Session (auto-pagination).

Emits individual `%LineItem{}` structs, fetching additional pages as needed.
Raises `LatticeStripe.Error` if any page fetch fails.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `session_id` - The session ID string
- `params` - Filter params
- `opts` - Per-request overrides

## Returns

An `Enumerable.t()` of `%LineItem{}` structs.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
