{"id":"webhook-standard-verify","version":"1.0.0","description":"Verify a Standard Webhooks (Svix/Clerk/Resend) webhook-signature header against its id.timestamp.payload signing string.","supported_operations":["verify a standard webhooks signature","check webhook-signature header","validate a svix or clerk webhook","standard webhooks spec verification","whsec_ secret signature check","clerk or resend webhook signature check"],"unsupported_operations":["computing a fresh webhook-signature header for a test delivery (see webhook-signature-compute)","verifying any other vendor webhook scheme (see webhook-stripe-verify, webhook-slack-verify, webhook-twilio-verify)"],"semantics":["secret decoding: strip a leading 'whsec_' if present, then base64-decode the remainder, tolerant of an already-correctly-padded or unpadded value. An empty result, or a string that still fails to base64-decode, is invalid_input.","signed content = webhook_id + '.' + webhook_timestamp (the exact digit string given) + '.' + payload (raw, never re-serialized), HMAC-SHA256'd with the decoded secret; the resulting bytes are base64-encoded (standard, padded) to form the expected token value.","webhook_signature is split on ASCII spaces into tokens of the form '<scheme>,<base64>'; only tokens whose scheme is exactly 'v1' are compared (any other scheme is skipped, not treated as an error) -- if no 'v1' token is present at all, reason is 'no_v1_signature'. Each v1 token's base64 part is constant-time-compared to the expected value; the FIRST index (0-based, left to right in webhook_signature) that matches is matched_index, and any one match makes the whole call valid -- if none match, reason is 'signature_mismatch'.","When now is given: timestamp_checked is true, and the tool fails with reason 'timestamp_outside_tolerance' when abs(now - webhook_timestamp) > tolerance_seconds (an ABSOLUTE, both-directions check), checked only after a signature match succeeds. When now is omitted, timestamp_checked is false and no freshness check runs.","secret is never echoed in the output or in any error details."],"limits":{"max_payload_bytes":262144},"pricing":{"status":"unpriced","charge_usd":null},"input_schema":{"type":"object","additionalProperties":false,"required":["payload","webhook_id","webhook_timestamp","webhook_signature","secret"],"properties":{"payload":{"type":"string","maxLength":262144},"webhook_id":{"type":"string","minLength":1,"maxLength":256},"webhook_timestamp":{"type":"string","pattern":"^[0-9]{1,16}$"},"webhook_signature":{"type":"string","minLength":1,"maxLength":4096},"secret":{"type":"string","minLength":1,"maxLength":512},"now":{"type":"integer","minimum":0,"maximum":99999999999},"tolerance_seconds":{"type":"integer","minimum":0,"maximum":86400,"default":300}}},"output_schema":{"type":"object","additionalProperties":false,"required":["valid","reason","timestamp_checked","matched_index"],"properties":{"valid":{"type":"boolean"},"reason":{"type":["string","null"],"enum":["no_v1_signature","signature_mismatch","timestamp_outside_tolerance",null]},"timestamp_checked":{"type":"boolean"},"matched_index":{"type":["integer","null"],"minimum":0}}},"examples":[{"input":{"payload":"{\"test\":1}","webhook_id":"msg_1","webhook_timestamp":"1614265330","webhook_signature":"v2,decoy","secret":"MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"},"output":{"valid":false,"reason":"no_v1_signature","timestamp_checked":false,"matched_index":null}},{"input":{"payload":"{\"test\":1}","webhook_id":"msg_1","webhook_timestamp":"1614265330","webhook_signature":"v1,notarealsignature==","secret":"MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"},"output":{"valid":false,"reason":"signature_mismatch","timestamp_checked":false,"matched_index":null}}],"execute_url":"/v1/tools/webhook-standard-verify/versions/1.0.0/execute"}