1Create an endpoint
An endpoint is a public URL that records every request sent to it. New accounts get one called My first endpoint. To add more, press + next to Endpoints in the sidebar and give it a name, such as Stripe dev.
Its catch URL looks like this. Copy it from the sidebar (hover the endpoint) or with ⌘K → Copy catch URL.
https://slinghook.example/v1/catch/3f1c9a2e-7b4d-4e8a-9c61-2d5f0e8b7a14
Free accounts have 3 endpoints. Pro and Team have no endpoint limit.
On Pro and Team you can also reserve a readable URL such as /v1/catch/stripe-dev under Endpoint settings → Reserved URL, so you paste it into your provider once and never again. Names are 3 to 40 lowercase letters, numbers and hyphens, and are first come, first served. The UUID URL keeps working alongside it. If you move back to Free, the name stays yours but only answers again once you upgrade.
2Catch your first webhook
Send anything to the catch URL and it appears in the live feed straight away. The quickest test is cURL:
curl -X POST https://slinghook.example/v1/catch/<endpoint-uuid> \
-H "Content-Type: application/json" \
-d '{"type": "test.ping", "status": "ok"}'
No provider set up yet? Press Simulate above the feed to send a realistic Stripe, GitHub, Shopify or Slack event, complete with a valid signature when the endpoint has a signing secret.
When you are ready for real traffic, paste the catch URL into your provider's webhook settings. The provider guides say where.
3Forward to localhost
SlingHook runs on the internet and your app runs on your laptop, so SlingHook cannot call localhost directly. The slinghook CLI opens an outbound connection instead, the same way stripe listen does, and delivers each webhook to your local server as it arrives.
Install and sign in
npm install -g slinghook
slinghook login --server https://slinghook.example
login asks for your email and password, creates a personal API token, and saves only the token. In CI or on a shared machine, create a token under User settings → API tokens and pass it with --token shk_… or SLINGHOOK_TOKEN instead.
Start forwarding
slinghook endpoints
slinghook listen <endpoint-uuid> --forward http://localhost:3000/webhooks
● Listening on endpoint 3f1c…
Forwarding to http://localhost:3000/webhooks
14:02:11 POST #1234 → 200 37ms sig:valid
14:02:15 POST #1235 → ✗ Connection refused (is your local server running?) 2ms
Each webhook keeps its method, body, query string and signature headers, so your app's own signature check runs for real. Every delivery shows up in the dashboard's replay history. If the connection drops, the CLI reconnects and picks up where it left off, so nothing that arrived in the gap is lost.
4Replay it
Changed your handler? You don't need to make the provider fire again. Select any captured request and press R (or Replay in the inspector) to send it to your forward target. The response status, body and timing are saved in the request's replay history.
- Edit & resend changes the method, headers or body for one send without touching the original.
- Copy as cURL gives you a command you can paste into a terminal or a bug report.
- Code turns a payload into TypeScript, Python, PHP or Go types, a fixture file, or a test that posts it to your handler.
That's the whole loop: catch, debug, replay. The rest of this page covers the parts you'll want once a real integration is wired up.
Stripe, GitHub and Shopify
Stripe
- In the Stripe dashboard, open Developers → Webhooks and choose Add endpoint.
- Paste your catch URL as the endpoint URL and pick the events you need.
- Copy the endpoint's Signing secret (it starts with
whsec_) into SlingHook's endpoint settings to check every signature.
GitHub
- In your repository, open Settings → Webhooks → Add webhook.
- Set Payload URL to your catch URL and Content type to
application/json. - Enter a secret, and save the same value in SlingHook's endpoint settings.
Shopify
- In the Shopify admin, open Settings → Notifications → Webhooks (or create a subscription from your app).
- Use your catch URL as the destination, in JSON format.
- Shopify signs with your app's client secret. Save it in SlingHook's endpoint settings.
Anything else that sends HTTP works too: Slack, Twilio, Paddle, WorkOS, Svix and your own services. SlingHook accepts JSON, form data, XML and plain text.
Verify signatures
Add the provider's signing secret in Endpoint settings → Webhook signing secret. SlingHook then checks the HMAC signature on every request and marks it valid or invalid in the feed. It supports Stripe, GitHub, Shopify, Slack and Standard Webhooks (Svix). Choose the provider explicitly to stop a sender from switching to a weaker scheme.
When a signature fails, click the badge. The signature debugger tells you why: the wrong kind of secret (a Stripe API key instead of whsec_…), stray whitespace in the saved secret, a stale timestamp, a body that was reformatted in transit, or a payload cut off at the size limit. You can try another secret there without saving it.
Secrets are encrypted at rest on the server.
Custom responses
By default the catch URL answers 200 OK straight away so providers don't retry. Under Endpoint settings → Simulate catch response you can return another status, a delay or a custom body, which is handy for testing how a provider retries after a 500 or a timeout. Turning an endpoint off makes it answer 410 Gone.
Scenarios
Many integrations are a sequence, such as a Stripe checkout followed by its subscription and invoice events. Save those requests as a scenario from Scenarios in the inspector, then replay the whole flow in order with the original gaps, a fixed delay, or back to back. Each step shows its status, and the run can stop at the first failure. Requests in a scenario are kept when old logs are pruned.
CLI commands
| Command | What it does |
|---|---|
slinghook login [--server URL] [--token shk_…] | Signs in and saves an API token in ~/.config/slinghook/config.json. |
slinghook endpoints | Lists your endpoints and their UUIDs. |
slinghook listen <uuid> --forward URL | Forwards new webhooks to URL until you stop it. Add --no-report to keep deliveries out of the replay history. |
slinghook logout | Forgets the saved token. Revoke it under User settings → API tokens. |
SLINGHOOK_SERVER and SLINGHOOK_TOKEN override the saved settings.
Headers SlingHook adds
| Header | When |
|---|---|
X-Webhook-Replay: true | On every replay and CLI delivery, so your app can tell them apart from first deliveries. |
X-SlingHook-Log-Id | On CLI deliveries: the ID of the captured request. |
Transport headers such as Host, Content-Length and Connection are dropped and recalculated. Signature headers are kept.
Limits and status codes
| Free | Pro | Team | |
|---|---|---|---|
| Endpoints | 3 | Unlimited | Unlimited |
| Events a month | 1,000 | 100,000 | 500,000 |
| Request history | 24 hours | 30 days | 90 days |
Every plan stores up to 1 MB of each request body. Bigger payloads are kept up to that size and flagged as truncated, and a truncated request can't be replayed. See pricing for the full comparison.
| Status from the catch URL | Meaning |
|---|---|
200 | Captured. Or the status you set under custom responses. |
404 | No endpoint has that UUID. |
410 | The endpoint is turned off. |
429 | Too many requests in a short burst, or a Free account has used its events for the month. Retry-After says when to try again. Paid plans keep catching past their monthly events. |