Stripe v2 Billing Meter Event Stream — high-throughput session-token API.
Unlike other LatticeStripe modules, MeterEventStream bypasses the standard
Client request pipeline. The v2 event stream uses a different authentication model
(short-lived session tokens instead of API keys) and a different host
(meter-events.stripe.com instead of api.stripe.com). This module calls
client.transport.request/1 directly with the appropriate headers.
Two-Step Usage
Create a session (uses your API key, returns a 15-minute token):
= MeterEventStream.create_session(client)
Send event batches within the session (uses the session token):
events = [ %{"event_name" => "api_call", "payload" => %{"stripe_customer_id" => "cus_123", "value" => "1"}}, %{"event_name" => "api_call", "payload" => %{"stripe_customer_id" => "cus_456", "value" => "3"}} ]
} = MeterEventStream.send_events(client, session, events)
Session Expiry
Sessions expire 15 minutes after creation. send_events/4 checks
session.expires_at before each call and returns {:error, :session_expired}
immediately if the session has expired — saving a network round-trip.
If the server returns a 401 with code billing_meter_event_session_expired
(e.g., due to clock skew), it is also normalized to {:error, :session_expired}.
There is no automatic session renewal. Call create_session/2 again to obtain
a fresh session.
Differences from v1 MeterEvent
| Aspect | v1 MeterEvent.create/3 | v2 MeterEventStream.send_events/4 |
|---|---|---|
| Auth | API key (Bearer) | Session token (Bearer) |
| Host | api.stripe.com | meter-events.stripe.com |
| Encoding | form-urlencoded | JSON |
| Batch | Single event | Up to 100 events |
| Response | Returns event object | Returns empty %{} |
See guides/metering.md for the complete metering guide including v1 and v2 patterns.
Summary
Functions
Create a short-lived meter event stream session.
Send a batch of meter events within an active session.
Functions
@spec create_session( LatticeStripe.Client.t(), keyword() ) :: {:ok, LatticeStripe.Billing.MeterEventStream.Session.t()} | {:error, LatticeStripe.Error.t()}
Create a short-lived meter event stream session.
Returns a %Session{} struct containing an authentication_token valid for
15 minutes. Pass this session to send_events/4 to send event batches.
Opts
:timeout— HTTP request timeout in milliseconds (default:client.timeout)
Return value
{:ok, %Session{}}— session created successfully{:error, %Error{}}— Stripe API error or connection error
Example
{:ok, session} = MeterEventStream.create_session(client)
# session.authentication_token is the bearer credential for send_events/4
# session.expires_at is a Unix timestamp (created + 900 seconds)
@spec send_events( LatticeStripe.Client.t(), LatticeStripe.Billing.MeterEventStream.Session.t(), [map()], keyword() ) :: {:ok, map()} | {:error, :session_expired} | {:error, LatticeStripe.Error.t()}
Send a batch of meter events within an active session.
Params
client—%Client{}(used for transport, json_codec, finch, timeout)session—%Session{}fromcreate_session/2events— non-empty list of event maps, each with:"event_name"(required) — must match aBilling.Meter.event_name"payload"(required) — map with customer mapping key and value"identifier"(optional) — deduplication UUID"timestamp"(optional) — Unix timestamp or ISO 8601 string
Opts
:timeout— HTTP request timeout in milliseconds (default:client.timeout)
Return value
{:ok, %{}}— events accepted (fire-and-forget; no per-event response){:error, :session_expired}— session token has expired (client-side or server-side){:error, %Error{}}— Stripe API error, validation error, or connection error
Example
events = [
%{"event_name" => "api_call", "payload" => %{"stripe_customer_id" => "cus_123", "value" => "1"}}
]
case MeterEventStream.send_events(client, session, events) do
{:ok, %{}} -> :sent
{:error, :session_expired} -> # create a new session
{:error, %Error{} = err} -> # handle error
end