LatticeStripe.Invoice (LatticeStripe v2.3.0)

Copy Markdown View Source

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 for the full object reference and available parameters.

Off-Stripe payments

amount_paid_off_stripe reports invoice payments collected outside Stripe, in the currency's smallest unit. Stripe includes it in API request responses from 2026-05-27.dahlia; set the client API version explicitly to access it. This does not establish availability in webhook event payloads. The package default remains 2026-03-25.dahlia.

Summary

Types

t()

A Stripe Invoice object.

Functions

Retrieves line items for a create_preview invoice.

Deletes a draft Invoice by ID.

Finalizes a draft invoice, transitioning it to open status.

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

Lists Invoices with optional filters.

Lists line items for a specific invoice.

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

Retrieves an Invoice by ID.

Searches for invoices matching a query.

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

Sends an invoice to the customer via email.

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

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

Retrieves an upcoming invoice preview.

Retrieves line items for an upcoming invoice preview.

Updates an Invoice by ID.

Voids an open invoice. Only callable on open invoices.

Types

t()

@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_paid_off_stripe: 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: LatticeStripe.Charge.t() | String.t() | nil,
  collection_method: atom() | String.t() | nil,
  created: integer() | nil,
  currency: String.t() | nil,
  custom_fields: list() | nil,
  customer: LatticeStripe.Customer.t() | 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: LatticeStripe.PaymentIntent.t() | 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: LatticeStripe.Quote.t() | 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: LatticeStripe.Subscription.t() | 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 for field definitions. amount_paid_off_stripe is an optional integer in the currency's smallest unit, available in API request responses from 2026-05-27.dahlia when the client opts into that version. The package default remains 2026-03-25.dahlia.

Functions

create(client, params \\ %{}, opts \\ [])

@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!(client, params \\ %{}, opts \\ [])

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

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

create_preview(client, params \\ %{}, opts \\ [])

@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!(client, params \\ %{}, opts \\ [])

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

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

create_preview_lines(client, params \\ %{}, opts \\ [])

@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(client, id, opts \\ [])

@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!(client, id, opts \\ [])

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

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

finalize(client, id, params \\ %{}, opts \\ [])

@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!(client, id, params \\ %{}, opts \\ [])

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

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

from_map(map)

@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(client, params \\ %{}, opts \\ [])

@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!(client, params \\ %{}, opts \\ [])

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

list_line_items(client, invoice_id, params \\ %{}, opts \\ [])

@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!(client, invoice_id, params \\ %{}, opts \\ [])

@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(client, id, params \\ %{}, opts \\ [])

@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!(client, id, params \\ %{}, opts \\ [])

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

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

pay(client, id, params \\ %{}, opts \\ [])

@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!(client, id, params \\ %{}, opts \\ [])

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

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

retrieve(client, id, opts \\ [])

@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!(client, id, opts \\ [])

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

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

search(client, params \\ %{}, opts \\ [])

@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

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!(client, params \\ %{}, opts \\ [])

@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

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(client, id, params \\ %{}, opts \\ [])

@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!(client, id, params \\ %{}, opts \\ [])

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

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

stream!(client, params \\ %{}, opts \\ [])

@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!(client, invoice_id, params \\ %{}, opts \\ [])

@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(client, params \\ %{}, opts \\ [])

@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

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!(client, params \\ %{}, opts \\ [])

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

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

upcoming_lines(client, params \\ %{}, opts \\ [])

@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(client, id, params, opts \\ [])

@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!(client, id, params, opts \\ [])

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

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

void(client, id, params \\ %{}, opts \\ [])

@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!(client, id, params \\ %{}, opts \\ [])

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

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