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
Creates a new webhook.
Gets a webhook by ID.
Lists all webhooks.
Removes a webhook.
Updates a webhook.
Verifies the signature of a webhook request sent by send.io and returns the decoded event.
Types
headers()
Request headers, as a map or a list of {name, value} tuples.
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
create(client \\ Sendio.client(), opts)
@spec create(Sendio.Client.t(), Keyword.t()) :: Sendio.Client.response(Sendio.Webhooks.Webhook.t())
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
get(client \\ Sendio.client(), webhook_id)
@spec get(Sendio.Client.t(), String.t()) :: Sendio.Client.response(Sendio.Webhooks.Webhook.t())
Gets a webhook by ID.
list(client \\ Sendio.client())
@spec list(Sendio.Client.t()) :: Sendio.Client.response(Sendio.List.t(Sendio.Webhooks.Webhook.t()))
Lists all webhooks.
remove(client \\ Sendio.client(), webhook_id)
@spec remove(Sendio.Client.t(), String.t()) :: Sendio.Client.response(Sendio.Empty.t())
Removes a webhook.
update(client \\ Sendio.client(), webhook_id, opts)
@spec update(Sendio.Client.t(), String.t(), Keyword.t()) :: Sendio.Client.response(Sendio.Webhooks.Webhook.t())
Updates a webhook.
Options
:endpoint- The webhook endpoint URL:events- List of events to subscribe to:name- A name for the webhook
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 exampleconn.req_headersin Plug). Thesvix-id,svix-timestampandsvix-signatureheaders are read, in any case; the keys:id,:timestampand:signaturework 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