# `LatticeStripe.Invoice`
[🔗](https://github.com/szTheory/lattice_stripe/blob/v1.1.0/lib/lattice_stripe/invoice.ex#L1)

Operations on Stripe Invoice objects.

An Invoice is the document Stripe generates when it is time to bill a customer.
Invoices track charges, taxes, discounts, and payment lifecycle. They can be
created manually or automatically by subscriptions.

## Lifecycle

```
draft --> (finalize) --> open --> (pay) --> paid
                           |
                         (void) --> void
                           |
                   (mark_uncollectible) --> uncollectible
```

## Common Workflow

For manually managed invoices:

    # 1. Create a draft invoice (auto_advance: false prevents automatic finalization)
    {:ok, invoice} = LatticeStripe.Invoice.create(client, %{
      "customer" => customer_id,
      "auto_advance" => false
    })

    # 2. Add InvoiceItems to the invoice
    {:ok, _item} = LatticeStripe.InvoiceItem.create(client, %{
      "customer" => customer_id,
      "invoice" => invoice.id,
      "amount" => 5000,
      "currency" => "usd",
      "description" => "Professional services"
    })

    # 3. Finalize the invoice (locks line items, moves to open)
    {:ok, open_invoice} = LatticeStripe.Invoice.finalize(client, invoice.id)

    # 4. Pay the invoice
    {:ok, paid_invoice} = LatticeStripe.Invoice.pay(client, open_invoice.id)

## auto_advance

When `auto_advance` is `true` (the default for subscription invoices), Stripe
automatically finalizes the draft invoice after approximately 1 hour. Set
`auto_advance: false` when creating invoices manually so you can add line items
before finalization.

## Stripe API Reference

See the [Stripe Invoice API](https://docs.stripe.com/api/invoices) for the full
object reference and available parameters.

# `t`

```elixir
@type t() :: %LatticeStripe.Invoice{
  account_country: String.t() | nil,
  account_name: String.t() | nil,
  account_tax_ids: list() | nil,
  amount_due: integer() | nil,
  amount_paid: integer() | nil,
  amount_remaining: integer() | nil,
  amount_shipping: integer() | nil,
  application: String.t() | nil,
  application_fee_amount: integer() | nil,
  attempt_count: integer() | nil,
  attempted: boolean() | nil,
  auto_advance: boolean() | nil,
  automatic_tax: LatticeStripe.Invoice.AutomaticTax.t() | nil,
  billing_reason: atom() | String.t() | nil,
  charge: String.t() | nil,
  collection_method: atom() | String.t() | nil,
  created: integer() | nil,
  currency: String.t() | nil,
  custom_fields: list() | nil,
  customer: String.t() | nil,
  customer_address: map() | nil,
  customer_email: String.t() | nil,
  customer_name: String.t() | nil,
  customer_phone: String.t() | nil,
  customer_shipping: map() | nil,
  customer_tax_exempt: atom() | String.t() | nil,
  customer_tax_ids: list() | nil,
  default_payment_method: String.t() | nil,
  default_source: String.t() | nil,
  default_tax_rates: list() | nil,
  deleted: boolean(),
  description: String.t() | nil,
  discount: map() | nil,
  discounts: list() | nil,
  due_date: integer() | nil,
  effective_at: integer() | nil,
  ending_balance: integer() | nil,
  extra: map(),
  footer: String.t() | nil,
  from_invoice: map() | nil,
  hosted_invoice_url: String.t() | nil,
  id: String.t() | nil,
  invoice_pdf: String.t() | nil,
  issuer: map() | nil,
  last_finalization_error: map() | nil,
  latest_revision: String.t() | nil,
  lines: LatticeStripe.List.t() | nil,
  livemode: boolean() | nil,
  metadata: map() | nil,
  next_payment_attempt: integer() | nil,
  number: String.t() | nil,
  object: String.t(),
  on_behalf_of: String.t() | nil,
  paid: boolean() | nil,
  paid_out_of_band: boolean() | nil,
  payment_intent: String.t() | nil,
  payment_settings: map() | nil,
  period_end: integer() | nil,
  period_start: integer() | nil,
  post_payment_credit_notes_amount: integer() | nil,
  pre_payment_credit_notes_amount: integer() | nil,
  quote: String.t() | nil,
  receipt_number: String.t() | nil,
  rendering: map() | nil,
  rendering_options: map() | nil,
  shipping_cost: map() | nil,
  shipping_details: map() | nil,
  starting_balance: integer() | nil,
  statement_descriptor: String.t() | nil,
  status: atom() | String.t() | nil,
  status_transitions: LatticeStripe.Invoice.StatusTransitions.t() | nil,
  subscription: String.t() | nil,
  subscription_details: map() | nil,
  subscription_proration_date: integer() | nil,
  subtotal: integer() | nil,
  subtotal_excluding_tax: integer() | nil,
  tax: integer() | nil,
  test_clock: String.t() | nil,
  threshold_reason: map() | nil,
  total: integer() | nil,
  total_discount_amounts: list() | nil,
  total_excluding_tax: integer() | nil,
  total_tax_amounts: list() | nil,
  transfer_data: map() | nil,
  webhooks_delivered_at: integer() | nil
}
```

A Stripe Invoice object.

See the [Stripe Invoice API](https://docs.stripe.com/api/invoices/object) for field definitions.

# `create`

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

Creates a new Invoice.

Sends `POST /v1/invoices` with the given params and returns `{:ok, %Invoice{}}`.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `params` - Map of invoice attributes. Common params:
  - `"customer"` - Customer ID (required for manual invoices)
  - `"auto_advance"` - Whether to auto-finalize (default `true` for subscriptions)
  - `"collection_method"` - `"charge_automatically"` or `"send_invoice"`
- `opts` - Per-request overrides (e.g., `[idempotency_key: "..."]`)

## Returns

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

# `create!`

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

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

# `create_preview`

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

Creates an invoice preview.

Replacement for the legacy `upcoming/3` endpoint. Returns `%Invoice{id: nil}`.

## Parameters

Pass params as a map with keys like `"customer"`, `"subscription"`,
`"subscription_items"`, `"subscription_proration_behavior"`, etc.

## Example

    Invoice.create_preview(client, %{
      "customer" => "cus_xxx",
      "subscription_details" => %{
        "items" => [%{"id" => "si_xxx", "price" => "price_new"}],
        "proration_behavior" => "create_prorations"
      }
    })

## Proration Guard

If `client.require_explicit_proration` is `true`, `"proration_behavior"` must
be present in params or `{:error, %Error{type: :proration_required}}` is returned.

# `create_preview!`

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

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

# `create_preview_lines`

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

Retrieves line items for a create_preview invoice.

Returns paginated `%Invoice.LineItem{}` structs for the preview invoice.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `params` - Map with `"customer"` and optional subscription params
- `opts` - Per-request overrides

## Returns

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

# `delete`

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

Deletes a draft Invoice by ID.

Sends `DELETE /v1/invoices/:id` and returns `{:ok, %Invoice{}}`.

Only applicable to draft invoices. Finalized invoices cannot be deleted;
use `void/3` to cancel a finalized invoice.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The invoice ID string
- `opts` - Per-request overrides

## Returns

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

# `delete!`

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

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

# `finalize`

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

Finalizes a draft invoice, transitioning it to `open` status.

After finalization, no more items can be added and the invoice becomes payable.
Only callable on draft invoices.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The invoice ID string (e.g., `"in_123"`)
- `params` - Optional params (e.g., `%{"auto_advance" => false}`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %Invoice{status: :open}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

# `finalize!`

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

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

# `from_map`

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

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

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

Atomizes status, collection_method, billing_reason, and customer_tax_exempt
using a whitelist — unknown values pass through as strings to avoid atom
table exhaustion from unexpected Stripe API values.

## Example

    invoice = LatticeStripe.Invoice.from_map(%{
      "id" => "in_123",
      "status" => "open",
      "collection_method" => "charge_automatically",
      "object" => "invoice"
    })
    # => %LatticeStripe.Invoice{id: "in_123", status: :open, ...}

# `list`

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

Lists Invoices with optional filters.

Sends `GET /v1/invoices` and returns `{:ok, %Response{data: %List{}}}` with
typed `%Invoice{}` items.

## Parameters

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

## Returns

- `{:ok, %Response{data: %List{data: [%Invoice{}, ...]}}}` 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 line items for a specific invoice.

Returns paginated line items rendered on the invoice. For draft invoices,
these reflect the current InvoiceItems. For finalized invoices, these are
locked.

## Example

    {:ok, response} = Invoice.list_line_items(client, "in_xxx")
    line_items = response.data.data  # [%Invoice.LineItem{}, ...]

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `invoice_id` - The invoice ID string
- `params` - Optional pagination params
- `opts` - Per-request overrides

## Returns

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

# `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.

# `mark_uncollectible`

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

Marks an open invoice as uncollectible. Only callable on open invoices.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The invoice ID string
- `params` - Optional params
- `opts` - Per-request overrides

## Returns

- `{:ok, %Invoice{status: :uncollectible}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

# `mark_uncollectible!`

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

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

# `pay`

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

Pays an open invoice.

Accepts optional `"paid_out_of_band"`, `"payment_method"`, and `"source"` params.
Only callable on open invoices.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The invoice ID string
- `params` - Optional params (e.g., `%{"paid_out_of_band" => true}`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %Invoice{status: :paid}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

# `pay!`

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

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

# `retrieve`

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

Retrieves an Invoice by ID.

Sends `GET /v1/invoices/:id` and returns `{:ok, %Invoice{}}`.

## Parameters

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

## Returns

- `{:ok, %Invoice{}}` 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(), map(), keyword()) ::
  {:ok, LatticeStripe.Response.t()} | {:error, LatticeStripe.Error.t()}
```

Searches for invoices matching a query.

## Searchable Fields

`created`, `currency`, `customer`, `last_finalization_error_code`,
`last_finalization_error_type`, `metadata`, `number`, `receipt_number`,
`status`, `subscription`, `total`

## Example

    Invoice.search(client, %{"query" => "status:'open' AND customer:'cus_xxx'"})

> #### Eventual Consistency {: .warning}
>
> Search results may not reflect changes made within the last ~1 second.
> Resources that were recently created, updated, or deleted may not appear
> in search results immediately. If you need real-time results for a specific
> resource, use `retrieve/3` instead.

Upcoming invoices (previews) are not searchable because they are not yet persisted objects.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `params` - Map with at least `"query"` key (Stripe search query string)
- `opts` - Per-request overrides

## Returns

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

# `search_stream!`

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

Returns a lazy stream of all invoices matching a search query (auto-pagination).

Emits individual `%Invoice{}` structs. Raises `LatticeStripe.Error` if any
page fetch fails.

> #### Eventual Consistency {: .warning}
>
> Search results may not reflect changes made within the last ~1 second.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `params` - Map with at least `"query"` key
- `opts` - Per-request overrides

## Returns

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

# `send_invoice`

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

Sends an invoice to the customer via email.

Only applicable when `collection_method: :send_invoice`. Named `send_invoice`
to avoid conflict with `Kernel.send/2`.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The invoice ID string
- `params` - Optional params
- `opts` - Per-request overrides

## Returns

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

# `send_invoice!`

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

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

# `stream!`

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

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

Emits individual `%Invoice{}` 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., `%{"customer" => "cus_123"}`)
- `opts` - Per-request overrides

## Returns

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

# `stream_line_items!`

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

Returns a lazy stream of all line items for a specific invoice (auto-pagination).

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

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `invoice_id` - The invoice ID string
- `params` - Optional pagination params
- `opts` - Per-request overrides

## Returns

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

# `upcoming`

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

Retrieves an upcoming invoice preview.

Returns a `%Invoice{id: nil}` representing what the next invoice will look like.
Useful for previewing proration impact before confirming a subscription change.

## Parameters

Pass params as a map with keys like `"customer"`, `"subscription"`,
`"subscription_items"`, `"subscription_proration_behavior"`, etc.

## Example

    Invoice.upcoming(client, %{
      "customer" => "cus_xxx",
      "subscription" => "sub_xxx",
      "subscription_items" => [%{"id" => "si_xxx", "price" => "price_new"}],
      "subscription_proration_behavior" => "create_prorations"
    })

> #### Deprecation Notice {: .info}
>
> Stripe is deprecating this endpoint in favor of `create_preview/3`.
> Use `create_preview/3` for new integrations.

## Proration Guard

If `client.require_explicit_proration` is `true`, `"proration_behavior"` must
be present in params or `{:error, %Error{type: :proration_required}}` is returned.

# `upcoming!`

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

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

# `upcoming_lines`

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

Retrieves line items for an upcoming invoice preview.

Returns paginated `%Invoice.LineItem{}` structs for the upcoming invoice.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `params` - Map with `"customer"` and optional subscription params
- `opts` - Per-request overrides

## Returns

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

# `update`

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

Updates an Invoice by ID.

Sends `POST /v1/invoices/:id` with the given params and returns `{:ok, %Invoice{}}`.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The invoice ID string
- `params` - Map of fields to update
- `opts` - Per-request overrides

## Returns

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

# `update!`

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

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

# `void`

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

Voids an open invoice. Only callable on open invoices.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The invoice ID string
- `params` - Optional params
- `opts` - Per-request overrides

## Returns

- `{:ok, %Invoice{status: :void}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

# `void!`

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

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

---

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