Webhook Signing and Delivery

Use this module when nginx sends signed events to another system or receives signed callbacks from vendors and internal services. It gives you one consistent place to handle both sides of that exchange.

When to use this module

  • You need nginx to sign outbound payloads with HMAC-SHA256 before forwarding them to a webhook endpoint.
  • You need to verify inbound callback signatures so you know the sender is real and the payload was not tampered with.
  • You want configurable retry behavior for outbound delivery on timeouts, fetch failures, and 5xx responses.
  • You are composing http_client for upstream calls and need signing to be a first-class part of the delivery path rather than ad-hoc string building in a handler.

nginx.conf synthesis

http {
    js_engine qjs;
    js_path "njs/";
    js_import main from app.js;

    server {
        listen 8888;

        # Outbound: sign and deliver a webhook to a configurable target
        location /deliver {
            js_content main.deliver_demo;
        }

        # Inbound: verify a callback signature against the body
        location /verify {
            js_content main.verify_demo;
        }

        # Inspect the current webhook configuration summary
        location /describe/outbound {
            js_content main.describe_outbound;
        }

        location /describe/inbound {
            js_content main.describe_inbound;
        }
    }
}

For outbound delivery, runtime overrides like $webhook_demo_url and $webhook_demo_timeout_ms let you control the target and timeout without changing the config. For inbound verification, place the handler behind a proxy_pass or auth_request that receives the callback.

Public Gleam API

Config model (webhook/spec)

TypeDescription
WebhookConfigNamed descriptor with algorithm, delivery mode, url, secret, headers, timeout, retry settings
AlgorithmCurrently HmacSha256
DeliveryModeOutbound or Inbound
ConfigErrorTyped validation errors: EmptyName, EmptyUrl, EmptySecret, InvalidTimeout, InvalidRetryAttempts, MissingSignatureHeader
FunctionDescription
validate(WebhookConfig)Returns Ok(WebhookConfig) or Error(ConfigError)
summary(WebhookConfig)Human-readable config description
demo_outbound()Example outbound config for testing
demo_inbound()Example inbound config for testing

Signing and verification (webhook/sign)

FunctionDescription
sign(WebhookConfig, String)Promise(String)Hex-encoded HMAC-SHA256 signature of the payload
verify(WebhookConfig, String, String)Promise(Bool)Case-insensitive, constant-time comparison
signature_header(WebhookConfig, String)#(String, String)Header name-value tuple for the signed request

Outbound delivery (webhook/deliver)

FunctionDescription
deliver(WebhookConfig, String)Promise(Result(Response, DeliveryError))Signs the payload and sends it via http_client
deliver_with_retry(WebhookConfig, String)Promise(Result(Response, DeliveryError))Same as deliver but retries on timeouts, fetch failures, and 5xx
DeliveryErrorConfigInvalid, SignFailed, UpstreamFailed

Inbound verification (webhook/verify)

FunctionDescription
extract_signature(Dict(String,String), WebhookConfig)Result(String, VerifyError)Case-insensitive header lookup
verify_request(Dict(String,String), String, WebhookConfig)Promise(Result(Nil, VerifyError))Full signature check against body
VerifyErrorMissingSignature, InvalidSignature, InvalidPayload

Works well with

  • Stock nginx proxy_set_header — set custom headers on webhook delivery requests.
  • HTTP Client for outbound delivery, retry, and timeout semantics.
  • Response Transform for shaping callback payloads before delivery.
  • Metrics for tracking webhook delivery success and failure rates.
  • MLCache for future idempotency and replay protection patterns.