Concepts
Three nouns carry the whole product: an Endpoint captures Requests, and forwarding turns each request into a Delivery with a full attempt history.
Learn these three nouns once and every screen and every API response is predictable.
Endpoint
An endpoint is a capture URL: https://in.webhookvault.dev/hook/{id}. Anything HTTP that
reaches it is stored — every method, any content type, binary bodies included (stored base64,
flagged bodyIsBinary). The endpoint answers the sender with the response you configure
(status, headers, body), independent of what happens to the request afterwards.
- An endpoint that is switched off answers
410and stops capturing — visibly dark, never half-alive. - A deleted endpoint answers
404, immediately. - An ephemeral endpoint (created with
ttlSeconds) answers404after its expiry and is then swept away with everything it captured — built for CI runs.
Sub-paths are captured too: senders can call …/hook/{id}/anything/here and the path is stored with
the request.
Captured request
A captured request is the stored record: method, path, query string, headers, body, source IP, size, timing. It lives until your plan's retention window expires it, you delete it, or the per-endpoint storage cap evicts it oldest-first — the vault always stores the newest arrival and ages out old ones rather than refusing a sender.
Two honesty flags matter when reading one back:
| Flag | Meaning |
|---|---|
bodyIsBinary | body holds base64 of the original bytes (invalid UTF-8 or NUL content). Decoded back to bytes on forward/replay. |
bodyTruncated | The body exceeded your plan's payload cap. Only its size was recorded; it cannot be replayed, and the API will say so rather than send a placeholder. |
Delivery
When forwarding is enabled, every capture becomes a delivery: a background job that relays the request to your destination URL, retries on failure with exponential backoff, and parks in a dead-letter state when retries are exhausted. Every attempt — automatic or manual — is recorded and readable via the attempts endpoint.
The delivery state on a request is always one of:
| State | In the app | Meaning |
|---|---|---|
NotAttempted | — | Forwarding was off when the request arrived. |
Pending | sending | Queued or in flight. |
Succeeded | delivered code | The destination answered 2xx. |
Failed | errored code | The destination answered, but not 2xx. |
Errored | errored | The destination was unreachable (DNS, refused, timeout). |
DeadLetter | gave up | Retries exhausted. A replay starts it fresh. |
Replay re-delivers any stored request on demand — one at a time (the outcome returns inline) or in bulk (queued through the same pipeline, outcomes land in the attempt history). Replaying is always safe on the vault's side: it re-sends exactly what was captured.
Where next?
- Quickstart — capture your first webhook
- CI testing mode — ephemeral endpoints and the await API
- API reference — every operation on these three nouns