# `Tink.WebhookHandler`
[🔗](https://github.com/iamkanishka/tink.ex/blob/v0.1.1/lib/tink/webhook_handler.ex#L1)

Handler for Tink API webhooks.

Tink sends webhooks for various events like:
- User credentials updated
- Transaction data refreshed
- Account data changed
- Credential errors

## Setup

1. Configure webhook secret in your application:

    config :tink,
      webhook_secret: System.get_env("TINK_WEBHOOK_SECRET")

2. Create a webhook endpoint in your Phoenix app:

    defmodule MyAppWeb.TinkWebhookController do
      use MyAppWeb, :controller

      def handle(conn, params) do
        signature = get_req_header(conn, "x-tink-signature") |> List.first()
        body = conn.assigns.raw_body  # You need to capture raw body

        case Tink.WebhookHandler.handle_webhook(body, signature) do
          {:ok, event} ->
            # Process event
            process_webhook_event(event)
            send_resp(conn, 200, "OK")

          {:error, :invalid_signature} ->
            send_resp(conn, 401, "Invalid signature")

          {:error, reason} ->
            send_resp(conn, 400, "Bad request: #{reason}")
        end
      end
    end

3. Register webhook handlers:

    Tink.WebhookHandler.register_handler(:credentials_updated, &handle_credentials_update/1)

## Webhook Events

Tink sends the following event types:

- `credentials.updated` - Credentials were updated
- `credentials.refresh.succeeded` - Data refresh succeeded
- `credentials.refresh.failed` - Data refresh failed
- `provider_consents.created` - Consent was created
- `provider_consents.revoked` - Consent was revoked

## Examples

    # Handle webhook in controller
    def webhook(conn, _params) do
      signature = get_req_header(conn, "x-tink-signature") |> List.first()
      body = conn.assigns.raw_body

      case Tink.WebhookHandler.handle_webhook(body, signature) do
        {:ok, event} ->
          MyApp.Webhooks.process(event)
          send_resp(conn, 200, "OK")

        {:error, :invalid_signature} ->
          send_resp(conn, 401, "Unauthorized")
      end
    end

    # Register event handlers
    Tink.WebhookHandler.register_handler(:credentials_updated, fn event ->
      # Update user's credential status
      Users.update_credential_status(event["userId"], :updated)
    end)

## Verification

Webhooks are verified using HMAC-SHA256 signature.

# `event`

```elixir
@type event() :: %{
  type: event_type(),
  data: map(),
  timestamp: DateTime.t(),
  raw: map()
}
```

# `event_type`

```elixir
@type event_type() ::
  :credentials_updated
  | :credentials_refresh_succeeded
  | :credentials_refresh_failed
  | :provider_consents_created
  | :provider_consents_revoked
  | :unknown
```

# `handler_function`

```elixir
@type handler_function() :: (event() -&gt; term())
```

# `get_handlers`

```elixir
@spec get_handlers() :: %{required(event_type()) =&gt; [handler_function()]}
```

Gets all registered handlers grouped by event type.

## Examples

    handlers = Tink.WebhookHandler.get_handlers()
    #=> %{credentials_updated: [#Function<...>]}

# `handle_webhook`

```elixir
@spec handle_webhook(String.t(), String.t()) :: {:ok, event()} | {:error, atom()}
```

Handles an incoming webhook request.

Verifies the signature, validates the payload structure, guards against
test webhooks, and parses the event.

## Parameters

  * `body` - Raw webhook request body (JSON string)
  * `signature` - Webhook signature from `X-Tink-Signature` header

## Returns

  * `{:ok, event}` - Successfully parsed and verified webhook
  * `{:error, :invalid_signature}` - Signature verification failed
  * `{:error, :invalid_payload}` - Failed to parse webhook body
  * `{:error, :test_webhook}` - Payload is a Tink test ping (acknowledged, not dispatched)

## Examples

    {:ok, event} = Tink.WebhookHandler.handle_webhook(body, signature)
    #=> {:ok, %{type: :credentials_updated, data: %{...}}}

# `register_handler`

```elixir
@spec register_handler(event_type(), handler_function()) :: :ok
```

Registers a handler function for a specific event type.

Uses an ETS `:bag` table for concurrent-safe registration.

## Parameters

  * `event_type` - Type of event to handle
  * `handler_fun` - Function to call when event is received (arity 1)

## Examples

    Tink.WebhookHandler.register_handler(:credentials_updated, fn event ->
      Logger.info("Credentials updated for user: #{event.data["userId"]}")
      MyApp.Users.sync_credentials(event.data["userId"])
    end)

# `unregister_handlers`

```elixir
@spec unregister_handlers(event_type()) :: :ok
```

Unregisters all handlers for an event type.

## Examples

    Tink.WebhookHandler.unregister_handlers(:credentials_updated)

---

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