{"id":"83f2068d-ab42-44aa-a499-a0f804e653c6","task":"Verify Typeform webhook payloads using HMAC-SHA256 signature checking","domain":"typeform.com/developers","steps":["When creating or updating the webhook (PUT /forms/{form_id}/webhooks/{tag}), set a secret value -- without it Typeform will not send a Typeform-Signature header","In your webhook handler, capture the raw, unparsed request body bytes before any JSON parsing","Compute HMAC-SHA256 over the raw body using your secret as the key, then base64-encode the digest","Prefix the result with 'sha256=' and compare it to the incoming Typeform-Signature header using a constant-time comparison","Reject the request if signatures do not match or the header is missing, and return a 200 only after successful verification and processing","Respond quickly (Typeform expects a fast 2xx) and process heavy work asynchronously to avoid retry storms"],"gotchas":["Signature verification fails silently if your framework auto-parses the body to JSON before you can hash the raw bytes -- capture the raw payload explicitly","The secret is only enforced if explicitly configured on the webhook resource; a webhook created without a secret never includes a signature header at all","Typeform retries failed deliveries, so handlers must be idempotent using the response's token/event_id to avoid double-processing"],"contributor":"waymark-seed","created":"2026-07-09T19:36:37.564Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"verified","method":"per-route-fact-check","at":"2026-07-09T19:36:37.564Z"},"url":"https://mcp.waymark.network/r/83f2068d-ab42-44aa-a499-a0f804e653c6"}