Webhooks

A webhook represents one webhook integration — a target URL where HostWebhook delivers events, with optional fallback URLs, payload filters, payload transforms, and signature verification.

What is a webhook?

Each webhook has:

  • Name—A friendly label shown in the dashboard
  • Target URL—Where HostWebhook POSTs events (your server)
  • Ingress URL—Where your webhook source sends events — unique per webhook
  • Ingress token—The token in the ingress URL — rotate it to invalidate the old URL
  • Signing secret—Used to sign every delivery — verify it on your server
  • Max retries—How many additional attempts after a failure (plan-limited: Free 0–3, Pro 0–10, Enterprise 0–20)
  • Retry delay—Base delay (seconds) for exponential backoff (default: 60)
  • Rate limit—Max deliveries per minute (0 = unlimited)
  • Active—Paused webhooks queue events but pause delivery
  • Incoming signature—Verify signatures from Stripe, GitHub, or custom HMAC on inbound requests
  • Payload filters—Rules to accept or discard events based on payload content
  • Fallback URLs—Backup URLs tried in order when the primary target URL fails

Plan limits

PlanEvents / weekMax retriesMax retry delayBackoff cap
Free1,000360 s30 min
Starter2,500 – 10,0005600 s2 hr
Pro6,000 – 50,000103,600 s6 hr
Enterprise12,000 – 200,000207,200 s24 hr

Events reset every week. Free has 1,000; on Starter, Pro and Enterprise you choose how many you need each week, and above 200,000 a week there's a Custom plan.

ℹThe backoff cap is the maximum delay between any two retries regardless of how large the exponential value grows. A retry is an additional attempt after a failure — configuring maxRetries: 3 means up to 4 total attempts (1 initial + 3 retries). Exceeding your plan's limit returns 403 Forbidden.

Rotating secrets

Both the ingress token and signing secret can be rotated at any time from the webhook detail page.

  • Rotating the ingress token invalidates the old ingress URL immediately. Update your webhook source to use the new URL.
  • Rotating the signing secret invalidates the old secret immediately. Update your server's environment variable first.
⚠There is no grace period after rotation — the old secret/token stops working the moment you rotate.

Pausing a webhook

Pausing a webhook stops delivery. Events continue to be accepted at the ingress URL and queued — they will be delivered once you activate the webhook again. Useful for maintenance windows.

Ingress protection

HostWebhook offers multiple layers of ingress protection. You can enable any combination — when multiple are active, all must pass.

Require API Key

When enabled, every request to the ingress must include a valid API key with the ingress:write scope in the Authorization header (events:write, the wider scope, opens it too — keys created beforeingress:write existed use that one). The API key identifies who is sending, verifies they have permission, and confirms they belong to the same organization as the webhook.

bashSending with API key
curl -X POST https://api.hostwebhook.com/api/in/YOUR_TOKEN \
  -H "Authorization: Bearer hwk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"event": "order.created"}'

Incoming signature verification

Verifies that the payload was not tampered with in transit. Configure the type and shared secret — HostWebhook validates the signature header on every inbound request.

TypeDescription
noneNo signature verification (default)
stripeVerify Stripe-Signature header (HMAC-SHA256)
githubVerify X-Hub-Signature-256 header (HMAC-SHA256)
shopifyVerify X-Shopify-Hmac-Sha256 header (HMAC-SHA256, base64)
hostwebhookVerify X-HostWebhook-Signature header (t=timestamp,v1=hmac)
staticVerify a static secret in Authorization, X-Webhook-Secret, or custom header

API Key vs Incoming Signature

They solve different problems and can work together.

API KeyIncoming Signature
Who uses itYour clients (SDK, API)External services (Stripe, GitHub)
What it verifiesIdentity + permissions (scopes)Payload integrity (not tampered)
ScopesYes (ingress:write, canvas:write, etc.)No
Org ownershipYesNo
Replay protectionNo (use deduplication)Yes (timestamp in HMAC)
ℹWhen both are enabled on a webhook, both must pass. If the API key is valid but the signature is invalid (or vice versa), the request is rejected. Use API key alone for your own clients, signature alone for external services, or both for maximum security.
✦Marketplace templates auto-configure the signature type based on the source (Stripe → stripe, Shopify → shopify, GitHub → github).

Payload filters

Payload filters let you discard events that don't match specific criteria — before any delivery attempt is made. Events that fail the filter are saved with status filtered and no delivery job is created.

✦Use payload filters to avoid spending retries and quota on events you don't care about — for example, only processing payment_intent.succeeded events from a Stripe integration that sends dozens of event types.

How filters work

All filter rules are evaluated against the parsed JSON payload. If all rules pass, the event is queued for delivery. If any rule fails, the event is discarded. Fields support dot-notation for nested properties.

Available operators

OperatorDescriptionValue required
eqField equals value (string comparison)Yes
neqField does not equal valueYes
containsField contains value (string)Yes
gtField is greater than value (numeric)Yes
ltField is less than value (numeric)Yes
existsField is present and not nullNo
not_existsField is absent or nullNo

Example — only process succeeded payments

// Payload filters on the webhook:
[
  { "field": "type", "operator": "eq", "value": "payment_intent.succeeded" },
  { "field": "data.object.amount", "operator": "gt", "value": "0" }
]

// This Stripe payload passes:
{ "type": "payment_intent.succeeded", "data": { "object": { "amount": 5000 } } }

// This one is filtered (wrong type):
{ "type": "payment_intent.created", "data": { "object": { "amount": 5000 } } }

Manage payload filters from the Payload Filters section on the webhook detail page.


Payload transforms

A payload transform lets you reshape the event before HostWebhook delivers it to the webhook's target URL — converting a raw Stripe payload into a Discord embed, for example. Transforms use a JSON template with {{path}} interpolation.

Interpolation syntax

SyntaxDescription
{{payload.type}}Value from the event payload using dot-notation
{{headers.stripe-signature}}Value from the original inbound headers
{{meta.eventId}}HostWebhook event metadata (eventId, receivedAt)
{{payload.amount ?? 0}}Null coalescing — use fallback if path is null/undefined
{{payload.status === 'active' ? 'Yes' : 'No'}}Ternary — compare with string/number/null
{{payload.field !== null ? payload.other : 'none'}}Ternary with path resolution in branches

Example — Stripe payment to Discord embed

{
  "embeds": [{
    "title": "💳 Payment Received",
    "color": 5763719,
    "fields": [
      {
        "name": "Amount",
        "value": "{{payload.data.object.amount_received ?? 0}} {{payload.data.object.currency}}",
        "inline": true
      },
      {
        "name": "Customer",
        "value": "{{payload.data.object.customer ?? 'Guest'}}",
        "inline": true
      }
    ],
    "timestamp": "{{meta.receivedAt}}"
  }]
}
✦Use the Marketplace to get pre-built templates with payload transforms already configured to post Stripe, Shopify, GitHub, Railway, Sentry and app events to Discord or Slack.

API

The transform is a field on the webhook itself — send payloadTransform when you create or update one, ornull to remove it. See the API reference for the full schema.


Circuit Breaker

The circuit breaker automatically stops delivering to a webhook that is consistently failing — protecting both your server and your retry budget.

FieldDescriptionDefault
circuitBreaker.enabledEnable the circuit breakerfalse
circuitBreaker.thresholdConsecutive failures to open the circuit5
circuitBreaker.cooldownSecondsHow long the circuit stays open before testing300

The circuit breaker has three states: CLOSED (normal — deliveries flow), OPEN (blocked — events are queued but not delivered), and HALF_OPEN (testing — one event is allowed through to check if the webhook has recovered).

ℹSee the Circuit Breaker deep dive for state diagrams and advanced configuration.

Priority

Each webhook has a priority field (1–5, default 3). Priority 1 is critical — events for higher-priority webhooks are dequeued and delivered before lower-priority ones.

✦You can also set priority per-event using the X-HW-Priority header on inbound requests. This overrides the webhook default for that specific event.

Fallback URL

Configure a fallbackUrl on a webhook. If the primary targetUrl fails all retries, HostWebhook makes one final attempt to the fallback URL before marking the event as failed. Useful for disaster recovery or backup processing servers.

Chaos testing

Enable chaos testing to simulate failures in development and staging:

FieldDescription
chaosConfig.enabledEnable chaos testing for this endpoint
chaosConfig.failureRatePercentage of deliveries that will be artificially failed (0–100)
chaosConfig.latencyMsArtificial latency added to each delivery (milliseconds)
⚠Chaos testing is intended for non-production environments. Enabling it on a live webhook will cause real delivery failures.