Documentation Index
Fetch the complete documentation index at: https://docs.knoxcall.com/llms.txt
Use this file to discover all available pages before exploring further.
Inbound Webhook format guide
This page is the wire-level reference for each format the Inbound Webhooks verifier supports. If you’re integrating a custom provider, the rules below tell you exactly what KnoxCall computes when it verifies a request. All formats use HMAC-SHA256 with the shared secret you configured on the subscription. Comparisons are constant-time (crypto.timingSafeEqual) — there’s no timing oracle to exploit.
Stripe
Header:Stripe-Signature: t=<unix-seconds>,v1=<hex-sha256> (multiple v1=... pairs accepted — Stripe rotates secrets this way during a cutover window)
Signed payload: <timestamp>.<body> — the t= value, a literal ., then the raw request body.
Replay protection: yes — KnoxCall rejects with replay_window_exceeded if now - t > replay_window_seconds. Default 300 (5 min) matches Stripe’s recommendation.
Compatibility: anything that adopted Stripe’s signature format. The verifier accepts a request when any of the listed v1= values matches; that’s how Stripe handles secret rotation. If you rotate the secret on KnoxCall, an in-flight cutover where the upstream sends both old and new signatures will keep working until you update the upstream config.
GitHub
Header:X-Hub-Signature-256: sha256=<hex-sha256>
Signed payload: the raw body bytes only.
Replay protection: no — GitHub webhooks include a delivery ID but don’t sign it, so KnoxCall can’t enforce a timestamp window. If your application can’t tolerate replay (e.g. webhooks that mutate state by content rather than idempotency key), enforce the check on your side using GitHub’s X-GitHub-Delivery header.
Compatibility: GitHub webhooks, Postmark, SendGrid Inbound Parse, and most internal SaaS that copied GitHub’s scheme.
Slack
Headers:X-Slack-Signature: v0=<hex-sha256>X-Slack-Request-Timestamp: <unix-seconds>
v0:<timestamp>:<body> — the literal string v0:, the timestamp, another :, then the raw body.
Replay protection: yes — KnoxCall enforces the configured window against X-Slack-Request-Timestamp. Default 300 matches Slack’s documented recommendation.
Compatibility: Slack events, slash commands, interactive components.
AWS SNS (HMAC variant)
Headers (outbound):x-amz-sns-signature: <base64-hmac-sha256>x-amz-sns-signature-version: 1-hmac
x-amz-sns-signature. The x-amz-sns-signature-version header is present on outbound deliveries but not required for inbound verification.
⚠️ This is not real AWS SNS. Real SNS uses RSA over a canonicalised message envelope, not HMAC. KnoxCall’s aws-sns format is an HMAC variant intended for KnoxCall-to-KnoxCall flows or internal services that wanted SNS-shaped headers without the RSA tooling. If you’re verifying real AWS-issued SNS messages, this format won’t match — let us know if RSA SNS is a deal-breaker for you.
KnoxCall legacy
Header:X-Webhook-Signature: sha256=<hex-sha256>
Signed payload: the raw body only.
Replay protection: no.
This is the format KnoxCall’s outbound Webhook Signing emitted before the multi-format library landed. Use it when both ends are KnoxCall (KnoxCall-to-KnoxCall internal events, or one KnoxCall tenant fanning to another).
Custom
Header: (caller-named, e.g.X-MyApp-Signature) with value sha256=<hex-sha256>
Signed payload: the raw body only.
Replay protection: no.
For internal tools that don’t match a named format. Set custom_header_name when you create the subscription. The verifier only knows that one HMAC-SHA256 of the body is in the named header — it doesn’t try to be clever about timestamps.
Reproducing a verification yourself
If you want to confirm KnoxCall’s behaviour from the outside (or reproduce why a request failed), here’s the GitHub-format check in seven lines of Node:${timestamp}.${rawBody} and the header parses out as t=...,v1=.... The Slack version uses v0:${timestamp}:${rawBody} and the X-Slack-Signature: v0= header.
The verifier source is at src/inbound-webhooks/verifier.ts if you want to read the canonical implementation.
What happens when verification fails
KnoxCall surfaces the precise reason in thesignature_error column of API Logs and (when forwarding with on_invalid='forward_with_error_header') in the X-Knox-Verify-Reason HTTP header. Common values:
| Reason | Meaning |
|---|---|
missing <header> header | The request didn’t include the header KnoxCall expected for this format |
malformed <header> | The header was present but didn’t match the format’s regex (e.g. not sha256=<64-hex>) |
replay_window_exceeded | Timestamp was outside [now − replay_window_seconds, now + replay_window_seconds] |
no v1 signature matched (Stripe) | Header parsed correctly but none of the listed v1= values verified — most often a wrong-secret or rotated-secret-on-only-one-side scenario |
Stripe-Signature missing t= | The Stripe header didn’t carry a timestamp; usually a misconfigured custom shim claiming to be Stripe |
Next steps
- Inbound Webhooks overview →
- Outbound Webhook Signing → — the inverse direction