Sendio.Webhooks (sendio v1.1.0)

Manage webhooks in Sendio, and verify the signature of the requests they send (verify/3).

Summary

Types

Request headers, as a map or a list of {name, value} tuples.

Why verify/4 rejected a webhook request.

Functions

Lists all webhooks.

Verifies the signature of a webhook request sent by send.io and returns the decoded event.

Types

@type headers() :: map() | [{String.t() | atom(), String.t()}]

Request headers, as a map or a list of {name, value} tuples.

Link to this type

verify_error()

@type verify_error() ::
  :missing_header
  | :invalid_timestamp
  | :timestamp_out_of_tolerance
  | :invalid_secret
  | :invalid_signature
  | :invalid_payload

Why verify/4 rejected a webhook request.

Functions

Link to this function

create(client \\ Sendio.client(), opts)

Creates a new webhook.

Options

  • :endpoint - The webhook endpoint URL (required)
  • :events - List of events to subscribe to (required)
  • :name - A name for the webhook
Link to this function

get(client \\ Sendio.client(), webhook_id)

Gets a webhook by ID.

Link to this function

list(client \\ Sendio.client())

Lists all webhooks.

Link to this function

remove(client \\ Sendio.client(), webhook_id)

Removes a webhook.

Link to this function

update(client \\ Sendio.client(), webhook_id, opts)

Updates a webhook.

Options

  • :endpoint - The webhook endpoint URL
  • :events - List of events to subscribe to
  • :name - A name for the webhook
Link to this function

verify(payload, headers, secret, opts \\ [])

@spec verify(String.t(), headers(), String.t(), Keyword.t()) ::
  {:ok, map()} | {:error, verify_error()}

Verifies the signature of a webhook request sent by send.io and returns the decoded event.

  • payload - the raw request body, exactly as received (not re-encoded JSON)
  • headers - the request headers, as a map or a list of {name, value} tuples (for example conn.req_headers in Plug). The svix-id, svix-timestamp and svix-signature headers are read, in any case; the keys :id, :timestamp and :signature work too.
  • secret - the webhook's signing secret (whsec_...)

The timestamp must be within the tolerance of the current time and one of the v1 signatures in svix-signature must be the HMAC-SHA256 of id.timestamp.payload. Signatures are compared in constant time.

Options

  • :tolerance - how many seconds the timestamp may be from the current time, either way (default 300)

Example

{:ok, payload, conn} = Plug.Conn.read_body(conn)
secret = System.fetch_env!("SENDIO_WEBHOOK_SECRET")

case Sendio.Webhooks.verify(payload, conn.req_headers, secret) do
  {:ok, event} -> handle(event["type"], event["data"])
  {:error, _reason} -> Plug.Conn.send_resp(conn, 400, "invalid signature")
end