cleaniquecoders / laravel-config-webhook
Define, sign, dispatch and log outgoing webhooks in Laravel with retries, HMAC signatures, and an optional Livewire + Flux admin UI.
Package info
github.com/cleaniquecoders/laravel-config-webhook
pkg:composer/cleaniquecoders/laravel-config-webhook
Fund package maintenance!
Requires
- php: ^8.3
- illuminate/contracts: ^12.0||^13.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- livewire/livewire: ^3.0||^4.0
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.0.0||^11.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- spatie/laravel-ray: ^1.35
Suggests
- livewire/flux: Required to render the bundled Flux admin UI
- livewire/livewire: Required for the optional admin UI component (^3.0||^4.0)
README
Define, sign, dispatch and log outgoing webhooks in any Laravel app. Subscribers register a URL, a secret, and the event types they care about; when one of those events fires, the package delivers an HMAC-signed JSON payload with automatic retries and exponential backoff, and records every attempt in a delivery log. Ships with an optional Livewire + Flux admin UI.
The package is completely app-agnostic β it knows nothing about your domain. You register your own event catalogue (via config or at runtime) and either dispatch payloads manually or map your domain events to webhook types.
Features
- π Outgoing webhooks β per-subscriber URL, secret, subscribed events, custom headers
- π HMAC-SHA256 signatures β every request is signed; helpers to verify incoming ones too
- π Retries with exponential backoff β configurable base/multiplier, full delivery log
- π§Ύ Delivery logs β status, HTTP code, response time, attempt, error, response body
- π§© Config- or runtime-driven event catalogue β no hardcoded domain events
- π₯οΈ Optional Livewire + Flux admin UI β works headless without it
- π Secrets encrypted at rest, configurable authorization gate, configurable user model
- β Laravel 12 & 13, PHP 8.3+
Requirements
- PHP 8.3+
- Laravel 12 or 13
- (Optional, for the admin UI)
livewire/livewire^3 || ^4 andlivewire/flux
Installation
composer require cleaniquecoders/laravel-config-webhook
The service provider and ConfigWebhook facade are auto-discovered β no manual
registration needed.
Publish and run the migrations:
php artisan vendor:publish --tag="laravel-config-webhook-migrations"
php artisan migrate
Publish the config:
php artisan vendor:publish --tag="laravel-config-webhook-config"
Optionally publish the views (to customise the Flux UI):
php artisan vendor:publish --tag="laravel-config-webhook-views"
The optional admin UI requires
livewire/livewireandlivewire/flux. The service, job, and signing all work without them.
Configuration
Register the event types your app can emit, either in config/config-webhook.php:
'events' => [ 'order.created' => 'Order Created', 'order.cancelled' => 'Order Cancelled', 'user.registered' => 'User Registered', ],
β¦or at runtime (e.g. in a service provider's boot()):
use CleaniqueCoders\ConfigWebhook\Facades\ConfigWebhook; ConfigWebhook::registerEvents([ 'order.created' => 'Order Created', 'user.registered' => 'User Registered', ]);
Usage
1. Dispatch a payload manually
Fan a payload out to every active webhook subscribed to the event type:
use CleaniqueCoders\ConfigWebhook\Facades\ConfigWebhook; ConfigWebhook::send('order.created', [ 'id' => $order->id, 'total' => $order->total, ]);
The receiver gets:
// POST https://subscriber.example.com/hook // Headers: X-Webhook-Signature, X-Webhook-Event, X-Webhook-Delivery { "event": "order.created", "timestamp": "2026-06-08T12:00:00+00:00", "data": { "id": 123, "total": 49.90 } }
2. Map a domain event (auto-dispatch)
Wire a domain event to a webhook type once and the package dispatches automatically whenever the event fires:
use App\Events\OrderCreated; use CleaniqueCoders\ConfigWebhook\Facades\ConfigWebhook; ConfigWebhook::listen( OrderCreated::class, 'order.created', fn (OrderCreated $event) => [ 'id' => $event->order->id, 'total' => $event->order->total, ], );
3. Verifying signatures on the receiving side
use CleaniqueCoders\ConfigWebhook\Support\WebhookSignature; $valid = WebhookSignature::verify( payload: $request->getContent(), signature: $request->header('X-Webhook-Signature'), secret: $sharedSecret, );
Admin UI
Enable the bundled full-page route in config/config-webhook.php:
'route' => [ 'enabled' => true, 'prefix' => 'admin/webhooks', 'name' => 'config-webhook.index', 'middleware' => ['web', 'auth'], ],
Or drop the Livewire component anywhere in your own layout:
<livewire:config-webhook::webhooks />
Restrict access with a gate:
'gate' => 'manage-webhooks', // ability string, or a fn ($user) => bool
Pruning logs
php artisan config-webhook:prune --days=30
How it works
| Concern | Class |
|---|---|
| Manager (facade root) | ConfigWebhook β registerEvent(s), listen, send, dispatchFromEvent |
| Models | Models\Webhook, Models\WebhookDeliveryLog (package Concerns\HasUuid) |
| Status | Enums\DeliveryStatus β PENDING, SUCCESS, FAILED, RETRYING |
| Delivery | Jobs\SendWebhookEvent (queued, retry + backoff) |
| Signing | Support\WebhookSignature β generate / verify |
| Events | Events\WebhookDelivered, Events\WebhookFailed |
| CLI | Commands\PruneWebhookDeliveryLogsCommand |
| UI | Livewire\Webhooks + resources/views/livewire/webhooks.blade.php (Flux, optional) |
Testing
composer test
The suite includes a true end-to-end test (tests/EndToEndTest.php) that mirrors how a
consuming app uses the package: a domain event is mapped with ConfigWebhook::listen(), a
subscriber webhook is created, the event is fired, and the queued job runs on the sync
queue to deliver a signed HTTP request β asserting both the outgoing request and the
recorded delivery log.
Local development (try it in a real app)
The package ships an Orchestra Testbench Workbench
setup (testbench.yaml + workbench/) so you can boot a real Laravel app around it:
composer install vendor/bin/testbench workbench:build # creates the sqlite db + runs migrations vendor/bin/testbench serve # http://127.0.0.1:8000
GET /webhooksβ the bundled Livewire admin UI (needslivewire/fluxinstalled to render)GET /fireβ dispatches the sampleOrderShippeddomain event through the full pipeline
workbench/app/Providers/WorkbenchServiceProvider.php shows exactly how a host app registers
its event catalogue and maps a domain event to a webhook type.
Changelog
Please see CHANGELOG for more information on what has changed recently.
Credits
This package was extracted and generalised from the G8Stack webhook integrations feature.
License
The MIT License (MIT). Please see License File for more information.