# `WalletPasses.EventHandler`
[🔗](https://gitlab.com/phinnaeus/wallet_passes/blob/main/lib/wallet_passes/event_handler.ex#L1)

Behaviour for reacting to wallet pass lifecycle events from both Apple and
Google.

Configure with:

    config :wallet_passes, :event_handler, MyApp.WalletEventHandler

All callbacks are optional — implement only the ones you care about.

Callbacks run asynchronously in a supervised `Task` (see
`WalletPasses.EventHandler.Dispatch`) so they cannot extend Apple/Google
response times. Their return value is ignored. Exceptions are captured,
logged, and reported via telemetry; they do not bring down the request or
the supervisor.

# `event_meta`

```elixir
@type event_meta() :: map()
```

# `platform`

```elixir
@type platform() :: :apple | :google
```

# `on_pass_added`
*optional* 

```elixir
@callback on_pass_added(serial_number :: String.t(), platform(), event_meta()) :: any()
```

Fires when a pass is added to a user's wallet.

  * Apple: when a device registers for push notifications for this pass.
  * Google: when a `save` callback is received from Google Wallet.

`meta`:
  * Apple: `%{device_library_id: String.t(), push_token: String.t()}`
  * Google: `%{object_id: String.t(), class_id: String.t(), nonce: String.t(), exp_time_millis: integer()}`

# `on_pass_fetched`
*optional* 

```elixir
@callback on_pass_fetched(serial_number :: String.t(), platform(), event_meta()) :: any()
```

Fires when an Apple device fetches the latest version of a pass. This is
high-volume — iOS may fetch the pass several times per day per device.
Treat as informational; do not write a row per fetch to a consumer DB
without rate-limiting.

Google does not have an analogue (Google serves pass updates itself).

`meta`:
  * Apple: `%{}`

# `on_pass_removed`
*optional* 

```elixir
@callback on_pass_removed(serial_number :: String.t(), platform(), event_meta()) :: any()
```

Fires when a pass is removed.

  * Google: unambiguous — the user removed the pass from their wallet.
  * Apple: **ambiguous.** This event fires on any device unregister, which
    includes iOS push-token rotation, app uninstall, the user disabling
    notifications for the pass, or genuine pass removal. There is no
    on-device signal to disambiguate. Treat the Apple variant as "this
    device is no longer reachable for push," not as a definitive removal
    signal. For an authoritative wallet-presence check, use
    `WalletPasses.wallet_presence/1` (which reports both platforms
    separately) or rely on Google's `del`.

`meta`:
  * Apple: `%{device_library_id: String.t()}`
  * Google: `%{object_id: String.t(), class_id: String.t(), nonce: String.t(), exp_time_millis: integer()}`

---

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