WebhookSafeDocs
Documentation / Provider Integrations
REFERENCE

Connect your webhook providers.

Webhook Safe Cloud supports signature verification for Stripe, GitHub, Shopify, Slack Events API, and generic webhook sources. Each provider uses its own signature format and request header.

Supported providers

Select a provider when creating an endpoint. Webhook Safe applies the corresponding signature verification rules to incoming requests.

ProviderProvider valueSignature headerSecret
Slack Events APIslackx-slack-signature + x-slack-request-timestampRequired
Stripestripestripe-signatureRequired
GitHubgithubx-hub-signature-256Required
Shopifyshopifyx-shopify-hmac-sha256Required
Genericgenericx-webhook-signatureOptional

Slack Events API

Receive signed Slack events in Cloud, then forward accepted callbacks to your application's receiver. The webhook URL configured in Slack and your destination URL serve different purposes.

Slack app setup

  1. Create an endpoint with provider slack and your application’s HTTPS receiver as its destination.
  2. Copy the Signing Secret from your Slack app’s Basic Information page into the endpoint’s signing-secret field. A bot token, client secret or deprecated verification token will not work.
  3. In Slack app settings, open Socket Mode and turn Enable Socket Mode off. When it is on, Slack sends events through a WebSocket instead of the HTTP Request URL—even if the URL shows Verified.
  4. In Slack’s Event Subscriptions, enable events and set Request URL to $BASE_URL/v1/webhooks/ENDPOINT_ID. Each Slack app has one Events API request URL.
  5. Cloud verifies the signed setup request and returns the challenge automatically. The challenge is not stored, forwarded or charged as an event.
  6. Under Subscribe to bot events, add the events you need. For a mention test, add app_mention with the app_mentions:read bot scope. Save Changes, then install or reinstall into your intended test workspace.
  7. Invite the app to a test channel with /invite @Your App Name. Send a new channel message by selecting the app from the @ suggestions. Open Events in Cloud and select your endpoint. Verification challenges do not appear as events; a callback should.

Create the Cloud endpoint

{
  "id": "slack-events",
  "name": "Slack events",
  "destinationUrl": "https://your-app.example/slack",
  "provider": "slack",
  "signingSecret": "REPLACE_WITH_SLACK_SIGNING_SECRET"
}

Send this body through the authenticated Create endpoint API, or use Endpoints in your workspace. Keep the signing secret out of URLs and logs.

Signature verification and event parsing

Cloud requires exactly one x-slack-signature and x-slack-request-timestamp, verifies the original bytes, and rejects timestamps more than five minutes old or in the future. Signed JSON event_callback requests use event_id for duplicate protection within the endpoint. Retry headers do not skip a request that has not been persisted.

Callbacks receive HTTP 202 after durable acceptance or confirmed duplication. Slack expects a 2xx acknowledgment within three seconds; delivery to your receiver runs separately with normal retry/replay behavior. A setup challenge receives HTTP 200 with {"challenge":"..."}. Invalid signatures return 401; malformed or unsupported signed envelopes return 400.

Cloud forwards the original JSON body, without Slack’s signature headers. Inbound verification does not authenticate the outgoing delivery to your receiver. Validate the event’s business fields and make downstream processing idempotent.

Troubleshooting

  • Verified, but no events: turn Socket Mode off, save subscriptions, reinstall after permission changes, and check the workspace, channel membership and clickable app mention.
  • Event recorded, but delivery failed: Slack ingestion succeeded. Open the event's attempt history and check that your destination receiver is running, reachable and returns 2xx. An expired test receiver cannot accept deliveries.
  • Unexpected event counts: each row is a stored event. Retries and replay add delivery attempts to that event. Compare provider event IDs; setup challenges create no row.
  • Cannot reuse an endpoint ID: disabling retains its ID, configuration, history and endpoint allowance. Re-enable the original endpoint when continuing its setup.

OAuth installation, Socket Mode, slash commands, interactivity and outbound Slack notifications are not included. Slack HTTP setup reference. For your own receiver, the webhook-safe npm library provides these verification helpers from v0.7.0.

Stripe

Create an endpoint with provider set to stripe and supply the webhook endpoint signing secret provided by Stripe.

curl -X POST "$BASE_URL/v1/endpoints" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "stripe-events",
    "name": "Stripe events",
    "destinationUrl": "https://your-app.example/stripe",
    "provider": "stripe",
    "signingSecret": "REPLACE_WITH_STRIPE_SIGNING_SECRET"
  }'

Configure Stripe to send webhook events to:

$BASE_URL/v1/webhooks/stripe-events

Stripe sends its signature in the stripe-signature header. Webhook Safe verifies the signature against the original request payload before accepting the event.

GitHub

Create an endpoint with provider set to github. Configure the same signing secret in both GitHub's webhook settings and Webhook Safe.

curl -X POST "$BASE_URL/v1/endpoints" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "github-events",
    "name": "GitHub events",
    "destinationUrl": "https://your-app.example/github",
    "provider": "github",
    "signingSecret": "REPLACE_WITH_GITHUB_SECRET"
  }'

Set GitHub's webhook payload URL to:

$BASE_URL/v1/webhooks/github-events

GitHub sends the signature in x-hub-signature-256. Webhook Safe also reads x-github-delivery as the provider's delivery identifier for event deduplication.

Shopify

Create an endpoint with provider set to shopify and provide the secret used to verify Shopify webhook signatures.

curl -X POST "$BASE_URL/v1/endpoints" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "shopify-events",
    "name": "Shopify events",
    "destinationUrl": "https://your-app.example/shopify",
    "provider": "shopify",
    "signingSecret": "REPLACE_WITH_SHOPIFY_SECRET"
  }'

Configure the Shopify webhook destination as:

$BASE_URL/v1/webhooks/shopify-events

Shopify sends its signature in x-shopify-hmac-sha256. Webhook Safe also reads x-shopify-webhook-id as the provider's webhook identifier for event deduplication.

Generic webhooks

Generic endpoints support sources that are not covered by a built-in provider integration. You can create a generic endpoint with or without a signing secret.

curl -X POST "$BASE_URL/v1/endpoints" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "custom-events",
    "name": "Custom events",
    "destinationUrl": "https://your-app.example/custom",
    "provider": "generic",
    "signingSecret": "REPLACE_WITH_SHARED_SECRET"
  }'

When a signing secret is configured, incoming requests must provide a valid signature in the x-webhook-signature header.

If no signing secret is configured, generic webhook requests are accepted without signature verification. Use unsigned endpoints only when that behavior is appropriate for your integration.

Integration flow

The setup process is similar across all supported providers.

1

Create an endpoint

Choose the provider, destination URL, and signing secret through the management API.

2

Configure the provider

Point your provider to the Webhook Safe ingestion URL for the new endpoint.

3

Receive and verify

Webhook Safe checks the incoming signature using the configured provider's verification rules.

4

Deliver and monitor

Verified events are queued for delivery to your application, with retries and attempt history.

BACK TOIntroduction
→