A webhook bin service built with CloudFlare Workers, Hono framework and CloudFlare Durable Objects. Capture, inspect and debug HTTP webhooks with ease.
The EchoHook API is live at: https://echohook.dev
- API Development: Test webhooks during development
- Third-party Integration: Debug webhooks from services like GitHub, Stripe, PayPal
- API Monitoring: Monitor webhook delivery and payloads
- Development Testing: Create temporary endpoints for testing
- Webhook Inspection: Analyze webhook structure and content
- β Token Authentication: Secure API access with Bearer tokens
- β Webhook Capture: Capture any HTTP method and payload
- β Request Inspection: View headers, body, query parameters and metadata
- β Bin Management: Create, update and delete webhook bins
- β Structured Logging: JSON-formatted logs for monitoring and debugging
- β TypeScript: Fully typed with modern TypeScript
- β CloudFlare Durable Objects: Serverless stateful storage with strong consistency
- β Hono Framework: Fast and lightweight web framework
- β Real-time: Instant webhook capture and viewing
- β CORS: Cross-Origin Resource Sharing enabled
All API endpoints (except root / and token creation) require authentication using Bearer tokens.
- Create an API Token:
curl -X POST https://echohook.dev/api/auth/token \ -H "Content-Type: application/json" \ -d '{"name": "My Token", "description": "Token for webhook testing"}'
- Use the token in all requests:
curl -H "Authorization: Bearer YOUR_TOKEN" https://echohook.dev/api/binsnpm run dev
curl -X POST https://echohook.dev/api/auth/token \ -H "Content-Type: application/json" \ -d '{"name": "My API Token", "description": "For testing"}'
Response:
{
"success": true,
"data": {
"id": "token-uuid",
"token": "your-64-char-token",
"name": "My API Token",
"description": "For testing",
"created_at": "2025εΉ΄06ζ10ζ₯T12:00:00.000Z",
"is_active": true
}
}# Set your token TOKEN="your-64-char-token" # List webhook bins curl -H "Authorization: Bearer $TOKEN" \ https://echohook.dev/api/bins # Create a webhook bin curl -X POST https://echohook.dev/api/bins \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "My Webhook Bin", "description": "Test bin"}' # Capture a webhook curl -X POST https://echohook.dev/api/webhook/your-bin-id \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"message": "Hello webhook!"}'
GET /- Landing page with documentation (no auth required)GET /api- API health check (no auth required)
POST /api/auth/token- Create new API token (no auth required)DELETE /api/auth/tokens/:tokenId- Delete an API token
GET /api/bins- List all webhook binsGET /api/bins/:binId- Get single bin detailsPOST /api/bins- Create new webhook binPUT /api/bins/:binId- Update bin detailsDELETE /api/bins/:binId- Delete bin and all its captured requests
GET /api/bins/:binId/requests- Get all captured requests for a binPOST /api/webhook/:binId- Capture webhook (accepts any HTTP method)
{
"name": "My API Token",
"description": "Optional description",
"expiresIn": "365"
}{
"name": "My Webhook Bin",
"description": "Optional description"
}{
"success": true,
"data": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "My Webhook Bin",
"description": "Optional description",
"created_at": "2024εΉ΄06ζ01ζ₯T12:00:00.000Z",
"updated_at": "2024εΉ΄06ζ01ζ₯T12:00:00.000Z",
"request_count": 5,
"last_request_at": "2024εΉ΄06ζ01ζ₯T12:30:00.000Z"
}
}{
"success": true,
"data": [
{
"id": "req-123e4567-e89b-12d3-a456-426614174000",
"bin_id": "123e4567-e89b-12d3-a456-426614174000",
"method": "POST",
"url": "https://echohook.dev/webhook/123e4567-e89b-12d3-a456-426614174000",
"headers": {
"content-type": "application/json",
"user-agent": "GitHub-Hookshot/abc123"
},
"body": "{\"action\":\"push\",\"repository\":{\"name\":\"my-repo\"}}",
"query_params": {
"source": "github"
},
"ip_address": "192.168.1.1",
"user_agent": "GitHub-Hookshot/abc123",
"content_type": "application/json",
"content_length": 45,
"received_at": "2024εΉ΄06ζ01ζ₯T12:30:00.000Z"
}
]
}pnpm install
pnpm run dev
This starts the development server at http://localhost:8787
The landing page HTML is managed in index.html. To sync changes to the worker:
npm run sync-html
This copies the content from index.html to src/html.ts for deployment.
pnpm run build # Syncs HTML and deploys # or pnpm run deploy # Deploys without syncing
Note: Durable Objects automatically handle storage without requiring database setup or migrations.
curl -X POST https://echohook.dev/api/bins \ -H "Content-Type: application/json" \ -d '{"name": "GitHub Webhooks", "description": "Capture GitHub webhook events"}'
# Any HTTP method is supported curl -X POST https://echohook.dev/api/webhook/YOUR_BIN_ID \ -H "Content-Type: application/json" \ -H "X-GitHub-Event: push" \ -d '{"action": "push", "repository": {"name": "my-repo"}}'
curl https://echohook.dev/api/bins/YOUR_BIN_ID/requests
curl https://echohook.dev/api/bins
curl https://echohook.dev/api/bins/YOUR_BIN_ID
curl -X PUT https://echohook.dev/api/bins/YOUR_BIN_ID \ -H "Content-Type: application/json" \ -d '{"name": "Updated Bin Name", "description": "New description"}'
curl -X DELETE https://echohook.dev/api/bins/YOUR_BIN_ID