modo/webhook/mod.rs
1//! # modo::webhook
2//!
3//! Outbound webhook delivery following the
4//! [Standard Webhooks](https://www.standardwebhooks.com/) specification.
5//!
6//! Provides signed outbound HTTP POST requests using HMAC-SHA256,
7//! plus verification helpers for incoming webhook requests.
8//!
9//! # Provides
10//!
11//! | Type | Purpose |
12//! |------|---------|
13//! | [`WebhookSender`] | Signs and delivers webhook payloads via HTTP POST. Clone-cheap (`Arc` inside). |
14//! | [`WebhookSecret`] | HMAC-SHA256 signing key. Serialized as `whsec_<base64>`. `Debug` output is redacted. |
15//! | [`WebhookResponse`] | HTTP status code and body bytes returned by the endpoint. |
16//! | [`SignedHeaders`] | The three Standard Webhooks request headers produced by [`sign_headers()`]. |
17//! | [`sign()`] | Compute a raw HMAC-SHA256 signature (base64-encoded). |
18//! | [`verify()`] | Verify a raw HMAC-SHA256 signature with constant-time comparison. |
19//! | [`sign_headers()`] | Build the three Standard Webhooks headers from id, timestamp, body, and secrets. |
20//! | [`verify_headers()`] | Verify incoming Standard Webhooks headers with replay-attack protection. |
21//!
22//! # Quick start
23//!
24//! ```
25//! use modo::webhook::{WebhookSender, WebhookSecret};
26//!
27//! # async fn example() -> modo::Result<()> {
28//! let sender = WebhookSender::default_client();
29//! let secret: WebhookSecret = "whsec_dGVzdC1rZXktYnl0ZXM=".parse()?;
30//!
31//! let response = sender.send(
32//! "https://example.com/webhooks",
33//! "msg_01HXYZ",
34//! b"{\"event\":\"user.created\"}",
35//! &[&secret],
36//! ).await?;
37//!
38//! println!("endpoint returned {}", response.status);
39//! # Ok(())
40//! # }
41//! ```
42
43mod client;
44mod secret;
45mod sender;
46mod signature;
47
48pub use client::WebhookResponse;
49pub use secret::WebhookSecret;
50pub use sender::WebhookSender;
51pub use signature::{SignedHeaders, sign, sign_headers, verify, verify_headers};