Public Beta: Direct engineering support available. Join Discord →
Docs
Recipes
Generic: Route Any Webhook Provider

Route Webhooks From Any Provider

Time: ~10 minutes | Difficulty: Beginner | Prerequisites: A provider that can POST JSON to a URL you give it, Slashbin account

TL;DR: Slashbin's gateway has no per-provider code. Shopify, Stripe, Square, GitHub, Typeform, LinkedIn, VideoAsk and QuickBooks each work because a row of configuration describes how to verify them — and Generic is that same mechanism with the configuration handed to you. Your provider gets the same verification, the same delivery log, the same retries, the same replay, and the same transforms as any named source. Nothing about the pipeline is downgraded for using it.


The Problem

You are integrating a provider we do not name on the Integrations page — Paddle, Twilio, Intercom, Calendly, a partner's order service, your own internal event bus. The list has eight logos and none of them are yours.

A named logo reads as supported. A card labelled "Generic" reads as fallback, and a fallback implies something is missing: fewer guarantees, a slower path, a feature you will discover you do not have three weeks in.

That reading is wrong, and the reason it is wrong is not obvious from the card:

  • There is no provider-specific code to be missing. Verification is driven entirely by stored configuration — which header carries the signature, how the digest is encoded, whether there is a prefix, what gets signed. Shopify is not a code path; it is a row. Generic is a row too.
  • The routing mechanism is the part nobody has written down. Generic is the only source that reads the topic from a header and falls back to the body. That fallback is precisely what lets an arbitrary provider route correctly without you writing parsing code — and it exists today as two columns in a database, described nowhere a developer would look.
  • So the honest question — "will this work with my provider?" — has no answer on the page. You cannot tell from the card whether Generic means "bring anything" or "good luck."

It means bring anything. Here is exactly what it expects.


The Solution

Create a Generic project. Slashbin becomes the URL your provider posts to, and the contract it applies is fixed and published:

FieldGeneric's value
Auth typeHMAC
Secret labelHMAC Signing Secret
Signature headerX-Slashbin-Signature
Signature encodinghex
Signature prefixnone
Signed payloadthe raw request body
Event topicx-webhook-topic, read from the headers
Topic fallbacktype, read from the body

Everything downstream of that row is identical to every other source:

  • The raw payload exactly as your provider sent it — bytes and headers.
  • Signature verification at the gateway, before your Golden Model or any destination sees the event.
  • The resolved topic — what Slashbin actually read for that specific request.
  • The transform result — what your model produced, or the error it threw.
  • Every delivery attempt — response code, response body, and timing.
  • The final disposition — delivered, retrying, or held in the Dead Letter Queue.

Outcome: an unlisted provider gets the same pipeline as a listed one. The only difference is that you supply the two facts a logo would otherwise imply — how the request is authenticated, and where the topic lives.


Step 1: Create a Generic Project in Slashbin

  1. Click Create New Project and select Generic.
  2. Type: Choose Transactional for discrete business events — an order, a signup, a payment. Choose the metric type only for high-volume telemetry you aggregate rather than act on individually.
  3. HMAC Signing Secret — enter a strong random string. Unlike Stripe or Square, nobody generates this for you; you are both ends of this contract, so you pick the secret.
  4. Copy the Ingestion URL from the project dashboard. That is the URL your provider will post to.

Selecting Generic loads the contract in the table above. You are not configuring a signature scheme — you are being told one.


Step 2: Sign Your Requests, or Configure the Header Your Provider Already Sends

There are two cases, and which one you are in depends on a single question: can you change what the sender puts in the request?

Case A — you control the sender

This covers your own services, a partner's system you have a contract with, and anything running in an automation platform that lets you set outbound headers.

Compute HMAC-SHA256 of the raw request body using the signing secret from Step 1, hex-encode the digest, and send it as the value of X-Slashbin-Signature — the bare digest, with no sha256= prefix and no other decoration.

Two details that account for most first-attempt failures:

  • Sign the bytes you send, not a re-serialized object. If your sender pretty-prints the JSON after signing it, or reorders keys, the digest no longer describes the body that arrived. Sign the exact byte sequence that goes on the wire.
  • No prefix means no prefix. sha256= is GitHub's and Typeform's convention, not a universal one. Sending sha256=abc123… where Generic expects abc123… fails verification with an error identical to a wrong secret.

Case B — you do not control the sender

Plenty of SaaS products will POST to any URL but will not sign for you. Many of them will let you attach a static custom header — check the webhook settings before assuming otherwise.

When that is all you have, Slashbin can compare a shared header token against the stored secret in constant time instead of computing a digest. There is no signing payload and no encoding involved on that path; the header either matches the secret or it does not. VideoAsk is a named source that works exactly this way, so this is not an improvised workaround — it is a supported authentication mode.

⚠️

A shared token is a bearer secret: anyone who sees one request sees the credential, and it does not bind the secret to the body. It is the right choice when the alternative is no authentication at all, and the wrong choice when you could sign instead. If you control the sender, use Case A.


Step 3: Give Slashbin a Topic to Route On

The topic is the routing key — the value your rules match on to decide which transform runs and which destinations receive the event. Generic is the only source that will look in two places for it.

First, the x-webhook-topic header. If it is present, that value is the topic.

If that header is absent, the type field in the JSON body. This is the fallback, and it is what makes an unlisted provider work without any code on your side.

If you control the sender: send the header

Set x-webhook-topic explicitly and you never have to think about payload shape again:

POST /ingest/… HTTP/1.1
Content-Type: application/json
X-Slashbin-Signature: 9f2b1c04e7a3…
x-webhook-topic: order.fulfilled

The topic is order.fulfilled regardless of what the body contains. This is the sturdier of the two options: the routing key stops depending on the payload schema, so a downstream change to the body cannot silently change how events route.

If you do not control the sender: use the body fallback

Most event-shaped JSON already carries a type field, and anything emitting CloudEvents (opens in a new tab)-structured JSON carries one by specification. A body like this routes correctly with no header at all:

{
  "specversion": "1.0",
  "type": "com.acme.invoice.paid",
  "source": "/billing/invoices",
  "id": "9f8a2c1e-4d3b-4f7a-9c11-2a6e5b0d8f34",
  "time": "2026-07-21T14:03:22Z",
  "data": {
    "invoice_id": "inv_8812",
    "account_id": "acct_4471",
    "amount_cents": 24900,
    "currency": "USD"
  }
}

Slashbin finds no x-webhook-topic, falls back to the body, and resolves the topic to com.acme.invoice.paid. Your rules match on that string, your Golden Model flattens data into whatever your warehouse wants, and the fact that this provider is not on our list never comes up again.

If your provider sends neither

If there is no header you can set and no type in the body, you have a routing decision to make, not code to write. Point that provider at its own Generic project, where every event is unambiguous because only one kind arrives, and let the project — rather than the topic — be what your rules key on.

The topic is read after verification, never before. A request that fails the signature check is rejected at the gateway and never reaches topic resolution — so a topic problem and an authentication problem are always two distinguishable entries in the delivery log, not one ambiguous failure.


Step 4: Deliver, Retry, and Replay

On the Outbound tab, click + Add Destination and point it at the system that should own the event. One event can fan out to several destinations, each with its own retry policy.

The guarantees here are the same ones the named sources get:

  • Transient failure → retry with backoff. Your handler returning 502 for ninety seconds costs you nothing.
  • Exhausted attempts → the Dead Letter Queue, holding the original raw payload, not a summary of it.
  • Fixed the handler → Replay. Slashbin re-delivers from its own storage; your provider is not involved and does not need to be. This matters more for an unlisted provider than a listed one, because obscure webhook implementations are exactly the ones with no replay button of their own.
  • Nothing arrived downstream but the log says delivered? The attempt record carries your endpoint's exact response body.

Because the transform runs at the gateway, replay always operates on the original payload through the current model — so you can map a field on Tuesday and re-run Monday's events through the new mapping.


Where Generic Stops

Generic covers HMAC-SHA256 over the raw body and shared-token headers. It cannot express every scheme in the wild, and the boundary is worth stating plainly:

  • Signatures that include a timestamp. Stripe's scheme signs a concatenation of the timestamp and the body and sends both in one header. Generic signs the body alone.
  • Signatures over something other than the body. Square signs the notification URL concatenated with the body — the URL is part of the signed material.
  • Anything that is not HMAC-SHA256 — SHA-1 schemes, asymmetric signatures, and mutual-TLS-based verification.

If your provider needs one of those, do not build a shim in front of Slashbin to normalize it. That shim becomes an unverified hop, which is the exact thing this product exists to remove. Ask us for a first-class source instead — adding one is configuration on our side, which is why the list grows.


Why Slashbin vs a Raw Handler

  • You write no verification code. Hex-encoded HMAC-SHA256 over the raw body in X-Slashbin-Signature, no prefix — applied at the gateway. The most common way a hand-rolled check fails is a non-constant-time comparison or a body that was re-serialized before hashing; neither is reachable from here.
  • Routing without body-parsing code. A header or a type field becomes a routing rule instead of an if-else chain at the top of your controller.
  • One contract across every source. Add a listed provider next month and your handlers do not change — Generic and the named sources produce the same downstream shape.
  • Delivery is retried and replayable from Slashbin's storage, on your schedule.
  • Silence becomes evidence. An event that arrived and matched no rule is a log entry with a resolved topic you can read, not an empty dashboard you have to guess at.

Next Steps