Represents a Stripe thin-event notification (/v2/events).
Thin events are the lightweight, fixed-shape webhook payloads Stripe delivers from
/v2/event-destinations. Unlike snapshot v1 events (delivered to /v1/webhooks and
returned by LatticeStripe.Event.retrieve/3), a thin-event notification carries only
the event metadata + a related_object reference — adopters fetch the full
LatticeStripe.Event.t() (and optionally the underlying typed resource) on demand.
When to use this vs LatticeStripe.Event
%EventNotification{}— what you receive fromWebhook.parse_event_notification/4on the/v2/eventsthin-event webhook path. Pure serializable data, no embedded%Client{}. Safe to put in ETS, log lines, GenServer state, or distributed messages.%LatticeStripe.Event{}— the full snapshot event, either delivered to v1 webhook endpoints (useWebhook.construct_event/4) or fetched from/v2/core/events/{id}(useWebhook.fetch_event/3).
Do not confuse the two. They are distinct types so adopter handler case blocks
fail loudly rather than fall through to no-match clauses.
Wire format
The thin-event wire payload has "object": "v2.core.event" — the same string both
on a notification (no data/changes) and on the fully-fetched event (with data).
Stripe distinguishes them by presence of data, not by the object string.
Field-by-field
id— Event ID ("evt_...")object— Always"v2.core.event"(per Stripe wire format)type— Event type string (e.g.,"v2.core.account.updated")created— ISO 8601 string like"2026-03-09T13:00:28.435Z". This is a legitimate type asymmetry vs.LatticeStripe.Event.t()created :: integer()(Unix seconds on v1/snapshot events) — Stripe ships the wire value verbatim and LatticeStripe preserves it. Adopters who need aDateTimeshould callDateTime.from_iso8601/1themselves.context— Free-form context string from Stripe (ornil)livemode—truefor live mode,falsefor test moderelated_object—%LatticeStripe.EventNotification.RelatedObject{}(ornilfor snapshot-style v2 events)reason— Map describing what triggered the event (containsrequest.idandrequest.idempotency_key; hidden inInspectbecause of that)extra— Unknown fields from Stripe not yet in this struct
Inspect
The Inspect implementation hides :reason (contains request id + idempotency key)
and :extra to keep output concise and avoid leaking auth-adjacent metadata.
Stripe API Reference
See Stripe Event Destinations and Stripe v2 Events API for the full payload schema.
Summary
Functions
Converts a decoded Stripe API map to a %EventNotification{} struct.
Types
@type t() :: %LatticeStripe.EventNotification{ context: String.t() | nil, created: String.t() | nil, extra: map(), id: String.t() | nil, livemode: boolean() | nil, object: String.t(), reason: map() | nil, related_object: LatticeStripe.EventNotification.RelatedObject.t() | nil, type: String.t() | nil }
A Stripe thin-event notification.
Returned by LatticeStripe.Webhook.parse_event_notification/4. Safely serializable —
contains no %Client{} or other credential material.
Functions
Converts a decoded Stripe API map to a %EventNotification{} struct.
Maps all known thin-event wire fields. Any unrecognized fields are collected into
the extra map so no data is silently lost. Always succeeds (infallible).
Decodes the nested related_object map into a
%LatticeStripe.EventNotification.RelatedObject{} struct via
RelatedObject.from_map/1. When the wire payload sets "related_object" to nil
(snapshot-style v2 events) or omits it, the field is nil.
Defaults object to "v2.core.event" when the key is missing — this matches the
Stripe wire format for v2 events.
Example
LatticeStripe.EventNotification.from_map(%{
"id" => "evt_test_123",
"object" => "v2.core.event",
"type" => "v2.core.account.updated",
"created" => "2026-03-09T13:00:28.435Z",
"livemode" => false,
"related_object" => %{
"id" => "acct_1T93Q4Pmpb34Vto6",
"type" => "v2.core.account",
"url" => "/v2/core/accounts/acct_1T93Q4Pmpb34Vto6"
}
})