# `LatticeStripe.Billing.Meter`
[🔗](https://github.com/szTheory/lattice_stripe/blob/v2.2.2/lib/lattice_stripe/billing/meter.ex#L1)

Stripe Billing Meter resource — usage-based billing schema.

See `guides/metering.md` (landed in Plan 20-06) for the full usage story,
including the two-layer idempotency contract, the 35-day backdating window,
and the `v1.billing.meter.error_report_triggered` webhook.

## Lifecycle

Meters are created once per usage concept, reported against via
`LatticeStripe.Billing.MeterEvent.create/3`, and eventually retired via
`deactivate/3`. A deactivated meter can be brought back with `reactivate/3`;
deletion is not exposed by the Stripe API.

## Usage

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

    # Create a meter with sum aggregation
    {:ok, meter} = LatticeStripe.Billing.Meter.create(client, %{
      "display_name" => "API Calls",
      "event_name" => "api_call",
      "default_aggregation" => %{"formula" => "sum"},
      "value_settings" => %{"event_payload_key" => "value"}
    })

    # Deactivate when no longer needed
    {:ok, _meter} = LatticeStripe.Billing.Meter.deactivate(client, meter.id)

# `t`

```elixir
@type t() :: %LatticeStripe.Billing.Meter{
  created: integer() | nil,
  customer_mapping: LatticeStripe.Billing.Meter.CustomerMapping.t() | nil,
  default_aggregation: LatticeStripe.Billing.Meter.DefaultAggregation.t() | nil,
  display_name: String.t() | nil,
  event_name: String.t() | nil,
  extra: map(),
  id: String.t() | nil,
  livemode: boolean() | nil,
  object: String.t() | nil,
  status: atom() | String.t() | nil,
  status_transitions: LatticeStripe.Billing.Meter.StatusTransitions.t() | nil,
  updated: integer() | nil,
  value_settings: LatticeStripe.Billing.Meter.ValueSettings.t() | nil
}
```

# `create`

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

Create a billing meter.

Requires `display_name`, `event_name`, and `default_aggregation` params
(string keys — Stripe wire format). After param validation, a pre-flight
guard raises `ArgumentError` on present-but-malformed `value_settings` for
sum/last formulas (T-20-01 silent-zero trap).

# `create!`

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

Bang variant of `create/3`. Raises `LatticeStripe.Error` on failure.

# `deactivate`

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

Deactivate a meter — POST `/v1/billing/meters/{id}/deactivate`.

Use this instead of `update/4` with a `status` param (Stripe does not
accept that shape). Deactivated meters reject new events with the
`archived_meter` error code.

# `deactivate!`

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

Bang variant of `deactivate/3`. Raises `LatticeStripe.Error` on failure.

# `from_map`

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

Decode a Stripe-shaped string-keyed map into a `%Meter{}`.

Nested sub-objects (`default_aggregation`, `customer_mapping`,
`value_settings`, `status_transitions`) are decoded via their respective
`from_map/1` callbacks. Unknown top-level keys land in `:extra`.

# `list`

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

List billing meters. Supports cursor-based pagination via `starting_after`
and `ending_before`, and filtering via `status` (`"active"` | `"inactive"`).

# `list!`

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

Bang variant of `list/3`. Raises `LatticeStripe.Error` on failure.

# `reactivate`

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

Reactivate a previously-deactivated meter — POST `/v1/billing/meters/{id}/reactivate`.

# `reactivate!`

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

Bang variant of `reactivate/3`. Raises `LatticeStripe.Error` on failure.

# `retrieve`

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

Retrieve a billing meter by ID.

# `retrieve!`

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

Bang variant of `retrieve/3`. Raises `LatticeStripe.Error` on failure.

# `status_atom`

> This function is deprecated. Status is now automatically atomized in from_map/1. Access meter.status directly..

```elixir
@spec status_atom(t() | String.t() | nil) :: atom()
```

# `stream!`

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

Returns a lazy stream of all billing meters (auto-pagination).

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

# `update`

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

Update a billing meter.

At time of writing, Stripe only mutates `display_name`; other keys in
`params` are passed through to the API for forward compatibility. If Stripe
later exposes additional mutable fields, this function will begin accepting
them automatically without a library change.

# `update!`

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

Bang variant of `update/4`. Raises `LatticeStripe.Error` on failure.

---

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