A free, self-hosted webhook testing tool. Inspect, debug, and forward HTTP requests in real time.
Similar to Webhook.site and RequestBin, but open-source and self-hostable with zero external dependencies.
- 🔗 Webhook URL management — create unique endpoints with UUIDs or custom slugs
- 📨 Capture all HTTP methods — POST, GET, PUT, PATCH, DELETE, and more
- 👀 Real-time updates — see requests as they arrive via WebSockets (Laravel Reverb)
- 🔍 Request inspection — view headers, body, query params, and metadata
- 🔀 Webhook forwarding — forward captured requests to any target URL
- 🔔 Slack notifications — get notified in Slack for every captured request
- 📧 Email notifications — receive email alerts for captured requests
- 📤 Export — download requests as CSV or JSON
- 🏷️ Custom slugs — give your endpoint a memorable name
- ⚡ Rate limiting — configurable per-URL hourly limits
- 🗑️ Data retention — automatic cleanup of old requests
- 🔐 Authentication — email/password registration and login
- 🗄️ SQLite by default — zero external database dependency
# Generate an app key
docker run --rm php:8.4-cli php -r "echo 'base64:'.base64_encode(random_bytes(32)).PHP_EOL;"
# Pull and run the image
docker run -d \
--name viewhook \
-p 8080:8080 \
-v viewhook-data:/data \
-e APP_KEY=<your-key> \
-e APP_URL=http://localhost:8080 \
ghcr.io/paulund/viewhook:latestVisit http://localhost:8080
Port note: The container's nginx listens on port 8080 (not 80). Always map to
:8080inside the container (e.g.-p 8080:8080or-p 80:8080).
# Clone the repository
git clone https://github.com/paulund/viewhook.git
cd viewhook
# Copy environment file
cp .env.example .env
# Start with Laravel Sail (Docker)
./vendor/bin/sail up -d
# Install dependencies
./vendor/bin/sail composer install
npm install
# Generate app key and run migrations
./vendor/bin/sail artisan key:generate
./vendor/bin/sail artisan migrate
# Start the dev server
npm run devVisit http://localhost
All limits are configurable via environment variables:
| Variable | Default | Description |
|---|---|---|
VIEWHOOK_RATE_LIMIT |
100 |
Maximum requests per URL per hour |
VIEWHOOK_RETENTION_HOURS |
(empty) | Hours to keep captured requests (empty = keep forever) |
VIEWHOOK_MAX_PAYLOAD_KB |
10240 |
Maximum payload size in KB (10 MB) |
See .env.example for the full list of available environment variables.
Use the Docker image ghcr.io/paulund/viewhook:latest. Attach a persistent volume at /data for the SQLite database.
New to DigitalOcean? Get $200 in free credit using this referral link.
docker run -d \
--name viewhook \
--restart unless-stopped \
-p 8080:8080 \
-v viewhook-data:/data \
-e APP_KEY=<your-key> \
-e APP_URL=https://your-domain.com \
ghcr.io/paulund/viewhook:latest- Backend: Laravel 12 (PHP 8.4)
- Frontend: Inertia.js + React + TypeScript
- Styling: Tailwind CSS v4
- Database: SQLite (development and production self-hosting)
- Cache/Queue: Database-backed (no Redis required)
- Real-time: Laravel Reverb (WebSockets)
- Auth: Laravel Sanctum + Breeze
| Layer | Responsibility |
|---|---|
Actions (app/Actions/) |
Single-purpose business logic entry points |
DTOs (app/DataTransferObjects/) |
Immutable data containers between layers |
Services (app/Services/) |
External I/O (no DB writes) |
Jobs (app/Jobs/) |
Async work, persist via model methods |
Models (app/Models/) |
Eloquent models with domain logic |
See docs/ for detailed architecture documentation.
# All backend checks (lint + static analysis + tests with 100% coverage)
./vendor/bin/sail composer run test
# All frontend checks (eslint + prettier + typescript + vitest)
npm testContributions are welcome! Please read CONTRIBUTING.md for code style, testing requirements, and the PR process.
If Viewhook saves you time, consider sponsoring the project. Your support helps keep it maintained and free for everyone.
MIT — see LICENSE.
Built by Paul Underwood.
