svix
semver
>=1.0.0postconditions20functions12last verified2026-06-11coverage score92%Postconditions — what we check
- create · api-errorerrorWhensvix-server rejected the message — invalid app ID, malformed payload, unauthorized API key, or rate-limitedThrows
ApiException (svix.ApiException) with statusCode and bodyRequired handlingCaller MUST catch ApiException around message.create(). 4xx errors (400 validation, 401 auth, 404 unknown app, 429 rate limit) require distinct handling — DO NOT blindly retry on auth or validation errors. For rate-limit (429), respect Retry-After if present and back off. The webhook is NOT delivered when create() throws — so a swallowed exception equals a silently-lost integration message.costhighin prodsilent failureusers seelost datavisibilitysilent - create · network-errorerrorWhenNetwork failure reaching api.svix.com — DNS, TLS, timeoutThrows
Error (Node.js network error) or ApiException with no bodyRequired handlingCaller MUST catch and either retry with exponential backoff or enqueue locally for later replay. svix-server does NOT see the message at all when network errors hit before request lands — your system is the only one that knows it was supposed to fire. For critical integrations (billing, compliance), pair create() with a local outbox table so failed sends can be replayed.costhighin prodsilent failureusers seelost datavisibilitysilentSources[1] - verify · signature-mismatcherrorWhenWebhook signature did not validate against the provided secretThrows
WebhookVerificationErrorRequired handlingCaller MUST catch WebhookVerificationError and respond with HTTP 401 (or 400) WITHOUT processing the payload body. A swallowed signature error is an authentication bypass — the caller would then process attacker-controlled webhook events as if they came from a trusted sender. NEVER fall back to "trust the body anyway." Constant-time signature comparison is handled by svix internally; the caller's only job is to not ignore the throw.costcriticalin prodsilent failureusers seesecurity breachvisibilitysilent - verify · timestamp-expirederrorWhenWebhook timestamp is outside the tolerance window (default 5 minutes) — likely a replay attackThrows
WebhookVerificationErrorRequired handlingCaller MUST catch and reject with HTTP 401. svix's verify() rejects messages older than the tolerance window to prevent replay attacks against the webhook endpoint. Do NOT extend the tolerance window to "be lenient" — that defeats the protection. If clock skew is a real concern, sync NTP rather than widening the window.costcriticalin prodsilent failureusers seesecurity breachvisibilitysilentSources[1] - verify · missing-required-headerserrorWhenOne or more required svix headers are absent from the request (svix-id, svix-timestamp, svix-signature)Throws
WebhookVerificationErrorRequired handlingCaller MUST catch WebhookVerificationError and return HTTP 400. Missing headers indicate a request that was NOT sent by svix — either a probe, a misconfigured sender, or a programming error in the caller's header extraction. Never attempt to process the payload body without all three headers present. This error is distinct from a bad signature — it means the request is not a well-formed webhook at all.costcriticalin prodsilent failureusers seesecurity breachvisibilitysilentSources[1] - create · application-create-api-errorerrorWhensvix API rejected the create request — invalid payload, auth failure, or rate limitThrows
ApiException (svix.ApiException) with code (HTTP status) and bodyRequired handlingCaller MUST catch ApiException. Key cases: 401/403 = invalid auth token (bad SVIX_AUTH_TOKEN env); 422 = validation error on ApplicationIn payload (body is HTTPValidationError); 429 = rate limit exceeded. A swallowed exception leaves the customer without an application — subsequent message.create() calls will fail with 404 (app not found) and webhook delivery will silently fail.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - create · application-create-network-errorerrorWhenNetwork failure reaching api.svix.com before or during the requestThrows
Error (native fetch error after 2 automatic retries)Required handlingCaller MUST catch Error (not just ApiException). svix's SDK retries 5xx and network failures twice before throwing. If still failing, the application was NOT created and the customer's tenant has no svix app — retry with idempotency key. For critical onboarding paths, treat this as a blocking error that must block the signup flow or queue for later retry with exponential backoff.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - getOrCreate · application-get-or-create-api-errorerrorWhensvix API rejected the getOrCreate request — auth failure, validation error, or rate limitThrows
ApiException (svix.ApiException) with code (HTTP status) and bodyRequired handlingCaller MUST catch ApiException. Same error profile as application.create(). Common in retry-safe onboarding flows — do not assume getOrCreate() is "safe to ignore on error" because an application already exists. On auth failure (401/403), all subsequent webhook operations for this customer will also fail silently.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - create · endpoint-create-api-errorerrorWhensvix API rejected endpoint creation — invalid URL, auth failure, app not found, validation errorThrows
ApiException (svix.ApiException) with code and bodyRequired handlingCaller MUST catch ApiException. Critical cases: 404 = app not found (application was not created first, or wrong appId); 422 = URL failed validation (non-HTTPS URL in production, malformed URL, invalid filter event types); 401/403 = bad auth token. A silently-swallowed failure here means the customer's webhook URL is never registered — message.create() will succeed but deliver to zero endpoints.costhighin prodsilent failureusers seelost datavisibilitysilent - recover · endpoint-recover-api-errorerrorWhensvix API rejected the recover request — invalid endpoint, auth failure, or validation errorThrows
ApiException (svix.ApiException) with code and bodyRequired handlingCaller MUST catch ApiException. Critical: 404 = endpointId or appId not found; 422 = invalid date range in RecoverIn (e.g. since > until, or since too far in past). recover() returns immediately with a background task ID — a successful HTTP 202 only means the task was queued, NOT that messages were replayed. Callers using this for SLA recovery MUST poll backgroundTask.get(taskId) to confirm completion.costhighin prodimmediate exceptionusers seelost datavisibilityvisible - recover · endpoint-recover-async-not-polledwarningWhenrecover() returns RecoverOut with a background task ID, but caller does not poll task statusThrows
No throw — RecoverOut.id is silently discardedRequired handlingrecover() is ASYNCHRONOUS. A 200 response means the replay job was queued, not completed. Callers MUST use the returned taskId to poll backgroundTask.get(taskId) until status is 'finished'. Treating a successful recover() response as confirmation that messages were replayed is incorrect — the replay may be still in progress or may have partially failed.costmediumin prodsilent failureusers seelost datavisibilitysilent - rotateSecret · endpoint-rotate-secret-api-errorerrorWhensvix API rejected the rotateSecret request — auth failure, endpoint not found, or invalid key formatThrows
ApiException (svix.ApiException) with code and bodyRequired handlingCaller MUST catch ApiException. 404 = endpointId or appId not found; 422 = supplied key does not meet svix's format requirements (if providing a custom key). Critically: if this call is NOT wrapped in try-catch and fails silently, the secret rotation event is lost — the caller may believe rotation succeeded and stop using the old secret, but svix still has the old secret, causing all subsequent webhook verifications to fail.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - appPortalAccess · app-portal-access-api-errorerrorWhensvix API rejected the portal access request — auth failure, app not found, or invalid parametersThrows
ApiException (svix.ApiException) with code and bodyRequired handlingCaller MUST catch ApiException. 404 = appId not found (customer's svix application does not exist — onboarding may have failed silently); 401/403 = bad auth token; 422 = invalid AppPortalAccessIn (e.g. invalid featureFlags). A swallowed exception here results in the caller redirecting the customer to a null/undefined URL — typically a broken redirect or a blank page. This is directly user-visible as a failed portal access attempt.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - resend · message-attempt-resend-api-errorerrorWhensvix API rejected the resend request — invalid IDs, app/message/endpoint not found, or auth failureThrows
ApiException (svix.ApiException) with code and bodyRequired handlingCaller MUST catch ApiException. 404 = one of appId, msgId, or endpointId not found — the attempt does not exist in svix's system (possibly already expired or from the wrong environment). 401/403 = auth failure. A swallowed exception means the admin/support operator believes the message was resent when it was not — the customer's integration remains broken without any indication.costmediumin prodimmediate exceptionusers seelost datavisibilityvisible - expireAll · authentication-expire-all-api-errorerrorWhensvix API rejected the expireAll request — app not found, auth failure, or invalid parametersThrows
ApiException (svix.ApiException) with code (HTTP status) and bodyRequired handlingCaller MUST catch ApiException around expireAll(). Critical cases: 404 = appId not found (customer's svix application was never created or was already deleted); 401/403 = bad SVIX_AUTH_TOKEN (expired or revoked server token). A swallowed exception during a security incident means ALL outstanding portal magic links remain valid — the customer's webhook management portal is still accessible to unauthorized parties. This is a security regression. Never treat a void return from this method as success without a surrounding try-catch.costcriticalin prodsilent failureusers seesecurity breachvisibilitysilent - expireAll · authentication-expire-all-network-errorerrorWhenNetwork failure reaching api.svix.com after 2 automatic retriesThrows
Error (native fetch network error after retry exhaustion)Required handlingCaller MUST catch Error (not just ApiException). svix retries 5xx and network failures twice before propagating the error. If still failing after retries, the token revocation was NOT applied — all outstanding portal sessions remain valid. Security incident handlers MUST treat this as a blocking failure, not a best-effort call. Retry with backoff, or notify the security team that revocation failed so they can revoke the SVIX_AUTH_TOKEN itself as a last resort.costcriticalin prodsilent failureusers seesecurity breachvisibilitysilentSources[3] - replayMissing · endpoint-replay-missing-api-errorerrorWhensvix API rejected the replayMissing request — endpoint not found, auth failure, or invalid time rangeThrows
ApiException (svix.ApiException) with code and bodyRequired handlingCaller MUST catch ApiException. 404 = endpointId or appId not found; 422 = invalid ReplayIn (e.g. invalid date range, since > until, or since too far in the past beyond svix's retention window). 401/403 = auth failure. A swallowed exception means the endpoint backfill was silently skipped — new endpoints onboarded into an existing event stream will never receive historical messages they missed, and the customer sees incomplete webhook history.costmediumin prodimmediate exceptionusers seelost datavisibilityvisible - replayMissing · endpoint-replay-missing-async-not-polledwarningWhenreplayMissing() returns ReplayOut with a background task ID, but caller does not poll task statusThrows
No throw — ReplayOut.id is silently discardedRequired handlingreplayMissing() is ASYNCHRONOUS. A 200 response means the replay job was queued (ReplayOut.status will initially be "running"), NOT that messages were delivered. Callers MUST use the returned ReplayOut.id to poll backgroundTask.get(taskId) until status is "finished" or "failed". Treating a successful replayMissing() response as confirmation that the endpoint is caught up is incorrect. This is the same async pitfall as endpoint.recover() — both return a background task reference that must be tracked, not discarded.costmediumin prodsilent failureusers seelost datavisibilitysilent - sendExample · endpoint-send-example-api-errorerrorWhensvix API rejected the sendExample request — unknown event type, endpoint not found, or auth failureThrows
ApiException (svix.ApiException) with code and bodyRequired handlingCaller MUST catch ApiException. 404 = endpointId or appId not found; 422 = eventType does not exist in svix's registered event types for this app (the event schema must be pre-registered before examples can be sent); 401/403 = auth failure. A swallowed exception in a "Send Test Event" UI means the user receives no feedback that the test failed — they believe their endpoint is configured correctly when it is not, leading to missed production events.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - sendExample · endpoint-send-example-delivery-not-confirmedwarningWhensendExample() returns MessageOut successfully but the endpoint URL did not receive the payloadThrows
No throw — MessageOut is returned but delivery is asynchronousRequired handlingsendExample() returns MessageOut when the TEST MESSAGE WAS QUEUED — NOT when the endpoint received it. The actual HTTP delivery to the customer's URL is asynchronous and happens after this call returns. Callers that treat a successful MessageOut response as confirmation that the endpoint is working are incorrect. To confirm delivery, check messageAttempt.listByMsg(appId, msg.id) and verify that at least one attempt has status "success". A "Send Test Event" UI that only checks the sendExample() return without checking delivery attempts will give false assurance to customers with misconfigured endpoints.costmediumin prodsilent failureusers seeservice unavailablevisibilitysilent
Sources
Every postcondition cites at least one of these. Numbered to match the footnotes above.
- [1]docs.svix.com/api-referencehttps://docs.svix.com/api-reference
- [2]github.com/svix/svix-webhookshttps://github.com/svix/svix-webhooks/blob/main/javascript/src/api/messageAttempt.ts
- [3]github.com/svix/svix-webhookshttps://github.com/svix/svix-webhooks/blob/main/javascript/src/request.ts
- [4]github.com/svix/svix-webhookshttps://github.com/svix/svix-webhooks/blob/main/javascript/src/api/authentication.ts
- [5]github.com/svix/svix-webhookshttps://github.com/svix/svix-webhooks/blob/main/javascript/src/api/endpoint.ts
- [6]github.com/svix/svix-webhookshttps://github.com/svix/svix-webhooks/blob/main/javascript/src/models/replayOut.ts
Need a different package?
Request a profile