DocumentationMigrate to the Outbound Gateway

Migrate to the Outbound Gateway

Move your outbound webhooks to Webhook Relay from Svix, Hookdeck Outpost, Convoy, Hook0 or a homegrown queue. Import your customers' existing signing secrets, publish to both providers, then switch one customer at a time with rollback at every stage.

Moving to the Outbound Gateway is a staged cutover, not a big-bang switch. You import your event types, customers and endpoints together with their existing signing secrets, publish every event to both providers for a while, and then switch customers over one at a time. Where the old secret can be imported and the signature scheme already is Standard Webhooks (Svix, Outpost in Standard Webhooks mode), your customers don't change anything. At every stage, rollback is one step back.

The Outbound Gateway is generally available on the Basic, Business and Pro plans. For what it is and how it compares, see the Outbound Gateway overview and the webhooks-as-a-service comparison.

Choose your source

You use todaySecretsWhat your customers' receivers changeGuide
SvixImported as they are (whsec_…)Nothing with a Svix or Standard Webhooks library. Code that reads svix-* headers by name switches to webhook-*Migrate from Svix
Hookdeck OutpostImported if they fit the format, otherwise newStandard Webhooks mode: nothing when the secret is imported. Default mode (x-outpost-signature): a new signature schemeMigrate from Hookdeck Outpost
ConvoyUsually new: Convoy's generated secrets are 25 characters, too short to import. Longer custom secrets in the format importNew signature scheme (X-Convoy-Signature → Standard Webhooks)Migrate from Convoy
Hook0New (Hook0 secrets are UUIDs)New signature scheme (X-Hook0-Signature → Standard Webhooks) and a new secretMigrate from Hook0
Your own queue, cron or workerImported if they fit the format, otherwise newA new signature scheme, unless you already sign with Standard WebhooksMigrate a homegrown sender

Every Outbound Gateway delivery is signed with Standard Webhooks: webhook-id, webhook-timestamp and webhook-signature (v1, HMAC-SHA256 with a whsec_ secret, one secret per endpoint). Customers whose receivers change need the receiving guide.

Import existing signing secrets

Creating an endpoint accepts an optional secret, so a migrated customer keeps verifying with the key they already have. The secret must be 32 to 100 standard base64 characters (A-Z, a-z, 0-9, +, /, padded or not) that decode to a key of at least 24 bytes. The whsec_ prefix is optional; a secret given without it is stored and returned with it. This is the format Svix and other Standard Webhooks senders issue. Without secret, Webhook Relay generates a new whsec_ secret as usual.

# Read OLD_SECRET from the old provider into the environment. Never echo it.
jq -n --arg url "https://acme.example/webhooks" --arg secret "$OLD_SECRET" \
  '{url: $url, event_types: ["invoice.paid"], secret: $secret}' |
curl -s --user "$RELAY_KEY:$RELAY_SECRET" -X POST \
  https://my.webhookrelay.com/v1/outbound/consumers/customer_42/endpoints \
  -H 'Content-Type: application/json' --data @- | jq '{id, state}'
  • Refused: URL-safe base64 (-, _), UUIDs (hyphens), anything shorter than 32 characters, and asymmetric whsk_ / whpk_ keys. The 400 error never echoes the secret. Create those endpoints without secret; they get a new one.
  • After import the secret is encrypted at rest, reveal returns it (with the whsec_ prefix), and rotation works the same as for a generated secret.
  • Dashboard: the Add endpoint dialog has an optional Existing signing secret field (create only), for migrating a handful of customers without code.
  • MCP: create_outbound_endpoint accepts the same secret argument.
  • SDKs: the TypeScript and Go SDKs add a secret option to endpoint create in their next release (relay.outbound.endpoints.create(consumer, { url, eventTypes, secret }), Go OutboundEndpointOptions.Secret). Until then, create imported endpoints with the REST call, as the import scripts in each guide do.

A secret that imports only keeps the same key. If the old provider used a different signature scheme (Convoy, Hook0, Outpost's default mode, most homegrown senders), the customer still switches their verification code to Standard Webhooks, but they keep the same secret value in their configuration.

Why move: cheap to start, best to scale

Start for $9.99. At 10 million messages it's still a flat plan. The Outbound Gateway is included in Webhook Relay plans from Basic. There are no per-message fees, retries and fan-out are free, and outbound messages don't count against your inbound webhook quota. You pay for how many customers you serve, not for how many events you send.

PlanPrice (monthly / annual)Customers (consumers)Endpoints per customerEvent types
Basic$9.99 / $8.9910010300
Business$79.99 / $71.9950025500
Pro$249.99 / $224.991,0001001,000

Enterprise plans can raise limits up to the platform ceiling of 1,000 consumers, 100 endpoints per consumer and 1,000 event types.

Monthly cost with about 30 days of history. List prices checked on 2026-10-10 from Svix pricing and Hookdeck Outpost pricing:

Monthly messagesWebhook Relay (35-day history)Svix Basic (30d)Svix Pro (90d)Hookdeck Outpost Growth (30d)
100k$9.99~$25$490~$500
1M$9.99~$115~$585~$509
10M$9.99–$249.99 (tier set by customer count, not volume)~$1,015~$1,485~$599
50M$9.99–$249.99~$5,015~$5,485~$999

Svix: $20 Basic / $490 Pro including 50k messages, then $0.0001 per message. Outpost: Starter $0 + $10 per million (7-day retention only), Growth $499 + $10 per million. A 256 KiB payload is one Outbound Gateway message.

Beyond price, each endpoint is its own delivery lane with its own rate limit (50 per second by default), concurrency and retry schedule, so one failing customer never delays another. Every attempt is recorded for 35 days, and you can retry one delivery, re-send failed deliveries or replay skipped ones.

Before you start: what doesn't carry over

  • Secrets in other formats. Only Standard Webhooks-format secrets import (see above). Endpoints whose secret doesn't fit get a new whsec_ secret, and those customers update their receiver once.
  • Limits. Your plan sets the number of consumers, endpoints per consumer and event types (see the table above). GET /v1/outbound/access returns your effective limits (see Check access and limits).
  • No bulk import endpoint. The scripts in each guide create resources one call at a time and can be re-run after a failure.
  • Consumer portal. There is no embeddable portal for your customers to manage their own endpoints. Add, update and remove endpoints from your own product with the API.
  • Destinations. Endpoints are public HTTPS URLs. Non-HTTP destinations such as SQS or Pub/Sub are not available.
  • History. Past messages and attempts stay with the old provider. The Outbound Gateway keeps history from the day you start publishing.

Check access and limits

The Outbound Gateway is included in the Basic, Business and Pro plans. Open Outbound webhooks in the dashboard, then confirm from code. The response includes your account's effective limits:

curl --user "$RELAY_KEY:$RELAY_SECRET" https://my.webhookrelay.com/v1/outbound/access
# {"enabled":true,"limits":{"consumers":100,"endpoints_per_consumer":10,"event_types":300}}

"enabled": false means the account is on the Free plan: upgrade to Basic or above on the billing page. Until then, every other /v1/outbound route returns 403.

Use an access token restricted to Outbound: manage for the import, and a separate Outbound: publish only token for the services that publish. See Create an access token.

The cutover plan

The plan is the same for every source. Each guide fills in the provider-specific calls.

StageWhat happensRollback
1. ImportCreate event types, one consumer per customer and their endpoints, passing each endpoint's existing secret where it fits the format. Imported endpoints are paused straight away.Nothing is live. Leave the endpoints paused, or delete them.
2. Shadow publishYour code publishes every event to both providers. The old provider still delivers. Webhook Relay records each message as rejected (skipped) on the paused endpoints, which lets you compare counts.Turn off the Webhook Relay publish call (a feature flag).
3. Receiver changes, only where neededSkip this for customers whose secret was imported and whose receiver already verifies Standard Webhooks (for example Svix library users). Everyone else updates their receiver to accept a delivery from the old provider or Webhook Relay: a header rename, a new signature scheme, or a new secret. Send them the receiving guide.Nothing to undo: receivers still verify the old provider.
4. Switch, per customer (needs approval)Resume the customer's Webhook Relay endpoints and disable (never delete) their endpoints at the old provider. Start with an internal test customer, then a few, then the rest.Pause the Webhook Relay endpoints and re-enable the old ones.
5. End dual publishOnce every customer is switched and the old provider's last retries have finished, remove the old publish call and SDK.Re-add the old publish call; the old configuration is still there.
6. DecommissionA human closes the old account after any history they need is exported.n/a

Two rules keep this safe:

  • Exactly one provider delivers to a customer at a time. Both providers assign their own message IDs, so a receiver that deduplicates on the message ID can't detect a copy sent by the other provider. If you also put your own event ID in the payload, receivers can deduplicate across providers.
  • Don't replay the shadow period. Messages skipped while an endpoint was paused were already delivered by the old provider. Don't call replay-missing for that window when you resume.

Verify with a free Webhook Bin

Before switching anyone, prove that your publish path and your customers' verification work end to end:

  1. Create a free Webhook Bin (curl -s -X POST https://bin.webhookrelay.com/v1/bins) and register https://bin.webhookrelay.com/v1/webhooks/<BIN_ID> as an endpoint of a test consumer such as migration-test. Bins are public, so publish test data only.
  2. Publish a test event to migration-test and read the captured request back with curl -s https://bin.webhookrelay.com/v1/bins/<BIN_ID>.
  3. Paste the headers, body and the endpoint's secret into the Standard Webhooks signature verifier. It must report a valid signature. To prove secret import end to end, create the test endpoint with a test secret in the old provider's format and verify with that secret.
  4. During the shadow stage, compare counts per customer and event type: the old provider's delivered messages against GET /v1/outbound/messages?consumer=<id> and the rejected deliveries on each paused endpoint (GET /v1/outbound/endpoints/{id}/deliveries?status=rejected).

Let your agent do it

Every guide ends with a prompt for Claude Code, Cursor, Codex or any coding agent with shell and web access. The prompt points the agent at a machine-readable playbook:

SourcePlaybook
Svixwebhookrelay.com/outbound-migration/svix.md
Hookdeck Outpostwebhookrelay.com/outbound-migration/hookdeck-outpost.md
Convoywebhookrelay.com/outbound-migration/convoy.md
Hook0webhookrelay.com/outbound-migration/hook0.md
Homegrown senderwebhookrelay.com/outbound-migration/diy.md

Each playbook lists the exact API calls, the checks to run and what the agent must never do. The agent stops for your approval before stage 4. If you connect the Webhook Relay MCP server, the agent can create consumers and endpoints (including imported secrets) and check deliveries with the outbound MCP tools instead of scripts.

Move our outbound webhooks to Webhook Relay
Paste into Claude Code, Cursor, Codex or any agent with shell and web access.

Read https://webhookrelay.com/outbound-migration/index.md and work out which provider this codebase uses to send webhooks to customers (Svix, Hookdeck Outpost, Convoy, Hook0 or a homegrown queue/worker). Then read the matching playbook and follow it step by step: inventory the code, check GET /v1/outbound/access and its limits, import event types, consumers and endpoints (paused, with their existing signing secrets where the format allows), add dual publishing behind a feature flag, and run the verification checks.

Never print, log or commit signing secrets. Never delete anything at the old provider. Stop and ask me for approval before switching any customer's traffic.

Next steps

Frequently asked questions

Can I keep my customers' existing signing secrets when I migrate to Webhook Relay?

Yes, when the secret is in the Standard Webhooks format. Creating an endpoint accepts an optional secret field: 32 to 100 standard base64 characters, with or without the whsec_ prefix, which is the format Svix issues. An imported secret is encrypted at rest and rotates like a generated one, so your customers keep verifying with the key they already have. Secrets that don't fit the format, such as Hook0's UUID secrets or asymmetric whsk_ keys, can't be imported, and those endpoints get a new whsec_ secret.

Do my customers have to change anything when I migrate from Svix?

Usually not. Svix secrets import as they are, and Svix's verification libraries accept the unbranded webhook-id, webhook-timestamp and webhook-signature headers that Webhook Relay sends. A receiver that verifies with a Svix or Standard Webhooks library needs no change. A receiver that reads the svix-* headers by name in its own code has to read the webhook-* names instead.

Will my customers receive duplicate webhooks during the migration?

Not if you follow the cutover plan. Imported endpoints start paused, so while you publish to both providers only the old provider delivers and Webhook Relay records each message as skipped. When you switch a customer, you resume their Webhook Relay endpoint and disable the old one in the same step, so exactly one provider delivers to that customer at any time.

How many customers can I migrate to the Outbound Gateway?

Basic covers 100 consumers with 10 endpoints each and 300 event types, Business covers 500 consumers with 25 endpoints each and 500 event types, and Pro covers 1,000 consumers with 100 endpoints each and 1,000 event types. 1,000 consumers per account is the current platform ceiling. GET /v1/outbound/access returns your account's limits, and the import scripts check them before they create anything.

Is there a bulk import API?

No. The import scripts in each guide create event types, consumers and endpoints one call at a time with the REST API. Consumer and event type calls are upserts and a repeated endpoint URL is rejected with 409, so a script that stops on an error can be re-run safely.

Can an AI coding agent run the migration?

Yes, up to the switch. Every guide has a prompt that points the agent at a machine-readable playbook under webhookrelay.com/outbound-migration/. The agent inventories your code, imports the configuration and secrets, adds dual publishing and runs the checks, then stops and asks for approval before any production traffic moves.

Did this page help you?