Gaiia.Webhook (Gaiia v0.2.0)

Copy Markdown View Source

Signs and verifies Gaiia webhook deliveries.

Verification requires the exact raw request body bytes. Parsing JSON and then re-encoding it can change those bytes and break the signature. In Phoenix, cache the raw body with a custom body reader before Plug.Parsers decodes it.

Subscriptions

Endpoints are managed with the generated operations — Gaiia.Queries.webhooks/4, Gaiia.Mutations.create_webhook/4, Gaiia.Mutations.delete_webhook/4 — and deliveries are auditable through Gaiia.Queries.webhook_execution/4.

CreateWebhookInput.eventNames is [String!]!: the schema does not enumerate event names, so this library cannot check them and no list is bundled here to go stale. The catalog (85 events as of 2026-09-07, from account.created to work_order.updated) is at https://app.gaiia.com/docs/webhooks/overview, and a live endpoint's current subscriptions read back from webhook.eventNames. A misspelled name is accepted and simply never fires.

Summary

Types

Reason a webhook signature could not be verified.

Options for verify/4.

Functions

Build a complete webhook signature header.

Verify a webhook signature against the exact raw request body.

Types

error_reason()

@type error_reason() :: :malformed_signature | :expired | :invalid_signature

Reason a webhook signature could not be verified.

verify_option()

@type verify_option() :: {:tolerance, non_neg_integer()} | {:now, integer()}

Options for verify/4.

Functions

sign(raw_body, secret, timestamp)

@spec sign(binary(), binary(), integer()) :: String.t()

Build a complete webhook signature header.

This is useful when constructing webhook fixtures for tests.

verify(raw_body, signature_header, secret, opts \\ [])

@spec verify(binary(), String.t(), binary(), [verify_option()]) ::
  :ok | {:error, error_reason()}

Verify a webhook signature against the exact raw request body.

The timestamp must be within :tolerance seconds of :now. The default tolerance is 300 seconds and the default time is the current Unix time.