{"id":37629507,"url":"https://github.com/ar27111994/webhook-debugger-logger","last_synced_at":"2026-04-25T18:06:52.855Z","repository":{"id":329772247,"uuid":"1120109772","full_name":"ar27111994/webhook-debugger-logger","owner":"ar27111994","description":"Enterprise-grade webhook testing suite for developers. Capture, inspect, replay, forward, validate, and mock webhook traffic in real time without tunnels. Includes SSE live streaming, JSON Schema validation, and signature verification for Stripe, GitHub, Shopify, Slack, and custom HMAC workflows.","archived":false,"fork":false,"pushed_at":"2026-04-25T12:46:11.000Z","size":37044,"stargazers_count":25,"open_issues_count":1,"forks_count":3,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-25T14:25:36.022Z","etag":null,"topics":["api-mocking","api-testing","debugging","developer-tools","docker","express","http-replay","nodejs","real-time","self-hosted","shopify","sse","stripe","webhook-testing","webhooks"],"latest_commit_sha":null,"homepage":"https://apify.com/ar27111994/webhook-debugger-logger","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ar27111994.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"docs/roadmap/conditional-multi-provider-verification.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"patreon":"ar27111994","ko_fi":"ar27111994","liberapay":"ar27111994","buy_me_a_coffee":"ar27111994","thanks_dev":"d/gh/ar27111994"}},"created_at":"2025-12-20T14:06:58.000Z","updated_at":"2026-04-20T08:43:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ar27111994/webhook-debugger-logger","commit_stats":null,"previous_names":["ar27111994/webhook-debugger-logger"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/ar27111994/webhook-debugger-logger","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar27111994%2Fwebhook-debugger-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar27111994%2Fwebhook-debugger-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar27111994%2Fwebhook-debugger-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar27111994%2Fwebhook-debugger-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ar27111994","download_url":"https://codeload.github.com/ar27111994/webhook-debugger-logger/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar27111994%2Fwebhook-debugger-logger/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32271289,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T09:15:33.318Z","status":"ssl_error","status_checked_at":"2026-04-25T09:15:31.997Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-mocking","api-testing","debugging","developer-tools","docker","express","http-replay","nodejs","real-time","self-hosted","shopify","sse","stripe","webhook-testing","webhooks"],"created_at":"2026-01-16T10:55:06.738Z","updated_at":"2026-04-25T18:06:52.847Z","avatar_url":"https://github.com/ar27111994.png","language":"JavaScript","funding_links":["https://patreon.com/ar27111994","https://ko-fi.com/ar27111994","https://liberapay.com/ar27111994","https://buymeacoffee.com/ar27111994","https://thanks.dev/d/gh/ar27111994","https://www.patreon.com/cw/ar27111994","https://img.shields.io/badge/Support-thanks.dev-181717?logo=github\u0026logoColor=white"],"categories":[],"sub_categories":[],"readme":"# Webhook Debugger, Logger \u0026 API Mocking Suite\n\n![Webhook Debugger and Logger logo](https://raw.githubusercontent.com/ar27111994/webhook-debugger-logger/main/assets/icon-160.png)\n\nGenerate temporary webhook URLs, inspect every incoming request, replay failures, and simulate callback behavior without tunneling localhost.\n\n## Status\n\n[![Build Status](https://github.com/ar27111994/webhook-debugger-logger/actions/workflows/ci.yml/badge.svg)](https://github.com/ar27111994/webhook-debugger-logger/actions/workflows/ci.yml)\n[![GitHub release](https://img.shields.io/github/v/release/ar27111994/webhook-debugger-logger)](https://github.com/ar27111994/webhook-debugger-logger/releases)\n[![npm version](https://img.shields.io/npm/v/webhook-debugger-logger)](https://www.npmjs.com/package/webhook-debugger-logger)\n[![npm downloads](https://img.shields.io/npm/dm/webhook-debugger-logger)](https://www.npmjs.com/package/webhook-debugger-logger)\n[![Node.js](https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js\u0026logoColor=white)](https://nodejs.org/)\n[![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)\n[![GHCR](https://img.shields.io/badge/GHCR-Container%20Image-2496ED?logo=docker\u0026logoColor=white)](https://github.com/ar27111994/webhook-debugger-logger/pkgs/container/webhook-debugger-logger)\n![CodeRabbit Pull Request Reviews](https://img.shields.io/coderabbit/prs/github/ar27111994/webhook-debugger-logger?utm_source=oss\u0026utm_medium=github\u0026utm_campaign=ar27111994%2Fwebhook-debugger-logger\u0026labelColor=171717\u0026color=FF570A\u0026link=https%3A%2F%2Fcoderabbit.ai\u0026label=CodeRabbit+Reviews)\n\n[![Webhook Debugger, Logger \u0026 API Mocker - Debug webhooks 90% faster without localhost tunneling | Product Hunt](https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1057655\u0026theme=light\u0026t=1767529788592)](https://www.producthunt.com/products/webhook-debugger-logger-api-mocker?embed=true\u0026utm_source=badge-featured\u0026utm_medium=badge\u0026utm_campaign=badge-webhook-debugger-logger-api-mocker)\n\n## Run \u0026 Docs\n\n[![Open actor in the Apify Store](https://img.shields.io/badge/Apify%20Store-Open%20Actor-5A4FCF?logo=apify\u0026logoColor=white)](https://apify.com/ar27111994/webhook-debugger-logger)\n[![Run actor on Apify](https://img.shields.io/badge/Run%20on-Apify-6B46FF?logo=apify\u0026logoColor=white)](https://console.apify.com/actors/ar27111994~webhook-debugger-logger/input)\n[![Read the API reference](https://img.shields.io/badge/API-Reference-0F766E?logo=swagger\u0026logoColor=white)](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/api-reference.md)\n[![Self-host with Docker](https://img.shields.io/badge/Self--host-Docker-2496ED?logo=docker\u0026logoColor=white)](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/local_docker_testing.md)\n\n## Sponsor\n\n[![Patreon](https://img.shields.io/badge/Support-Patreon-FF424D?logo=patreon\u0026logoColor=white)](https://www.patreon.com/cw/ar27111994)\n[![Ko-fi](https://img.shields.io/badge/Support-Ko--fi-29ABE0?logo=kofi\u0026logoColor=white)](https://ko-fi.com/ar27111994)\n[![Liberapay](https://img.shields.io/badge/Support-Liberapay-F6C915?logo=liberapay\u0026logoColor=black)](https://liberapay.com/ar27111994)\n[![Buy Me a Coffee](https://img.shields.io/badge/Support-Buy%20Me%20a%20Coffee-FFDD00?logo=buymeacoffee\u0026logoColor=000000)](https://buymeacoffee.com/ar27111994)\n[![thanks.dev](https://img.shields.io/badge/Support-thanks.dev-181717?logo=github\u0026logoColor=white)](https://thanks.dev/d/gh/ar27111994)\n\n## Contribute\n\n[![Report a bug](https://img.shields.io/badge/Report-Bug-d73a4a?logo=github\u0026logoColor=white)](https://github.com/ar27111994/webhook-debugger-logger/issues/new?template=bug_report.md)\n[![Request a feature](https://img.shields.io/badge/Request-Feature-1f883d?logo=github\u0026logoColor=white)](https://github.com/ar27111994/webhook-debugger-logger/issues/new?template=feature_request.md)\n[![View changelog](https://img.shields.io/badge/View-Changelog-6f42c1?logo=readthedocs\u0026logoColor=white)](https://github.com/ar27111994/webhook-debugger-logger/blob/main/CHANGELOG.md)\n[![Security policy](https://img.shields.io/badge/Security-Policy-ffb000?logo=shield\u0026logoColor=white)](https://github.com/ar27111994/webhook-debugger-logger/blob/main/SECURITY.md)\n[![Contributing](https://img.shields.io/badge/Contributing-Guide-0969da?logo=github\u0026logoColor=white)](https://github.com/ar27111994/webhook-debugger-logger/blob/main/CONTRIBUTING.md)\n[![Code of Conduct](https://img.shields.io/badge/Code%20of-Conduct-ff69b4?logo=github\u0026logoColor=white)](https://github.com/ar27111994/webhook-debugger-logger/blob/main/CODE_OF_CONDUCT.md)\n\nWebhook Debugger, Logger \u0026 API Mocking Suite is an [Apify Actor](https://apify.com/ar27111994/webhook-debugger-logger) for testing webhook integrations end to end. It generates temporary endpoints, captures the full request envelope, exposes live and queryable logs, and lets you replay or forward captured traffic to another destination.\n\nIt is designed for developers working with providers such as Stripe, GitHub, Shopify, Slack, and custom internal webhooks who need more than a generic request bin.\n\n\u003e [!NOTE]\n\u003e This actor is optimized for testing, debugging, replay, and callback simulation. If you need permanent public ingress or long-term retention, place it behind your own infrastructure or run the self-hosted container with persistent storage.\n\n---\n\n\u003e [!WARNING]\n\u003e Generated webhook URLs are public unless you enable `authKey`, `allowedIps`, or signature verification. Do not point sensitive production traffic to unsecured endpoints.\n\n---\n\n## Screenshots\n\n\u003e [!NOTE]\n\u003e The Apify Store input tab always reflects the most recently published build. To avoid showing stale configuration fields, this README documents input options from the current repo schema in [.actor/input_schema.json](https://github.com/ar27111994/webhook-debugger-logger/blob/main/.actor/input_schema.json) and uses a live local runtime screenshot below.\n\n### Built-in dashboard\n\n![Self-hosted dashboard page showing the actor title, online status, active webhook count, and quick link to the info endpoint](https://raw.githubusercontent.com/ar27111994/webhook-debugger-logger/main/assets/dashboard-live.png)\n\n## Key input options\n\nThe current repo schema is defined in [.actor/input_schema.json](https://github.com/ar27111994/webhook-debugger-logger/blob/main/.actor/input_schema.json). These are the settings most users touch first.\n\n| Input                   | Purpose                                                                                                                  | Default    |\n| ----------------------- | ------------------------------------------------------------------------------------------------------------------------ | ---------- |\n| `urlCount`              | Number of temporary webhook endpoints to generate                                                                        | `3`        |\n| `retentionHours`        | How long generated webhook URLs remain active                                                                            | `24`       |\n| `maxPayloadSize`        | Maximum accepted request body size in bytes; values above 100 MB are clamped                                             | `10485760` |\n| `enableJSONParsing`     | Parse JSON payloads into structured objects for search                                                                   | `true`     |\n| `maskSensitiveData`     | Redact sensitive headers such as `Authorization`, `Cookie`, `Set-Cookie`, and API key headers from logs                  | `true`     |\n| `authKey`               | Protect management routes and optionally webhook ingest with a shared key                                                | unset      |\n| `allowedIps`            | Restrict traffic to specific IPs or CIDR blocks                                                                          | empty      |\n| `signatureVerification` | Verify Stripe, Shopify, GitHub, Slack, or custom signatures                                                              | unset      |\n| `forwardUrl`            | Forward every captured request to another destination                                                                    | unset      |\n| `defaultResponseCode`   | Return a custom HTTP status to the sender                                                                                | `200`      |\n| `responseDelayMs`       | Add an artificial response delay after processing completes; accepted range is 0-10,000 ms and higher values are clamped | `0`        |\n| `jsonSchema`            | Reject payloads that do not match a JSON Schema                                                                          | unset      |\n| `customScript`          | Transform or enrich the captured event before storage                                                                    | unset      |\n\n![Input schema preview from the Apify Actor input tab](https://raw.githubusercontent.com/ar27111994/webhook-debugger-logger/main/assets/input_schema_preview.png)\n\n## What does this actor do?\n\nThis project gives you a disposable webhook test environment with a documented HTTP API.\n\nIt helps you:\n\n- generate 1 to 50 unique webhook URLs for a run\n- inspect headers, query params, payloads, response status, timing, IP, and signature state\n- stream events live over Server-Sent Events (SSE)\n- replay captured requests to a new destination\n- forward incoming traffic to another endpoint with retries and circuit breaking\n- simulate downstream behavior with custom status codes, response bodies, headers, and latency\n- trigger Slack or Discord alerts when a webhook run needs attention\n- handle large request bodies by enforcing size limits and offloading oversized accepted payloads to storage\n- validate JSON payloads and run custom JavaScript transformation scripts before storage\n- plug the actor into Apify-native workflows, API automation, and MCP-enabled tooling that orchestrates Apify runs and datasets\n\n## Why use it?\n\nWebhook debugging is usually split across too many tools.\n\n- You need one tool to expose a public URL.\n- Another tool stores payloads.\n- Another tool replays failures.\n- Another tool simulates custom responses.\n\nThis actor combines those workflows in one place.\n\n### Problems it solves\n\n- No more tunneling localhost just to inspect a payload.\n- No more guessing what a provider actually posted.\n- No more manually rebuilding failed callbacks for retries.\n- No more separate mock server just to test response codes or latency.\n\n### Why teams pick it over a generic request bin\n\n- It captures requests and exposes a searchable API, not just raw dumps.\n- It supports replay and forwarding, not only passive logging.\n- It can validate signatures for common webhook providers.\n- It can alert Slack or Discord when capture, validation, or downstream delivery fails.\n- It supports inline custom scripting for payload cleanup and transformation.\n- It includes health, readiness, and metrics endpoints for operational setups.\n- It can run on Apify or as a self-hosted Node/Docker service.\n- It resumes background Dataset-to-DuckDB sync cleanly across stop, retry, and restart paths, which keeps self-hosted and test harness restarts predictable.\n\n## What can this actor do?\n\n| Feature                | What you get                                                                                             |\n| ---------------------- | -------------------------------------------------------------------------------------------------------- |\n| Temporary webhook URLs | Generate 1-50 unique endpoints per run with configurable retention                                       |\n| Full request capture   | Method, headers, query, body, response body, response headers, size, latency, IP                         |\n| Searchable logs        | DuckDB-backed `/logs` queries with pagination and detailed retrieval                                     |\n| Live streaming         | Real-time event feed over `/log-stream` using SSE                                                        |\n| Replay workflows       | Replay a captured request to a different target URL                                                      |\n| HTTP forwarding        | Forward every incoming request to a destination with retries and circuit breaker protection              |\n| API mocking            | Return custom status codes, headers, bodies, and artificial latency                                      |\n| Alert notifications    | Send Slack or Discord notifications for `error`, `4xx`, `5xx`, `timeout`, or `signature_invalid` events  |\n| Security controls      | Global API key, IP allowlist, sensitive header masking, provider signature verification                  |\n| Large payload handling | Enforce request size limits and offload large accepted payloads so inspection stays practical            |\n| Payload validation     | Optional JSON Schema validation and custom JavaScript transforms                                         |\n| Platform integrations  | Apify web server, Dataset, Key-Value Store, saved runs, API automation, and MCP-friendly Apify workflows |\n| Ops endpoints          | `/health`, `/ready`, `/system/metrics`, and `/info`                                                      |\n\n## Quick start on Apify\n\n### 1. Start the actor with a minimal config\n\n```json\n{\n  \"urlCount\": 3,\n  \"retentionHours\": 24,\n  \"enableJSONParsing\": true,\n  \"maskSensitiveData\": true\n}\n```\n\n### 2. Open the generated runtime info\n\nAfter the actor starts, open the web server URL and call `/info`.\n\n```json\n{\n  \"version\": \"3.0.5\",\n  \"status\": \"Enterprise Suite Online\",\n  \"system\": {\n    \"authActive\": false,\n    \"retentionHours\": 24,\n    \"maxPayloadLimit\": \"10.0MB\",\n    \"webhookCount\": 3,\n    \"activeWebhooks\": [\n      {\n        \"id\": \"wh_demo123\",\n        \"expiresAt\": \"2026-04-03T10:20:14.527Z\"\n      }\n    ]\n  },\n  \"features\": [\n    \"High-Performance Logging \u0026 Payload Forensics\",\n    \"Real-time SSE Log Streaming\",\n    \"Smart Forwarding \u0026 Replay Workflows\",\n    \"Isomorphic Custom Scripting \u0026 Latency Simulation\",\n    \"Provider Signature Verification \u0026 Enterprise Security\",\n    \"Large Payload Handling \u0026 Operational Health\"\n  ],\n  \"endpoints\": {\n    \"logs\": \"https://\u003crun-id\u003e.runs.apify.net/logs?limit=100\",\n    \"logDetail\": \"https://\u003crun-id\u003e.runs.apify.net/logs/:logId\",\n    \"logPayload\": \"https://\u003crun-id\u003e.runs.apify.net/logs/:logId/payload\",\n    \"stream\": \"https://\u003crun-id\u003e.runs.apify.net/log-stream\",\n    \"webhook\": \"https://\u003crun-id\u003e.runs.apify.net/webhook/:id\",\n    \"replay\": \"https://\u003crun-id\u003e.runs.apify.net/replay/:webhookId/:itemId?url=http://your-goal.com\",\n    \"info\": \"https://\u003crun-id\u003e.runs.apify.net/info\",\n    \"systemMetrics\": \"https://\u003crun-id\u003e.runs.apify.net/system/metrics\",\n    \"health\": \"https://\u003crun-id\u003e.runs.apify.net/health\",\n    \"ready\": \"https://\u003crun-id\u003e.runs.apify.net/ready\"\n  },\n  \"docs\": \"https://apify.com/ar27111994/webhook-debugger-logger\"\n}\n```\n\n### 3. Send a test webhook\n\n```bash\ncurl -X POST \"https://\u003crun-id\u003e.runs.apify.net/webhook/wh_demo123\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"event\":\"payment.success\",\"provider\":\"stripe\",\"amount\":9999}'\n```\n\n### 4. Inspect the captured event\n\n```json\n{\n  \"count\": 1,\n  \"items\": [\n    {\n      \"id\": \"evt_demo123\",\n      \"timestamp\": \"2026-04-02T10:25:02.319Z\",\n      \"webhookId\": \"wh_demo123\",\n      \"requestId\": \"req_demo123\",\n      \"method\": \"POST\",\n      \"statusCode\": 200,\n      \"contentType\": \"application/json\",\n      \"processingTime\": 10,\n      \"size\": 61,\n      \"remoteIp\": \"203.0.113.10\",\n      \"requestUrl\": \"/webhook/wh_demo123\",\n      \"body\": {\n        \"event\": \"payment.success\",\n        \"provider\": \"stripe\",\n        \"amount\": 9999\n      }\n    }\n  ]\n}\n```\n\n`processingTime` is the server-side processing cost only. It does **not** include any configured `responseDelayMs` latency simulation.\n\n![Dataset view showing captured webhook events with metadata and payload fields](https://raw.githubusercontent.com/ar27111994/webhook-debugger-logger/main/assets/dataset_view.png)\n\n## Advanced configuration examples\n\n### Secure an endpoint and verify a Stripe signature\n\n```json\n{\n  \"urlCount\": 1,\n  \"retentionHours\": 72,\n  \"authKey\": \"demo-shared-secret\",\n  \"allowedIps\": [\"203.0.113.10/32\"],\n  \"signatureVerification\": {\n    \"provider\": \"stripe\",\n    \"secret\": \"whsec_demo\",\n    \"tolerance\": 300\n  }\n}\n```\n\n### Forward captured traffic to another system\n\n```json\n{\n  \"urlCount\": 2,\n  \"forwardUrl\": \"https://example.com/ingest\",\n  \"forwardHeaders\": true,\n  \"maxForwardRetries\": 3,\n  \"alertOn\": [\"error\", \"5xx\", \"signature_invalid\"]\n}\n```\n\n### Mock a slow callback with a custom response\n\n```json\n{\n  \"defaultResponseCode\": 202,\n  \"defaultResponseBody\": \"{\\\"received\\\":true,\\\"queued\\\":true}\",\n  \"defaultResponseHeaders\": {\n    \"Content-Type\": \"application/json\",\n    \"X-Debug-Source\": \"webhook-debugger\"\n  },\n  \"responseDelayMs\": 1500\n}\n```\n\n### Send alerts to Slack or Discord\n\n```json\n{\n  \"alerts\": {\n    \"slack\": {\n      \"webhookUrl\": \"https://hooks.slack.com/services/T000/B000/XXXX\"\n    },\n    \"discord\": {\n      \"webhookUrl\": \"https://discord.com/api/webhooks/...\"\n    }\n  },\n  \"alertOn\": [\"error\", \"4xx\", \"5xx\", \"timeout\", \"signature_invalid\"]\n}\n```\n\n### Transform payloads with custom scripting\n\n```json\n{\n  \"customScript\": \"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' }; }\"\n}\n```\n\nThe script runs in a disposable worker isolate and receives `{ event, req, console, HTTP_STATUS }`.\nIt can normalize, enrich, or redact payload data before the event is stored, but it does not get direct access to `process`, `require`, filesystem, or network primitives. String-based code generation such as `eval()` and `Function()` is disabled, and the runtime enforces bounded timeout and memory limits. If a script fails or times out, the error is logged and the webhook still completes through the normal response path.\n\n## API surface\n\nThe actor exposes a small but practical HTTP surface.\n\n`/health` and `/ready` are intentionally rate-limited but not protected by `authKey`, so orchestrators and load balancers can probe them even when management routes require authentication.\nDuring intentional shutdown, the HTTP listener is drained before `SyncService` and DuckDB teardown begin, so new probe traffic does not race a partially shutting-down read model.\n\n| Endpoint                          | Purpose                                           |\n| --------------------------------- | ------------------------------------------------- |\n| `GET /`                           | Lightweight dashboard page                        |\n| `GET /info`                       | Runtime info, active webhooks, endpoint discovery |\n| `ANY /webhook/:id`                | Capture incoming webhook traffic                  |\n| `GET /logs`                       | Query captured events                             |\n| `GET /logs/:logId`                | Fetch one log entry                               |\n| `GET /logs/:logId/payload`        | Retrieve the stored payload for an event          |\n| `GET /log-stream`                 | SSE live feed of captured events                  |\n| `POST /replay/:webhookId/:itemId` | Replay a captured event to a target URL           |\n| `GET /system/metrics`             | Sync and operational metrics                      |\n| `GET /health`                     | Liveness probe                                    |\n| `GET /ready`                      | Readiness probe                                   |\n\nFor the full contract, see [docs/api-reference.md](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/api-reference.md) and the machine-readable schema in [.actor/web_server_schema.json](https://github.com/ar27111994/webhook-debugger-logger/blob/main/.actor/web_server_schema.json).\n\n### Live stream preview\n\n![SSE stream output showing heartbeat events and real-time webhook captures](https://raw.githubusercontent.com/ar27111994/webhook-debugger-logger/main/assets/sse_stream.png)\n\n## Platform and MCP workflows\n\nThis project is built as an Apify Actor first, not as a standalone one-off webhook bin.\n\n### Apify platform integrations\n\n- Run it from the Apify Console or API and get public `runs.apify.net` webhook URLs immediately.\n- Persist captured events to the Apify Dataset for export, filtering, or downstream automation.\n- Persist active webhook state and large-payload offloads in the Apify Key-Value Store.\n- Reuse runs in saved tasks, schedules, and other Apify automation flows.\n- Expose the web server surface through `.actor/web_server_schema.json`, which makes the HTTP contract discoverable and easier to automate.\n- When you keep the actor warm with Apify Standby mode, the HTTP endpoints stay ready for webhook-style traffic instead of paying a cold-start penalty on each request.\n\n### MCP-enabled workflows through Apify\n\nThis actor is not itself an MCP server, but it fits cleanly into MCP-enabled automation built around Apify.\n\n- MCP clients can trigger or inspect Apify Actors, runs, datasets, and KVS records through Apify tooling.\n- Agent-driven workflows can use this actor as a disposable webhook target while another MCP tool verifies payloads, dashboards, or downstream effects.\n- The repo includes MCP-oriented development assets and guidance under the repo rules for using Apify and Chrome DevTools MCP during development.\n\n![MCP configuration screenshot showing how to connect Apify tooling in an MCP client](https://raw.githubusercontent.com/ar27111994/webhook-debugger-logger/main/assets/mcp_config.png)\n\nIn practice, that means AI-assisted integration tests can create a run, post webhook traffic, inspect `/info` or `/logs`, and then continue through the rest of an Apify or browser automation workflow.\n\n## Operational behavior\n\n### Hot-reload input configuration\n\nThe runtime can apply input changes without a full restart.\n\n- On Apify, `HotReloadManager` polls the Key-Value Store for updated actor input.\n- In local development, it watches the generated `storage/key_value_stores/default/INPUT.json` file with `fs.watch`.\n- Reloadable settings flow through `AppState.applyConfigUpdate()`, which updates rate limiters, auth, retention, replay settings, forwarding settings, and parser limits in place.\n- Set `DISABLE_HOT_RELOAD=true` if you want a fixed configuration for reproducible local runs.\n\nThis is useful when you want to tune forwarding, replay, auth, or limits while the actor is already receiving traffic.\n\n### Rate limiting\n\nThe actor protects both ingress and management endpoints.\n\n- `rateLimitPerMinute` controls the main API and management route limiter.\n- Webhook ingestion also applies a dedicated per-webhook limiter tuned for higher event throughput.\n- When limits are exceeded, the runtime returns standard HTTP throttling responses and emits rate-limit metadata in the normal request path.\n\nUse tighter limits for public debugging endpoints and looser limits for high-throughput provider tests.\n\n### Retries and timeouts\n\nRetry and timeout behavior exists in several places and serves different goals.\n\n| Setting             | What it controls                                | Default behavior                                                                       |\n| ------------------- | ----------------------------------------------- | -------------------------------------------------------------------------------------- |\n| `maxForwardRetries` | Retries for outbound forwarding to `forwardUrl` | Retries transient delivery failures with backoff and circuit breaker protection        |\n| `replayMaxRetries`  | Retries for replay requests                     | Retries replay delivery attempts before marking them failed                            |\n| `replayTimeoutMs`   | Per-attempt replay timeout                      | Bounds replay requests so a dead downstream does not hang the actor                    |\n| `responseDelayMs`   | Artificial response delay after processing      | Simulates slow callbacks for client timeout testing without inflating `processingTime` |\n\nIn addition to input-level settings, the runtime has internal bounded timeouts for alert delivery, background tasks, custom script execution, shutdown, DNS resolution, and outbound forwarding.\n\nIf you need the detailed implementation model behind these controls, see [docs/architecture.md](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/architecture.md).\n\n## Alert notifications\n\nWhen debugging webhook pipelines, passive logs are often not enough. The actor can push notifications to Slack and Discord so failures surface immediately.\n\n- Slack incoming webhook notifications\n- Discord webhook notifications\n- Trigger conditions for `error`, `4xx`, `5xx`, `timeout`, and `signature_invalid`\n- Works well with forwarding and replay workflows when you need to know that downstream delivery broke\n\nThis is especially useful when the actor is running on Apify in standby mode or as a long-lived debugging endpoint.\n\n## Custom scripting\n\nThe `customScript` input gives you an inline JavaScript hook for event transformation before storage.\n\nScripts execute inside a throwaway worker thread that hosts an isolated `vm` context. Only the mutable `event` object, a safe copy of `req`, `console`, and `HTTP_STATUS` are injected into that context.\n\nUse it to:\n\n- normalize payload shapes from different providers\n- parse JSON bodies and inject debug metadata\n- strip or remap fields before persisting\n- mark events for downstream routing or replay decisions\n\nBecause the script receives both `event` and `req`, you can combine payload, header, and query information when preparing the stored record.\n\nGuardrails:\n\n- `req` is a copied, reduced request snapshot rather than the live Express request object.\n- `process`, `require`, filesystem, and network APIs are not exposed to the script.\n- `eval()` and `Function()` style code generation are disabled inside the isolate.\n- Timeouts and worker resource limits stop runaway scripts without blocking the main request handler.\n- Operators can raise only the worker heap ceilings via `CUSTOM_SCRIPT_WORKER_MAX_OLD_GENERATION_MB` (clamped to 16-256 MB, default 32) and `CUSTOM_SCRIPT_WORKER_MAX_YOUNG_GENERATION_MB` (clamped to 8-128 MB, default 16) when legitimate scripts need more headroom.\n- Script failures are logged, and the capture pipeline falls back to the actor's normal response flow.\n\n## Architecture at a glance\n\nThe runtime uses a CQRS-style split:\n\n- **Write model**: Apify Dataset stores captured events as the durable source of truth.\n- **Read model**: DuckDB mirrors event metadata as a disposable local query layer for fast filtering and retrieval on `/logs`.\n- **State store**: Apify Key-Value Store keeps active webhook state, large payload offloads, and other runtime state.\n\nThat design lets the actor keep ingesting even if DuckDB needs to rebuild from the Dataset.\n\nDuckDB reset coordination is restart-safe as well: new DB callers wait behind a reset gate, while already-queued serialized writes and transactions are allowed to drain before the singleton is torn down. That avoids deadlocks during test restarts and lifecycle rebuilds without weakening write serialization.\n\nFor deeper implementation detail, see [docs/architecture.md](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/architecture.md).\n\n## Self-hosting\n\n### Run directly with Node.js\n\n```bash\nnpm install\nnpm start\n```\n\nThe web server listens on `http://localhost:8080` by default.\n\n#### CLI demo screenshots\n\n![VS Code terminal showing local actor startup and generated webhook IDs](https://raw.githubusercontent.com/ar27111994/webhook-debugger-logger/main/assets/demo_cli.PNG)\n\n![CLI output showing JSON/form submissions and a forced 401 scenario](https://raw.githubusercontent.com/ar27111994/webhook-debugger-logger/main/assets/demo_cli_output.PNG)\n\n![Terminal output of SSE stream with heartbeat and live captured events](https://raw.githubusercontent.com/ar27111994/webhook-debugger-logger/main/assets/demo_cli_sse_output.PNG)\n\n### Local .env loading and override order\n\nFor local CLI and self-hosted runs, the app automatically loads a `.env` file from the current working directory.\n\n- Existing process environment variables win over `.env` values.\n- `.env` loading is skipped during Jest runs so tests stay deterministic.\n- The main entrypoint imports the loader explicitly, and the shared env helper also imports it so env-backed constants still resolve correctly in modules that are evaluated outside `src/main.js`.\n\nUse [.env.example](https://github.com/ar27111994/webhook-debugger-logger/blob/main/.env.example) as the starting point for local configuration.\n\nTypical local overrides:\n\n```dotenv\nACTOR_WEB_SERVER_PORT=8080\nLOG_LEVEL=debug\nINPUT={\"urlCount\":1,\"retentionHours\":24,\"authKey\":\"local-dev-key\"}\n```\n\nUseful environment variables:\n\n| Variable                                 | Purpose                                                                                                                                                   |\n| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `ACTOR_WEB_SERVER_PORT`                  | Local HTTP port override                                                                                                                                  |\n| `INPUT`                                  | Full actor input JSON for local or container boot                                                                                                         |\n| `AUTH_KEY`                               | Used by [demo_cli.js](https://github.com/ar27111994/webhook-debugger-logger/blob/main/demo_cli.js) when calling protected endpoints                       |\n| `DEMO_TARGET`                            | Used by [demo_cli.js](https://github.com/ar27111994/webhook-debugger-logger/blob/main/demo_cli.js) to select a local target (`localhost`, `ipv4`, `ipv6`) |\n| `APIFY_LOCAL_STORAGE_DIR`                | Local storage location for state, datasets, and offloaded payloads                                                                                        |\n| `DUCKDB_STORAGE_DIR` / `DUCKDB_FILENAME` | Override DuckDB storage location and file name                                                                                                            |\n\n### Run with Docker\n\n```bash\ndocker build -t webhook-debugger-logger .\n\ndocker run --rm -p 8080:8080 \\\n  -e ACTOR_WEB_SERVER_PORT=8080 \\\n  -e APIFY_LOCAL_STORAGE_DIR=/app/storage \\\n  webhook-debugger-logger\n```\n\nThere is also a dedicated standalone image target in [Dockerfile](https://github.com/ar27111994/webhook-debugger-logger/blob/main/Dockerfile) via `--target runtime-standalone`. For a fuller local validation flow, including SSE verification, see [docs/local_docker_testing.md](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/local_docker_testing.md).\n\n## Pricing\n\nThis actor is configured for Apify pay-per-event pricing.\n\nAt the time of writing, the Apify Store listing advertises:\n\n- **$10 / 1,000 captured webhooks**\n\nExamples:\n\n- 100 captured webhooks: about **$1**\n- 1,000 captured webhooks: about **$10**\n- 10,000 captured webhooks: about **$100**\n\n\u003e [!NOTE]\n\u003e Always check the live [Apify Store listing](https://apify.com/ar27111994/webhook-debugger-logger) for the current price before running large test campaigns.\n\n## Support the project\n\nIf Webhook Debugger, Logger \u0026 API Mocking Suite saves you time, helps you debug a painful integration, or gives your team a better self-hosted workflow, you can help support its development.\n\n### Sponsor / support\n\n[![Patreon](https://img.shields.io/badge/Support-Patreon-FF424D?logo=patreon\u0026logoColor=white)](https://www.patreon.com/cw/ar27111994)\n[![Ko-fi](https://img.shields.io/badge/Support-Ko--fi-29ABE0?logo=kofi\u0026logoColor=white)](https://ko-fi.com/ar27111994)\n[![Liberapay](https://img.shields.io/badge/Support-Liberapay-F6C915?logo=liberapay\u0026logoColor=black)](https://liberapay.com/ar27111994)\n[![Buy Me a Coffee](https://img.shields.io/badge/Support-Buy%20Me%20a%20Coffee-FFDD00?logo=buymeacoffee\u0026logoColor=000000)](https://buymeacoffee.com/ar27111994)\n[![thanks.dev](https://img.shields.io/badge/Support-thanks.dev-181717?logo=github\u0026logoColor=white)](https://thanks.dev/d/gh/ar27111994)\n\n### Need hands-on help?\n\nIf you want help debugging or stabilizing a webhook integration, I also offer direct implementation support for setups such as:\n\n- Stripe webhooks\n- GitHub webhooks\n- Shopify webhooks\n- Slack events and callback flows\n- self-hosted Docker deployments\n- signature verification and replay workflows\n\nIf that would help, open an issue or reach out through one of the support links above and mention your use case.\n\n### Why support it?\n\nSupport helps fund:\n\n- maintenance and bug fixes\n- new provider integrations\n- better deployment and self-hosting guides\n- premium webhook recipes and debugging playbooks\n- faster iteration based on real user feedback\n\n## Typical use cases\n\n- Inspect webhook payloads from Stripe, Shopify, GitHub, Slack, or custom services.\n- Validate that your application handles success, delay, 4xx, and 5xx callback scenarios.\n- Replay captured payloads against staging after fixing a bug.\n- Forward test traffic into another service while still keeping a full audit trail.\n- Run temporary or self-hosted debug endpoints for QA, integration, or support teams.\n\n## Playbooks\n\nThe repo includes focused operational guides for common debugging and rollout scenarios:\n\n- [Zapier, Make, and n8n bridge](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/playbooks/low-code-bridge.md)\n- [GitHub App and CI webhook debugging](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/playbooks/github-ci.md)\n- [Incident response and replay recovery](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/playbooks/incident-response.md)\n- [Large payload and binary forensics](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/playbooks/large-payload-forensics.md)\n- [PII-safe production capture](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/playbooks/pii-safe-production-capture.md)\n- [Custom HMAC partner integrations](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/playbooks/custom-hmac-partner.md)\n- [Callback sandbox prototyping](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/playbooks/callback-sandbox.md)\n- [Canary validation and shadow replay](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/playbooks/canary-shadow-rollout.md)\n\n## Frequently asked questions\n\n### How long do generated webhook URLs stay active?\n\nSet `retentionHours` anywhere from 1 to 168 hours. Expired webhooks immediately stop accepting traffic. Their logs are purged from the `/logs` query endpoint during the next cleanup cycle (roughly every 10 minutes). Reducing `retentionHours` via hot-reload only affects newly generated webhooks — pre-existing webhooks keep their original, longer expiry window. Events already written to the Apify Dataset are retained independently of this setting.\n\n### Can I secure my webhook endpoints?\n\nYes. You can combine `authKey`, `allowedIps`, signature verification, and masked header logging.\n\n### Does it support replaying captured traffic?\n\nYes. Use the replay endpoint to send a stored event to another target URL.\n\n### Can I use it as a mock callback server?\n\nYes. You can return custom status codes, bodies, headers, and artificial latency to simulate downstream behavior.\n\n### Where are logs stored?\n\nCaptured events are written to the Apify Dataset as the durable source of truth. DuckDB keeps a disposable read model for fast log queries, and the Apify Key-Value Store holds active webhook state plus large payload offloads.\n\n### What happens with large payloads?\n\nThe actor enforces `maxPayloadSize` and rejects requests that exceed the configured hard limit. For large payloads that are still within the accepted range, the runtime can offload the payload content to the Apify Key-Value Store so the event remains queryable without forcing every large body through the in-memory read model.\n\n### Can I run it outside Apify?\n\nYes. You can run it locally with Node.js or Docker, or deploy the container into your own environment.\n\n## Documentation and related resources\n\n- [API reference](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/api-reference.md)\n- [Architecture overview](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/architecture.md)\n- [Local Docker testing guide](https://github.com/ar27111994/webhook-debugger-logger/blob/main/docs/local_docker_testing.md)\n- [Manual demo guide](https://github.com/ar27111994/webhook-debugger-logger/blob/main/MANUAL_DEMO_GUIDE.md)\n- [Publication guide](https://github.com/ar27111994/webhook-debugger-logger/blob/main/PUBLICATION_GUIDE.md)\n- [Security policy](https://github.com/ar27111994/webhook-debugger-logger/blob/main/SECURITY.md)\n\nIf you are looking for implementation and marketing guidance used during development, see the materials under [docs/marketing](https://github.com/ar27111994/webhook-debugger-logger/tree/main/docs/marketing).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Far27111994%2Fwebhook-debugger-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Far27111994%2Fwebhook-debugger-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Far27111994%2Fwebhook-debugger-logger/lists"}