Skip to main content
Create a subscription using webhooks:manage. Its secret is returned once; store it securely. Separate subscriptions should serve different projects/environments. A destination must be a public HTTPS DNS hostname on port 443. Private/local addresses and redirects are rejected; TLS verification remains enabled.
For dedicated message.status and message.received, supply explicit granted senderIds. Shared-only events need no customer-owned number and accept an empty array. Events contain metadata, not message bodies, OTPs or provider keys. message.received reports metadata only; developer message-content retrieval is not provided by the current service-key contract.

Signature contract

Headers retain their existing X-Sweefta-* names:
Compute HMAC-SHA256 with the signing-secret string as the UTF-8 key, over timestamp + '.' + exact-raw-JSON-body. Do not parse and reserialize before verification. Use constant-time comparison and reject stale timestamps (recommended tolerance: five minutes). Then check the signed body’s id matches the event-ID header and deduplicate that ID durably. A reusable Node.js verifier is included in examples/verify-webhook.mjs in this documentation directory, with tests. In Express, register express.raw({ type: 'application/json', limit: '256kb' }) for this route before any global JSON parser. Verify bytes, persist a deduplicated event in a transaction, enqueue your work, then return 2xx quickly.

Delivery and recovery

Delivery is at least once, can be delayed and can arrive out of order. Event IDs remain stable across retries; timestamp/signature are recalculated for each attempt. Do not assume provider events or statuses arrive in order. Check the authoritative GET endpoint when needed. 2xx acknowledges delivery. HTTP 400/401/403/404/410 is terminal; other failures retry with bounded exponential backoff, at most eight attempts. A subscription disabled before delivery cancels pending work. Use /webhooks/{id}/deliveries to inspect metadata. There is no public manual-redelivery endpoint in this version. Rotating a secret immediately invalidates the old secret; coordinate the receiver change. Webhook egress defaults to disabled until infrastructure validation. The default transport fails closed under a generic forward proxy; operators must configure reviewed SSRF-safe egress before enabling it.