# `LatticeStripe.EventNotification`
[🔗](https://github.com/szTheory/lattice_stripe/blob/v2.2.2/lib/lattice_stripe/event_notification.ex#L1)

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 from `Webhook.parse_event_notification/4`
  on the `/v2/events` thin-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 (use `Webhook.construct_event/4`) or fetched from
  `/v2/core/events/{id}` (use `Webhook.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 a `DateTime` should call
  `DateTime.from_iso8601/1` themselves.
- `context` — Free-form context string from Stripe (or `nil`)
- `livemode` — `true` for live mode, `false` for test mode
- `related_object` — `%LatticeStripe.EventNotification.RelatedObject{}` (or `nil`
  for snapshot-style v2 events)
- `reason` — Map describing what triggered the event (contains `request.id` and
  `request.idempotency_key`; hidden in `Inspect` because 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](https://docs.stripe.com/event-destinations) and
[Stripe v2 Events API](https://docs.stripe.com/api/v2/events) for the full payload
schema.

# `t`

```elixir
@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.

# `from_map`

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

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"
      }
    })

---

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