ingestlayer/docs/v0.4

docs · 04 reference

Webhook ingress.

The way in for anything that already speaks webhook — Stripe, GitHub, Calendly, your own backend. The URL is the source: a unique token per source, verified at the gate before the proxy touches storage.

URL shape

One per source.

endpoint↵ copy
# Each webhook source has its own URL, of the form:
https://in.ingestlayer.com/whk/<token>

# the token is opaque, rotatable, and unique per source.
# you find it under the source's row in /sources.

Webhook sources are created automatically for each org at bootstrap; additional ones can be created at /sources/new with the webhook.in kind. The token is regeneratable from the source detail page — old token stops working immediately.

Auth modes

HMAC, bearer, or open.

Each source declares one auth mode in its config. The proxy rejects every request that doesn't satisfy it.

signed · HMAC-SHA256 (default)

signed mode↵ copy
# verify with HMAC-SHA256 over the raw request body
# signing_secret is shown once when you create the source

X-Ingest-Signature: sha256=<hex>

# the proxy:
# 1. computes hmac(body, signing_secret)
# 2. timing-safe compares against the header
# 3. accepts on match, 401s on mismatch

bearer · static token

bearer mode↵ copy
# alternative: simple bearer token

Authorization: Bearer <bearer_token>

Useful for senders that don't support HMAC signing. Rotate the token if you suspect it leaked — same effect as rotating an API key.

none · open

Testing only. Anyone who knows the token can post. Useful for getting started, not for production traffic.

Event shape

Body in, event out.

POST · the body becomes the payload↵ copy
# the request body becomes the event payload as-is.
# if it has a string "type" field, that becomes event.type.
# otherwise the proxy stamps a default: "<source-kind>.received"

$ curl -X POST https://in.ingestlayer.com/whk/$TOKEN \
    -H "Authorization: Bearer $BEARER" \
    -H "Content-Type: application/json" \
    -d '{
      "type": "github.push",
      "ref":  "refs/heads/main",
      "head_commit": { "id": "abc123", "message": "ship it" }
    }'

Once auth passes, the webhook is rate-limited per source so one bursting endpoint doesn't starve the others. The event's type comes from the body's type field if it's a string, otherwise we stamp <source-kind>.received (e.g. stripe.received). The source is attached to the event automatically. A 202 in response means it's durable.

Idempotency

Same key as the SDK.

Pass X-Ingest-Idempotency-Key in the request headers. Same dedupe semantics as the SDK: identical key within the window is a no-op (returns 202 without writing a second event row).


REST APIback to docsnext: glossary