Marketplace
Pre-built templates that post events from Stripe, Shopify, GitHub, Railway, Sentry or your own app to a Discord or Slack channel. Each one sets up the webhook in seconds.
What is the Marketplace?
The Marketplace is a collection of ready-made notification templates. Each template creates one webhook, already configured with:
- Signature verification for Stripe, Shopify and GitHub, the payload filters that drop the events the template does not post, and a retry count
- A payload transform that turns each event into a Discord embed or a Slack message
Without templates, setting this up manually takes ~30 minutes. With a template, it takes under 2 minutes.
How it works
When you use a template, HostWebhook sits between the webhook source (e.g. Stripe) and the Discord or Slack channel the template posts to:
- Ingress URL—Goes into the webhook settings of the source (Stripe, Shopify, GitHub…) — your webhook source POSTs here
- Target URL—The Discord or Slack webhook URL you paste when you use the template — the webhook's only destination
- Payload transform—Reshapes each event into that service's format: an embed for Discord, a text message for Slack
The template does not also forward the original event to your own server: Discord or Slack is the webhook's only destination.
Using a template
Open the Marketplace
Go to Dashboard → Marketplace and browse the available templates. Search, or filter by category (Payments, DevOps, etc.), to find what you need.
Click "Use template"
A setup modal opens with:
- Webhook name — pre-filled, you can edit it
- Discord URL or Slack URL — required: the channel's webhook URL, where the message goes. The hint under the field says where to get it: in Discord, Channel Settings → Integrations → Webhooks → New Webhook → Copy URL; in Slack, Apps → Incoming WebHooks → Add to Slack → Copy Webhook URL
- Then, in {source} — not a field: what to set up in Stripe, Shopify, GitHub, Railway, Sentry or your app so it sends its events to this webhook (step 4)
- Signature verification and Signature Secret — on every Stripe, Shopify and GitHub template; see The signing secret below
- Payload transform — collapsed; expand it to see and edit the transform that builds the message. An edited badge marks your changes, and Reset brings back the template's
Create stays disabled until you paste the Discord or Slack URL.
Click "Create →"
HostWebhook creates the webhook automatically, then redirects you to the webhook detail page. Your ingress URL is ready.
Add the Ingress URL to your webhook source
Copy the Ingress URL — shown as Webhook URL on the webhook detail page — and do what the modal's Then, in {source} box said:
- Stripe: in the Stripe Dashboard, add a webhook endpoint with the Ingress URL and select the template's event
- Shopify: Settings → Notifications → Webhooks → Create webhook. Choose the template's event and JSON format, and paste the Ingress URL
- GitHub: Repo → Settings → Webhooks → Add webhook. Paste the Ingress URL, set Content type to
application/json, use the same secret as in HostWebhook, and select the template's event - Railway: your project → Settings → Webhooks. Add the Ingress URL
- Sentry: Settings → Developer Settings → create an internal integration, set its Webhook URL to the Ingress URL and enable issue webhooks
- Your app: from your backend, POST JSON to the Ingress URL — see Events from your app
Each template's event is in What each template posts.
The signing secret
Every Stripe, Shopify and GitHub template — 26 of the 36 — verifies the provider's signature, so the setup modal turns Signature verification on and offers a Signature Secret field. You can paste it right away or leave it empty and paste it later: the webhook is created with verification on either way, and until the secret is set it rejects every event with a 401 that says the secret is missing (signing_secret_missing) — nothing gets in unverified. The webhook page shows a warning until you paste it. The Railway, Sentry and app-event templates have no signature to verify and do not ask. Where the secret comes from:
- Stripe: after adding the endpoint in the Stripe Dashboard, click "Reveal" next to its Signing secret and copy the
whsec_...value. Each endpoint has its own. - GitHub: the secret you type in the repository's webhook settings. You choose it, so use the same value in both places.
- Shopify: it depends on who created the webhook. One created in the Shopify admin, under Settings → Notifications → Webhooks, is signed with the key that same page shows. One created by an app is signed with that app's client secret.
whsec_... on the webhook page under Configuration → Edit → Incoming Signature Verification. Stripe retries failed deliveries for up to 3 days, so events sent in the meantime arrive once the secret is in.Available templates
Every template comes in two versions, one that posts to Discord and one that posts to Slack — 36 templates in all.
| Source | Category | Templates | Signature |
|---|---|---|---|
| Stripe | Payments | Payment, Failed Payment, Refund, Dispute, Subscription, New Customer | Stripe |
| Shopify | E-commerce | New Order, Fulfilled, Refund | Shopify |
| GitHub | DevOps | Push, Pull Request, Issue, Release | GitHub |
| Railway | DevOps | Deploy Failed, Deploy Success | — |
| Sentry | Security | Error | — |
| Your app | User Engagement | New User Signup, Account Deletion | — |
What each template posts
The template's payload filters let through only the events below. Anything else the source sends is marked filtered in the webhook's Events list and never reaches Discord or Slack.
| Template | Posts when |
|---|---|
| Stripe Payment | type is payment_intent.succeeded |
| Stripe Failed Payment | type is payment_intent.payment_failed |
| Stripe Refund | type is charge.refunded |
| Stripe Dispute | type is charge.dispute.created |
| Stripe Subscription | Only a new or a canceled subscription: type is customer.subscription.created or customer.subscription.deleted |
| New Stripe Customer | type is customer.created |
| Shopify New Order, Fulfilled, Refund | No payload filter: every event the Shopify webhook sends, so create that webhook for the template's event — Order creation, Order fulfillment or Refund create |
| GitHub Push | Every push to a branch. Tag pushes are skipped (ref must contain refs/heads/) |
| GitHub Pull Request | Only action opened or closed. A closed pull request that was merged is posted as merged |
| GitHub Issue | action is opened |
| GitHub Release | action is published |
| Railway Deploy Failed | type is Deployment.failed |
| Railway Deploy Success | type is Deployment.deployed |
| Sentry Error | Only new issues: action is created. Resolving, assigning or archiving an issue posts nothing |
| New User Signup | event is user.created |
| Account Deletion | event is user.deleted |
| divide(100) | round(2)), which is right for two-decimal currencies. For a zero-decimal currency such as JPY or KRW the amount comes out 100 times too small: remove | divide(100) from the transform.Events from your app
The New User Signup and Account Deletion templates expect your backend to POST JSON like this to the Ingress URL:
{"event": "user.created", "user": {"name": "Jane Doe", "email": "jane@example.com"}}
{"event": "user.deleted", "user": {"name": "Jane Doe", "email": "jane@example.com", "reason": "Too expensive"}}reason is optional.
Troubleshooting
Events are not being delivered to Discord/Slack
- Check that the Ingress URL is correctly configured in the source — Stripe, Shopify, GitHub, Railway, Sentry or your app
- Check that the signing secret in HostWebhook matches the one that signs the webhook — for Shopify, the admin's key or the app's client secret, depending on who created it
- Check the Events list on the webhook — look for
filteredevents (payload filter mismatch; see What each template posts) orfaileddeliveries - Click any failed delivery to see the HTTP response from Discord/Slack
- Discord and Slack return
400when the body is not a message they accept — Discord, for example, rejects an embed field with an empty value. If you edited the payload transform, check it on the webhook detail page
Payload transform shows wrong values
The transform uses {{payload.path}} interpolation. If a field is missing, it resolves to an empty string. Use the null coalescing operator to provide a fallback: {{payload.customer ?? 'Guest'}}. See the Payload transforms guide for the full syntax.