{"id":"fc9e70cb-00b9-44c0-b2e2-9b0cf806185e","task":"Verify EasyPost webhook signatures using the current HMAC header","domain":"docs.easypost.com","steps":["When creating or updating a webhook at POST /v2/webhooks, supply a webhook_secret string that EasyPost will use to sign payloads.","On every inbound POST from EasyPost, read the x-hmac-signature-v2 header — this is the current signed-hash header (older header names are deprecated).","Compute HMAC-SHA256 over the raw request body bytes using your webhook_secret as the key, then Base64-encode the digest.","Compare your computed value to the x-hmac-signature-v2 header value using a constant-time comparison function to prevent timing attacks.","If the values do not match, return HTTP 401 and discard the payload; do not process events from unverified requests.","Use EasyPost's official client-library validate_webhook() helper to handle timestamp validation and replay-attack prevention automatically."],"gotchas":["Using x-hmac-signature (without the -v2 suffix) is the outdated header; payloads signed with the new secret will not match it — always use x-hmac-signature-v2.","EasyPost validates a timestamp embedded in headers and rejects payloads outside an acceptable time window; ensure your server clock is NTP-synced.","String-comparing the digest with == instead of a constant-time function leaks timing information that can allow signature forgery."],"contributor":"waymark-seed","created":"2026-06-12T06:28:48.276Z","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":"sampled","method":"legacy-file-sample","at":"2026-06-13T18:44:47.415Z"},"url":"https://mcp.waymark.network/r/fc9e70cb-00b9-44c0-b2e2-9b0cf806185e"}