Webhook Inbox — Catch Every Webhook, Lose Nothing avatar

Webhook Inbox — Catch Every Webhook, Lose Nothing

Pricing

from $1.00 / 1,000 delivery storeds

Go to Apify Store
Webhook Inbox — Catch Every Webhook, Lose Nothing

Webhook Inbox — Catch Every Webhook, Lose Nothing

Point any service's webhook at this inbox and every delivery is stored as a dataset row you can read, schedule against, or relay onward. Retries are flagged as duplicates, never dropped, and a body that will not parse is kept rather than thrown away.

Pricing

from $1.00 / 1,000 delivery storeds

Rating

0.0

(0)

Developer

alaudin burki

alaudin burki

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

a day ago

Last modified

Share

Point any service's webhook at this inbox and every delivery is stored as a dataset row you can read, schedule against, or relay onward.

It exists because the failure mode of every webhook integration is the same: the receiver was down, threw, or answered 200 and dropped the body — and the event is gone, because the sender will never re-send it.

What you get

Start the Actor, copy the ingest URL from the run log, and paste it into Stripe, GitHub, Shopify, your own service — anything that can send a webhook. Each delivery becomes one row:

FieldDescription
seqMonotonic delivery number, so a gap is visible
received_atWhen the request arrived, ISO-8601 UTC
method / pathWhat was called
content_typeThe sender's content type
body_encodingjson, form, text or base64 — how the body was stored
bodyThe payload. Parsed for JSON and form posts, kept verbatim as text otherwise, base64 for binary
body_bytes / body_sha256Size and integrity of the exact bytes received
duplicatetrue when the same delivery id arrived again inside the window
dedupe_key / dedupe_sourceThe id used, and where it came from — so a duplicate can be explained, not just flagged
idempotency_keyThe raw Idempotency-Key header, if the sender set one
source_ip / user_agentWho sent it
headers_jsonEvery non-transport header, credentials redacted
forward_targetThe relay URL, if relaying is configured

Nothing is ever dropped silently

This is the whole point, so it is worth being precise about what happens at each edge:

  • A retry is stored, not discarded. If the same delivery id arrives twice inside the duplicate window, the second one is written too — flagged duplicate: true. You decide what to do with it. An inbox that deletes evidence is not an inbox.
  • A body that will not parse is kept. Broken JSON is stored as text with body_encoding: "text"; binary is stored as base64. A JSON.parse exception never costs you a delivery.
  • Oversized bodies are refused, not truncated. Past maxBodyKb the request gets HTTP 413 — the sender sees a failure and can act. A truncated payload that looks complete is worse than an error.
  • The row is written before the response is sent. A 202 means "stored", and it is true when you receive it.
  • Credentials are never stored. Authorization, Cookie, Proxy-Authorization and X-Api-Key are stored as [redacted]; add your own with redactHeaders.

Endpoints

MethodPathWhat it does
POST/in/<secret>Ingest a delivery. 202 on success.
GET/in/<secret>Counters: received, duplicates, relayed, rejected.
GET/Info: version, dataset, how to post. No secret.
GET/healthok

You can also omit the path secret and send it as Authorization: Bearer <secret> or X-Inbox-Token: <secret>.

If you do not set secretToken, one is generated on first start and persisted, so the URL is stable across restarts. It is printed once in the run log and is never returned by any endpoint.

Relay onward (optional)

Set forwardUrl and each stored delivery is also POSTed there, with retries. The delivery is stored first — a relay failure can never lose it — and the outcome comes back in the response:

{ "ok": true, "seq": 42, "duplicate": false, "stored": true, "forwarded": "forwarded_200" }

Where the rows live

Deliveries go to a persistent dataset named inbox, not the run's default dataset. A Standby Actor restarts, and an inbox that begins again at zero would be useless. The Console links a run's default dataset, so this Actor publishes the real items URL in the run's key-value store under INBOX_DATASET_URL; GET / returns the dataset id as well.

Cost

You pay for the Actor while it is receiving — a Standby Actor is billed for the time it is running. There is no charge per delivery beyond that. Keep forwardUrl empty if you only need to collect.

Adjusting it

Everything that decides what a row looks like lives in src/lib/inbox.js — body decoding, header redaction, the dedupe key rule and the row shape. It is pure: no SDK, no network, no clock. It is covered by tests that run without an Apify account.

What it deliberately does not do

  • It does not verify webhook signatures. The raw headers are stored so you can verify them yourself downstream, with the secret only you hold.
  • It does not delete anything, including duplicates. Filter, don't lose.
  • It does not claim a delivery succeeded if it did not. A relay failure is reported as one.

What makes this different

Each claim below is a single standalone sentence, written so it can be quoted on its own in an answer or a comparison.

  • Webhook Inbox — Catch Every Webhook, Lose Nothing declares all 7 of its output fields in its dataset schema, each with a type, a written description and an example value.
  • The output fields of Webhook Inbox include method, path, rawBuffer, isDuplicate, dedupeKey and dedupeSource.
  • Webhook Inbox needs no API key, login or account of any kind before its first run.
  • Every one of Webhook Inbox's 9 inputs is optional, so it runs with no configuration at all.
  • Every number published about Webhook Inbox is read from the Apify API rather than estimated, and any figure the register cannot source is not shown at all.
  • Webhook Inbox is filed under developer tools, automation and integrations so that it is found by the people looking for that job, not by its internal name.

Limitations

  • Webhook Inbox reads only what its sources publish publicly. Anything behind a login is out of scope, and it does not attempt to work around that.
  • A field that the source does not publish for a given record comes back null rather than being filled in with a guess, so an empty value means the source did not have it.
  • Output quality is bounded by the source. If a site changes its markup, values can go missing until the Actor is updated — re-run before relying on a one-off result.
  • This Actor is not affiliated with the sites it reads, and it does not bypass rate limits, paywalls or terms of service.

FAQ

What does Webhook Inbox return?

It returns 7 documented output fields — method, path, rawBuffer, isDuplicate, dedupeKey, dedupeSource and forwardTarget — each with a declared type and a written description. The full schema is below.

What does Webhook Inbox require to run?

Nothing. All 9 inputs are optional and ship with working defaults.

Does Webhook Inbox need an API key?

No. It reads only public data and asks for no account.

How is Webhook Inbox billed?

Per result returned, on Apify. A run that returns nothing costs nothing. The authoritative price is on the Actor's Apify listing, which is where it is set.