Skip to main content

Documentation Index

Fetch the complete documentation index at: https://supahooks.ar27111994.dev/llms.txt

Use this file to discover all available pages before exploring further.

Find answers to the most common questions about configuring and using Webhook Debugger & Logger. If you need more detail on a specific topic, see the API reference or the input configuration reference.
Set retentionHours anywhere from 1 to 168 hours (default: 24). Once a webhook expires, it stops accepting traffic immediately. Its logs are purged from the /logs query endpoint during the next cleanup cycle, which runs approximately every 10 minutes.Reducing retentionHours via hot-reload only affects newly generated webhooks — webhooks that already exist keep their original expiry window. Events already written to the Apify Dataset are retained independently of this setting.
Call GET /info at any time to see each active webhook’s id and expiresAt timestamp.
Yes. You can layer multiple controls for defense in depth:
  • authKey — callers must pass the key as Authorization: Bearer <key> or ?key=<key>. When set, webhook ingest also requires this key, so add it to your provider’s webhook configuration.
  • allowedIps — restrict traffic to specific IPs or CIDR blocks.
  • Signature verification — automatically verify HMAC signatures from Stripe, GitHub, Shopify, Slack, or a custom provider.
  • maskSensitiveData — redact Authorization, Cookie, Set-Cookie, and API key headers from stored logs.
  • redactBodyPaths — redact specific dot-notation paths from the JSON body before storage.
Generated webhook URLs are public unless you configure at least one of the above controls. Do not point sensitive production traffic at unsecured endpoints.
Yes. Send a POST request to the replay endpoint with a destination URL:
curl -X POST \
  "https://<run-id>.runs.apify.net/replay/<webhookId>/<itemId>?url=https://target.example/webhook"
The actor strips masked and transport-managed headers before forwarding, then adds X-Apify-Replay: true, X-Original-Webhook-Id, and an Idempotency-Key to the outbound request. The response includes the target’s status code and body, plus a strippedHeaders list when any headers were removed.
The url query parameter is required. Replay targets that resolve to private or reserved IP ranges are blocked by SSRF protection.
Yes. Configure the response behavior using these input fields:
InputPurpose
defaultResponseCodeHTTP status code returned to the sender
defaultResponseBodyResponse body (JSON, XML, or plain text)
defaultResponseHeadersExtra headers included in every response
responseDelayMsArtificial delay added after processing (0–10,000 ms)
You can also override the status code on a per-request basis by appending ?__status=<code> to the webhook URL. This is useful for simulating 4xx or 5xx responses without changing the global configuration.
Captured events are stored in three places with different roles:
  • Apify Dataset — the durable source of truth. Every captured event is written here and retained independently of retentionHours.
  • DuckDB — a local read model that mirrors Dataset records for fast filtering and pagination at /logs. DuckDB syncs asynchronously, so there may be a short lag before new events appear in query results.
  • Apify Key-Value Store — holds active webhook state and stores large payload offloads that exceed the in-memory threshold.
If /logs doesn’t show a recent event yet, check /system/metrics to see the current Dataset-to-DuckDB sync status.
Requests whose body exceeds maxPayloadSize (default: 10 MB) are rejected with a 413 status.For payloads that are within the size limit but above the Key-Value Store offload threshold, the actor stores the payload content in KVS rather than keeping it in the in-memory read model. The event remains fully queryable via /logs, and you can retrieve the full payload on demand by calling GET /logs/:logId/payload.
Yes. You can run Webhook Debugger & Logger locally or in your own infrastructure without an Apify account.Node.js (20+):
npm install
npm start
Docker:
docker build -t webhook-debugger-logger .

docker run --rm -p 8080:8080 \
  -e ACTOR_WEB_SERVER_PORT=8080 \
  -e APIFY_LOCAL_STORAGE_DIR=/app/storage \
  webhook-debugger-logger
The server listens on port 8080 by default. Use the ACTOR_WEB_SERVER_PORT environment variable to change the port, and pass your actor input as the INPUT environment variable.
You can create between 1 and 50 webhook URLs per run using the urlCount input (default: 3). Each URL gets its own unique ID and expiry time.All endpoints generated in a single run share the same configuration settings for auth, signature verification, response mocking, and forwarding.
Yes. Set the jsonSchema input to a valid JSON Schema string. Incoming payloads that do not match the schema are rejected with a 400 Bad Request response before the event is stored.
{
  "jsonSchema": "{\"type\":\"object\",\"required\":[\"event\"],\"properties\":{\"event\":{\"type\":\"string\"}}}"
}
This is useful for enforcing a contract during integration testing without adding validation logic to your own service.
Yes. The customScript input accepts a JavaScript snippet that runs before the event is stored. Use it to normalize shapes, inject debug metadata, strip or remap fields, or mark events for downstream routing.
if (event.contentType === 'application/json') {
  const body = typeof event.body === 'string' ? JSON.parse(event.body) : event.body;
  event.body = { ...body, normalized: true, source: 'webhook-debugger' };
}
Scripts run in a sandboxed worker isolate. They have access to event, a read-only copy of req, console, and HTTP_STATUS, but no access to the filesystem, network, process, or require. eval() and Function() are disabled. If a script fails or times out, the error is logged and the capture pipeline continues normally.
Hot-reload lets you apply input changes without restarting the actor.
  • On Apify: the runtime polls the Key-Value Store for an updated actor input.
  • Locally: it watches storage/key_value_stores/default/INPUT.json for changes.
Reloadable settings include rate limiters, auth, retention, replay settings, forwarding settings, and parser limits. Changes take effect for new requests immediately after the reload is applied.Set the environment variable DISABLE_HOT_RELOAD=true if you want a fixed configuration for reproducible test runs.
Reducing retentionHours via hot-reload only affects new webhooks. Existing webhooks keep their original expiry window.
You can configure alerts to fire on any combination of these conditions:
TriggerWhen it fires
errorAn internal processing error occurs
4xxThe captured request results in a 4xx status
5xxThe captured request results in a 5xx status
timeoutA forwarding or replay attempt times out
signature_invalidSignature verification fails
Configure a Slack or Discord webhook URL in the alerts input and list the triggers you want in alertOn:
{
  "alerts": {
    "slack": { "webhookUrl": "https://hooks.slack.com/services/..." }
  },
  "alertOn": ["error", "4xx", "5xx", "timeout", "signature_invalid"]
}