Public Webhook Testing & Request Inspection Service
Hooklyn is a production-ready, zero-authentication webhook testing tool. Create temporary HTTP endpoints, capture every incoming request, and inspect method, headers, query parameters, cookies, body (JSON, form-data, text, XML, raw), client IP, timestamps, and size — all in a polished real-time web UI.
Created by Blitz · GitHub/social: blitzlabx
- Temporary webhook endpoints — one-click generation of unique 8-character IDs
- Full request capture — GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS and any other method
- Rich inspection — headers, query string, cookies, body, content-type, client IP (proxy-aware), user-agent, size, timestamps
- Body support — JSON (with parsed view),
application/x-www-form-urlencoded, plain text, XML, and binary (base64) - Real-time updates — Server-Sent Events (SSE) push new requests to the browser instantly
- Request history — per-bin history with configurable max size (default 100)
- Copy webhook URL and copy as curl
- Request replay — resend a captured request to any target HTTP/HTTPS URL
- Automatic expiration — inactive bins expire after configurable TTL (default 24 hours)
- Rate limiting, request size limits, CORS, structured JSON API responses
- Health endpoints —
GET /pingandGET /healthfor UptimeRobot and load balancers - Dockerized and ready for Render deployment
- No authentication — public by design for testing
┌─────────────┐ HTTP/SSE ┌──────────────────────────────┐
│ Browser UI │ ◄───────────────► │ Shelf server (Dart) │
└─────────────┘ │ ├── Static (public/) │
│ ├── /api/* (REST + SSE) │
┌─────────────┐ any method │ ├── /{binId} (capture) │
│ curl / app │ ───────────────► │ ├── /ping, /health │
└─────────────┘ │ └── BinStore (in-memory) │
└──────────────────────────────┘
- Runtime: Dart 3.13+, Shelf + shelf_router + shelf_static
- Storage: In-memory
BinStorewith periodic cleanup (no external DB required) - Frontend: Vanilla JS + modern CSS (IBM Plex), no framework lock-in
- Real-time: SSE per bin (
/api/bins/:id/stream)
- Dart SDK ^3.13.3
git clone https://github.com/blitzlabx/hooklyn.git
cd hooklyn
dart pub get
dart run bin/server.dartServer listens on http://0.0.0.0:8080 (or $PORT).
Open the UI, click Create Webhook Endpoint, then send requests:
curl -X POST http://localhost:8080/<bin-id> \
-H 'Content-Type: application/json' \
-d '{"event":"payment.succeeded","amount":1999}'All API responses are JSON with the shape:
{
"success": true,
"data": { ... }
}Errors:
{
"success": false,
"error": { "message": "..." }
}POST /api/bins
Content-Type: application/json
{
"ttlHours": 24,
"maxRequests": 100
}Optional body. ttlHours clamped 1–168, maxRequests 10–500.
Response 201:
{
"success": true,
"data": {
"id": "a1b2c3d4",
"webhookUrl": "https://host/a1b2c3d4",
"inspectUrl": "https://host/inspect/a1b2c3d4",
"createdAt": "...",
"expiresAt": "...",
...
}
}GET /api/bins/:id?limit=50GET /api/bins/:id/requests?limit=100GET /api/bins/:id/requests/:requestIdDELETE /api/bins/:idGET /api/bins/:id/streamEvents: request with JSON payload of the captured request. Heartbeats every ~25s.
POST /api/bins/:id/requests/:requestId/replay
Content-Type: application/json
{ "targetUrl": "https://example.com/webhook" }GET /api/bins/:id/requests/:requestId/curlGET /api/statsGET /ping → text/plain "pong"
GET /health → JSON status + store stats# JSON
curl -X POST https://your-host/<bin-id> \
-H 'Content-Type: application/json' \
-d '{"hello":"hooklyn"}'
# Form
curl -X POST https://your-host/<bin-id> \
-d 'name=Blitz&project=Hooklyn'
# Custom headers + path
curl -X PUT https://your-host/<bin-id>/orders/42 \
-H 'X-Signature: abc' \
-H 'Content-Type: application/xml' \
-d '<order id="42"/>'import 'package:http/http.dart' as http;
final res = await http.post(
Uri.parse('https://your-host/<bin-id>'),
headers: {'Content-Type': 'application/json'},
body: '{"from":"dart"}',
);
print(res.body);docker build -t hooklyn .
docker run --rm -p 8080:8080 \
-e PORT=8080 \
-e PUBLIC_BASE_URL=http://localhost:8080 \
hooklynThe image uses multi-stage build (AOT compile) and ships the public/ static assets.
- Push this repository to GitHub (
blitzlabx/hooklynor your fork). - In Render: New → Web Service → Connect repo.
- Runtime: Docker (or use the included
render.yaml). - Set environment variables as needed (see below).
- Health check path:
/health. - After deploy, optionally set
PUBLIC_BASE_URLtohttps://<your-service>.onrender.comso generated webhook URLs are absolute and correct behind the proxy.
render.yaml is provided for Blueprint-style deploys.
| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
Listen port (Render injects this) |
PUBLIC_BASE_URL |
(inferred) | Canonical public origin for webhook URLs |
BIN_TTL_HOURS |
24 |
Inactivity TTL for bins |
MAX_REQUESTS_PER_BIN |
100 |
Max stored requests per bin |
MAX_BINS |
10000 |
Soft cap on concurrent bins |
MAX_BODY_BYTES |
1048576 |
Max request body size (1 MiB) |
RATE_LIMIT_MAX |
120 |
Requests per window per IP |
RATE_LIMIT_WINDOW_SEC |
60 |
Rate-limit window in seconds |
- UptimeRobot / similar: probe
GET /ping(returns plainpong) orGET /health. - Both endpoints are lightweight and do not hit rate limits heavily; keep
/pingfor pure liveness.
- Per-IP sliding-window rate limiting (default 120 req/min).
- Request body size capped (default 1 MiB).
- CORS enabled for browser use (
*). - No authentication by design — do not put secrets in webhook payloads you send to a public instance.
- In-memory storage: data is lost on restart; bins expire automatically.
- Replay feature sends the captured request to a user-supplied URL — use only with trusted targets.
- Suitable for development and integration testing, not for production webhook reception of sensitive data without additional controls.
- Storage is in-memory only (no Redis/Postgres). Horizontal scaling will not share bins across instances.
- Free Render instances spin down when idle; cold start may take a few seconds.
- Binary bodies are stored base64-encoded and count toward size limits.
- Maximum concurrent bins and requests per bin are configurable but finite to protect memory.
dart pub get
dart run bin/server.dart # run
dart test # tests
dart analyze # static analysis
dart format . # formatFormatting and recommended lints are configured via analysis_options.yaml (package:lints/recommended.yaml).
bin/server.dart # entrypoint
lib/
handlers/ # API, webhook, health
middleware/ # CORS, rate limit, size limit
models/ # Bin, CapturedRequest
services/ # BinStore, RateLimiter
utils/
public/ # UI (index.html, styles.css, app.js)
test/
Dockerfile
render.yaml
Issues and pull requests are welcome at github.com/blitzlabx/hooklyn.
- Fork and create a feature branch.
- Keep changes focused; add tests where practical.
- Run
dart analyzeanddart testbefore opening a PR.
Hooklyn is created and maintained by Blitz (blitzlabx).
All project credit goes to Blitz.
MIT License — free to use, modify, and distribute.