TreasuryPrime.WebhookEvent (TreasuryPrime v1.0.0)

Copy Markdown View Source

Represents the body of an incoming webhook notification from Treasury Prime.

Every webhook payload has the same minimal shape, regardless of which event fired (see TreasuryPrime.Webhook for the full event catalog):

{
  "event": "ach.update",
  "op": "update",
  "id": "ach_01123456789",
  "url": "https://api.treasuryprime.com/ach/ach_01123456789"
}

Treasury Prime intentionally sends a thin notification — it tells you what changed, not the full new state — and explicitly does not guarantee delivery order. The recommended pattern (per their docs) is to always re-fetch the object by id/url rather than trusting any embedded state, which is exactly what fetch/2 does for you.

Example (in a Plug/Phoenix controller)

def webhook(conn, params) do
  event = TreasuryPrime.WebhookEvent.parse!(params)

  case TreasuryPrime.WebhookEvent.fetch(event, client) do
    {:ok, %TreasuryPrime.Ach{} = ach} -> handle_ach_update(ach)
    {:error, error} -> Logger.error("failed to fetch webhook object: " <> inspect(error))
  end

  send_resp(conn, 200, "")
end

Summary

Functions

Re-fetches the object referenced by this webhook event, by following its url. Treasury Prime does not guarantee webhook delivery order, so this is the recommended way to react to a webhook: always trust a fresh GET over the (intentionally thin) webhook payload itself.

Parses a decoded webhook JSON body (a string-keyed map, e.g. straight from Jason.decode!/1 or a Plug body parser) into a t/0.

Like parse/1, but raises ArgumentError on an invalid payload.

Types

t()

@type t() :: %TreasuryPrime.WebhookEvent{
  event: String.t(),
  id: String.t(),
  op: String.t(),
  url: String.t()
}

Functions

fetch(webhook_event, client)

@spec fetch(t(), TreasuryPrime.Client.t()) ::
  {:ok, map()} | {:error, TreasuryPrime.Error.t()}

Re-fetches the object referenced by this webhook event, by following its url. Treasury Prime does not guarantee webhook delivery order, so this is the recommended way to react to a webhook: always trust a fresh GET over the (intentionally thin) webhook payload itself.

Returns the raw, JSON-decoded map (this module doesn't know which resource struct to cast into, since that depends on event) — pattern match on event.event and pass the result to e.g. TreasuryPrime.Resource.cast(TreasuryPrime.Ach, raw_map) if you want a typed struct.

parse(arg1)

@spec parse(map()) :: {:ok, t()} | {:error, :invalid_payload}

Parses a decoded webhook JSON body (a string-keyed map, e.g. straight from Jason.decode!/1 or a Plug body parser) into a t/0.

parse!(payload)

@spec parse!(map()) :: t()

Like parse/1, but raises ArgumentError on an invalid payload.