Scope webhooks. Endpoints are project-wide, so account-bound keys can’t manage them. url must be public https (not a private, loopback or link-local address). signer is allternit (the default, below) or standard_webhooks (Standard Webhooks); endpoint objects show which one they use. events lists what you want, or ["*"] for everything:

Delivery and retries

We POST each event to each matching endpoint. Any 2xx answer within 10 seconds counts as delivered. Anything else is retried after 30 s, 2 min, 10 min, 30 min, 1 h, then every 2 h, for 24 hours; after that the delivery is marked failed (redeliver it from the log). Redirects aren’t followed. Events can arrive more than once and out of order: deduplicate on id.

Verify the signature

Every request carries:
v1 is the hex HMAC-SHA256 of "<t>.<raw request body>" with your endpoint’s secret. Check it against the raw body, before parsing, and reject requests whose t is more than five minutes old.

Standard Webhooks

Create the endpoint with "signer": "standard_webhooks" to get Standard Webhooks signatures instead, so any Standard Webhooks library (Svix, standardwebhooks on npm/PyPI) can verify them. The body is the same event object. The secret is then whsec_ followed by base64 of 32 random bytes, and every request carries:
webhook-id is the event id (the same on every retry, so deduplicate on it). The signature is base64 HMAC-SHA256 of "<webhook-id>.<webhook-timestamp>.<raw body>" keyed with the base64-decoded secret. The same headers are what MCP Events deliveries use.
Node