PHPackages                             techrays-labs/laravel-webhooker - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Queues &amp; Workers](/categories/queues)
4. /
5. techrays-labs/laravel-webhooker

ActiveLibrary[Queues &amp; Workers](/categories/queues)

techrays-labs/laravel-webhooker
===============================

A Laravel-native Webhook Reliability Engine for outbound &amp; inbound webhook management with retry, replay, and dashboard.

1.0.0(3mo ago)91MITPHPPHP ^8.1

Since Feb 22Pushed 3mo agoCompare

[ Source](https://github.com/techrays-labs/laravel-webhooker)[ Packagist](https://packagist.org/packages/techrays-labs/laravel-webhooker)[ RSS](/packages/techrays-labs-laravel-webhooker/feed)WikiDiscussions master Synced today

READMEChangelog (3)Dependencies (24)Versions (5)Used By (0)

[![Latest Version on Packagist](https://camo.githubusercontent.com/87cde030d24a029f5bea25a88483bbbdd46b878d62e71b80b6891b979fcbcb9d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f74656368726179732d6c6162732f6c61726176656c2d776562686f6f6b6572)](https://packagist.org/packages/techrays-labs/laravel-webhooker)[![Total Downloads](https://camo.githubusercontent.com/473123d903b76fdb78929e6fffb2ff6c7e8a1b7f5f3ca1f605cbde290f7bc57d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f74656368726179732d6c6162732f6c61726176656c2d776562686f6f6b6572)](https://packagist.org/packages/techrays-labs/laravel-webhooker)[![GitHub Stars](https://camo.githubusercontent.com/c93b0033a5b725a5baa3c6dbb035e52c93bd478d6269e7498495200495d6950c/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f74656368726179732d6c6162732f6c61726176656c2d776562686f6f6b65723f7374796c653d736f6369616c)](https://github.com/techrays-labs/laravel-webhooker/stargazers)[![GitHub Forks](https://camo.githubusercontent.com/79e1495ea324d6bfb64b9cd8e9dadecc9e82bcabd7bdadb633de41edf9856e7a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f74656368726179732d6c6162732f6c61726176656c2d776562686f6f6b65723f7374796c653d736f6369616c)](https://github.com/techrays-labs/laravel-webhooker/network)[![Latest Version](https://camo.githubusercontent.com/107ee138d54dc6eb156914011b7fd1dc31fad776647464b40ff1a5a389d739b7/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f74656368726179732d6c6162732f6c61726176656c2d776562686f6f6b6572)](https://github.com/techrays-labs/laravel-webhooker/releases)[![GitHub Workflow Status](https://camo.githubusercontent.com/dd358306b1dae8a8ac9182dc42c32a5444ab99741e2fb832fefb8c4330261a09/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f74656368726179732d6c6162732f6c61726176656c2d776562686f6f6b65722f74657374732e796d6c)](https://github.com/techrays-labs/laravel-webhooker/actions)[![GitHub License](https://camo.githubusercontent.com/ee46cb6aac7c863114eaf3052e2770a4cbf2c847aaf2aacfae6f4739476ed81f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f74656368726179732d6c6162732f6c61726176656c2d776562686f6f6b6572)](https://github.com/techrays-labs/laravel-webhooker/blob/master/LICENSE)

Laravel Webhooker
=================

[](#laravel-webhooker)

A Laravel-native Webhook Reliability Engine for outbound and inbound webhook management with intelligent retry, replay, circuit breaker, and a built-in dashboard.

The Problem
-----------

[](#the-problem)

Webhooks are critical infrastructure, but building reliable webhook delivery is hard. You need retry logic, signature verification, attempt logging, failure recovery, and operational visibility. Most teams either build fragile one-off solutions or rely on external SaaS services.

**Laravel Webhooker** gives you production-grade webhook infrastructure as a Composer package. Zero external dependencies. No SaaS billing. Just install, configure, and ship.

Features
--------

[](#features)

### Core

[](#core)

- **Outbound Delivery** - Queue-based async delivery with configurable timeout
- **Inbound Handling** - Receive, verify, deduplicate, and process inbound webhooks
- **Exponential Backoff Retry** - Configurable max attempts, delay, and multiplier
- **HMAC Signatures** - Automatic signing for outbound, verification for inbound
- **Attempt Logging** - Full record of every delivery attempt with status, duration, and errors
- **Replay** - Re-dispatch any failed event via Artisan command or dashboard
- **Pruning** - Automatic retention management to prevent unbounded storage growth

### Observability

[](#observability)

- **Webhook Metrics** - Aggregated stats (success rate, response time, failure rate) via a `WebhookMetrics` service
- **Endpoint Health Status** - Computed health classification (healthy, degraded, failing, unknown) per endpoint
- **Laravel Events** - Native event dispatching at key lifecycle points for custom listeners
- **Structured Logging** - Optional dedicated log channel with structured context

### Control

[](#control)

- **Circuit Breaker** - Auto-disable failing endpoints, cooldown period, half-open recovery
- **Endpoint Tagging** - Tag/group endpoints, dispatch to all endpoints by tag
- **Enable/Disable API** - Programmatically toggle endpoints with reason tracking
- **Per-Endpoint Retry** - Override global retry settings per endpoint

### Developer UX

[](#developer-ux)

- **Testing Facade** - `Webhook::fake()` with assertion helpers for your test suite
- **Inbound Simulator** - Artisan command to simulate inbound webhook deliveries locally
- **Debug Mode** - Verbose logging of full request/response cycles in development
- **Tinker Helpers** - `inspect()`, `lastFailed()`, `retryLast()`, `stats()` on the facade

### Hardening

[](#hardening)

- **Rate Limiting** - Per-endpoint outbound rate limits using Laravel's RateLimiter
- **Payload Validation** - Schema-based validation of outbound payloads before dispatch
- **IP Allowlist** - Restrict inbound webhooks to known IP addresses (supports CIDR)
- **Secret Rotation** - Rotate endpoint secrets with a configurable grace period
- **Idempotency Keys** - Prevent duplicate outbound deliveries

### Scaling &amp; Reliability (v2.0)

[](#scaling--reliability-v20)

- **Storage Driver Abstraction** - Pluggable storage backends via Laravel's Manager pattern
- **Dead-Letter Queue** - Auto-capture events that exhaust all retries for inspection and manual retry
- **Event Batching** - Dispatch to multiple endpoints as a tracked batch with progress monitoring
- **Endpoint Health History** - Periodic health snapshots for trend analysis over time
- **Multi-Database Support** - Read/write connection separation for read replicas
- **Table Partitioning** - MySQL (RANGE) and PostgreSQL (declarative) partitioning for high-volume tables
- **Horizontal Scaling** - Distributed locking for safe multi-worker webhook processing

### Dashboard

[](#dashboard)

- **Stats Overview** - 24h event counts, success rate, average response time, endpoint health breakdown
- **Event Timeline** - Visual timeline of delivery attempts with status codes, durations, and errors
- **Bulk Actions** - Select and replay or delete multiple events at once
- **Endpoint Detail Page** - Config, health, circuit breaker state, 7-day sparkline
- **Tag Filtering** - Filter events by endpoint tag
- **Dark Mode** - CSS variable theming with `prefers-color-scheme` and manual toggle
- **Analytics Dashboard** - Comprehensive analytics with success rates, response times, and trends

### REST API (v1.0.0)

[](#rest-api-v100)

- **Full CRUD for Endpoints** - Create, read, update, delete endpoints via API
- **Event Management** - List, view, replay, retry, delete events
- **Analytics Endpoints** - Programmatic access to delivery statistics
- **Token-based Authentication** - Secure API tokens with abilities and expiration
- **Schema Validation** - Validate event payloads against registered schemas

### Event Transforms (v1.0.0)

[](#event-transforms-v100)

- **Per-Endpoint Transforms** - Modify payloads before delivery to specific endpoints
- **Include/Exclude Fields** - Filter payload fields with simple configuration
- **Rename Fields** - Remap field names for different consumers
- **Add Computed Fields** - Inject dynamic values into payloads
- **Custom Transformers** - Implement `WebhookTransformer` interface for complex transformations

### Event Filtering (v1.0.0)

[](#event-filtering-v100)

- **Pattern-based Subscriptions** - Subscribe endpoints to specific event patterns using wildcards
- **Wildcard Matching** - Support `*` and `?` wildcards (e.g., `order.*`, `user.created`)
- **Multiple Patterns** - Multiple filter patterns per endpoint

### Event Schema Registry (v1.0.0)

[](#event-schema-registry-v100)

- **Schema Definitions** - Define JSON schemas for webhook event types
- **Validation** - Validate inbound/outbound payloads against registered schemas
- **Schema API** - RESTful management of event schemas

### Real-time WebSockets (v1.0.0)

[](#real-time-websockets-v100)

- **Live Delivery Updates** - Broadcast delivery status changes in real-time
- **Channel-based Events** - Subscribe to all deliveries or endpoint-specific channels
- **Laravel Reverb/Pusher** - Works with any Laravel broadcast driver

### Plugin System (v1.0.0)

[](#plugin-system-v100)

- **Extensible Architecture** - Register custom plugins to modify webhook behavior
- **Payload Transformation** - Plugins can modify payloads before sending
- **Event Hooks** - Hook into webhook lifecycle events (sending, delivered, failed)
- **Event Filtering** - Plugins can filter which events reach endpoints
- **Priority-based Execution** - Plugins execute in priority order

Requirements
------------

[](#requirements)

- PHP 8.1+
- Laravel 10, 11, 12, or 13

Installation
------------

[](#installation)

```
composer require techrays-labs/laravel-webhooker
```

Publish the configuration file:

```
php artisan vendor:publish --tag=webhooker-config
```

Run the migrations:

```
php artisan migrate
```

Quick Start: Outbound Webhooks
------------------------------

[](#quick-start-outbound-webhooks)

### Register an endpoint

[](#register-an-endpoint)

```
use TechraysLabs\Webhooker\Facades\Webhook;

$endpoint = Webhook::registerEndpoint([
    'name' => 'Payment Service',
    'url' => 'https://payments.example.com/webhook',
    'direction' => 'outbound',
    'secret' => 'your-webhook-secret',
    'is_active' => true,
    'timeout_seconds' => 30,
]);
```

### Dispatch an event

[](#dispatch-an-event)

```
Webhook::dispatch($endpoint->id, 'order.created', [
    'order_id' => 12345,
    'total' => 99.99,
    'currency' => 'USD',
]);
```

### Dispatch with idempotency key

[](#dispatch-with-idempotency-key)

```
Webhook::dispatch($endpoint->id, 'order.created', $payload, [
    'idempotency_key' => 'order-123-created',
]);
```

### Broadcast to all active outbound endpoints

[](#broadcast-to-all-active-outbound-endpoints)

```
Webhook::broadcast('order.shipped', [
    'order_id' => 12345,
    'tracking_number' => 'ABC123',
]);
```

### Dispatch to tagged endpoints

[](#dispatch-to-tagged-endpoints)

```
Webhook::dispatchToTag('payments', 'order.created', $payload);
```

The event is persisted immediately and delivered asynchronously via your queue. If delivery fails, it retries automatically with exponential backoff.

Quick Start: Inbound Webhooks
-----------------------------

[](#quick-start-inbound-webhooks)

### Register an inbound endpoint

[](#register-an-inbound-endpoint)

```
$endpoint = Webhook::registerEndpoint([
    'name' => 'Stripe Webhooks',
    'url' => 'https://yourapp.com/api/webhooks/inbound',
    'direction' => 'inbound',
    'secret' => 'whsec_your_stripe_secret',
    'is_active' => true,
    'timeout_seconds' => 30,
]);
```

Inbound webhooks are received at:

```
POST /api/webhooks/inbound/{route_token}

```

Each endpoint gets a unique `route_token` (e.g., `ep_a8f3kx9m2b7q`) auto-generated on creation. The full URL is displayed in the dashboard for easy copy-paste.

The package automatically:

1. Checks IP allowlist (if enabled)
2. Verifies the HMAC signature via the `X-Webhook-Signature` header
3. Rejects invalid or missing signatures with `401`
4. Deduplicates events via the `X-Webhook-Event-ID` header
5. Persists the payload
6. Queues it for async processing

### Custom inbound processing

[](#custom-inbound-processing)

Bind your own processor in a service provider:

```
use TechraysLabs\Webhooker\Contracts\InboundProcessor;

$this->app->bind(InboundProcessor::class, MyStripeProcessor::class);
```

```
use TechraysLabs\Webhooker\Contracts\InboundProcessor;
use TechraysLabs\Webhooker\Models\WebhookEvent;

class MyStripeProcessor implements InboundProcessor
{
    public function process(WebhookEvent $event): bool
    {
        match ($event->event_name) {
            'payment_intent.succeeded' => $this->handlePayment($event->payload),
            'customer.subscription.deleted' => $this->handleCancellation($event->payload),
            default => null,
        };

        return true;
    }
}
```

Dashboard
---------

[](#dashboard-1)

The built-in dashboard provides operational visibility into your webhook events.

Access it at `/webhooks` (configurable prefix).

The dashboard includes:

- **Stats overview** - Total events, delivered, failed, pending, success rate, avg response time, endpoint health breakdown, active circuit breakers
- **Event list** - Filterable by status, endpoint, event name, and tag with bulk actions (replay, delete)
- **Event detail** - Payload preview, delivery timeline with color-coded status, expandable response bodies, replay button
- **Endpoint list** - Route tokens, URLs, direction, active/disabled status, tags, inbound URLs
- **Endpoint detail** - Configuration, health status, circuit breaker state, 7-day success rate sparkline, recent events
- **Dark mode** - Toggle via button, respects system preference, persists via cookie

### Authorization

[](#authorization)

The dashboard is protected by a Laravel Gate. Define it in your `AuthServiceProvider`:

```
Gate::define('viewWebhookDashboard', function ($user) {
    return $user->isAdmin();
});
```

### Disable the dashboard

[](#disable-the-dashboard)

```
// config/webhooks.php
'dashboard' => [
    'enabled' => false,
],
```

Circuit Breaker
---------------

[](#circuit-breaker)

The circuit breaker prevents wasting queue resources on consistently failing endpoints.

**States:**

- `CLOSED` - Endpoint is healthy, deliveries proceed normally
- `OPEN` - Endpoint has failed too many times, deliveries are paused
- `HALF_OPEN` - After cooldown, allows a test delivery to check recovery

```
// config/webhooks.php
'circuit_breaker' => [
    'enabled' => true,
    'failure_threshold' => 10,    // Consecutive failures to trip
    'cooldown_seconds' => 300,    // Wait before half-open test
    'success_threshold' => 2,     // Successes in half-open to close
],
```

The circuit breaker can be bypassed with `--force` on the replay command.

Endpoint Management
-------------------

[](#endpoint-management)

### Enable/Disable

[](#enabledisable)

```
Webhook::disable($endpointId, 'Scheduled maintenance');
Webhook::enable($endpointId);
Webhook::isEnabled($endpointId);
```

### Tagging

[](#tagging)

```
$endpoint->attachTag('payments');
$endpoint->detachTag('payments');
$endpoint->hasTag('payments');

// Dispatch to all endpoints with a tag
Webhook::dispatchToTag('payments', 'order.created', $payload);
```

### Secret Rotation

[](#secret-rotation)

```
$newSecret = Webhook::rotateSecret($endpointId);
```

After rotation, both old and new secrets are accepted during a configurable grace period (default: 24 hours). Expired previous secrets are cleaned up by the `webhook:secret:cleanup` command.

Retention &amp; Pruning
-----------------------

[](#retention--pruning)

By default, webhook events are retained for 30 days. Run the prune command regularly:

```
php artisan webhook:prune
```

Or with a custom retention period:

```
php artisan webhook:prune --days=7
```

Schedule it in your application:

```
$schedule->command('webhook:prune')->daily();
$schedule->command('webhook:secret:cleanup')->hourly();
```

Retry Configuration
-------------------

[](#retry-configuration)

The default retry strategy uses exponential backoff:

```
// config/webhooks.php
'retry' => [
    'max_attempts' => 5,
    'base_delay_seconds' => 10,
    'multiplier' => 2,
],
```

This produces delays of: 10s, 20s, 40s, 80s, 160s.

### Per-endpoint retry

[](#per-endpoint-retry)

```
$endpoint->max_retries = 10;
$endpoint->retry_strategy = MyCustomRetryStrategy::class;
$endpoint->save();
```

### Custom retry strategy

[](#custom-retry-strategy)

Implement the `RetryStrategy` contract and bind it in your service provider:

```
use TechraysLabs\Webhooker\Contracts\RetryStrategy;

$this->app->bind(RetryStrategy::class, MyCustomRetryStrategy::class);
```

Rate Limiting
-------------

[](#rate-limiting)

Prevent overwhelming destination servers:

```
// config/webhooks.php
'rate_limiting' => [
    'enabled' => false,
    'default_per_minute' => 60,
],
```

Per-endpoint override via the `rate_limit_per_minute` column on `webhook_endpoints`.

Payload Validation
------------------

[](#payload-validation)

Validate outbound payloads before dispatch:

```
// config/webhooks.php
'payload_validation' => [
    'enabled' => false,
    'schemas' => [
        'order.created' => [
            'order_id' => 'required|integer',
            'amount' => 'required|numeric',
            'currency' => 'required|string|size:3',
        ],
    ],
],
```

Invalid payloads throw `InvalidWebhookPayloadException`.

IP Allowlist (Inbound)
----------------------

[](#ip-allowlist-inbound)

Restrict inbound webhooks to known IPs:

```
// config/webhooks.php
'inbound' => [
    'ip_allowlist' => [
        'enabled' => false,
        'global' => ['192.168.1.0/24'],
        'trust_proxy' => false,
    ],
],
```

Per-endpoint allowlists can be set via the `allowed_ips` JSON column.

Storage Driver Abstraction
--------------------------

[](#storage-driver-abstraction)

Laravel Webhooker uses a pluggable storage layer based on Laravel's Manager pattern. The default driver is `eloquent`.

```
// config/webhooks.php
'storage' => [
    'driver' => env('WEBHOOK_STORAGE_DRIVER', 'eloquent'),

    'drivers' => [
        'eloquent' => [
            'connection' => null,
            'read_connection' => null,
        ],
    ],
],
```

### Custom storage drivers

[](#custom-storage-drivers)

Extend the `WebhookStorageManager` to register your own drivers:

```
use TechraysLabs\Webhooker\Storage\WebhookStorageManager;

app(WebhookStorageManager::class)->extend('dynamodb', function ($app) {
    return new DynamoDbWebhookRepository(config('webhooks.storage.drivers.dynamodb'));
});
```

Dead-Letter Queue
-----------------

[](#dead-letter-queue)

Events that exhaust all retries can be automatically moved to a dead-letter queue for inspection and manual retry.

```
// config/webhooks.php
'dead_letter' => [
    'enabled' => false,
    'auto_move' => true,        // Auto-move after retries exhausted
    'retention_days' => 90,     // DLQ retention before pruning
],
```

### Managing the DLQ

[](#managing-the-dlq)

```
# List dead-lettered events
php artisan webhook:dead-letter list

# Retry a specific dead-lettered event
php artisan webhook:dead-letter retry {event_id}

# Purge all dead-lettered events older than retention
php artisan webhook:dead-letter purge

# Count dead-lettered events
php artisan webhook:dead-letter count
```

The `WebhookMovedToDeadLetter` event is fired when an event enters the DLQ.

Event Batching
--------------

[](#event-batching)

Dispatch the same event to multiple endpoints as a tracked batch:

```
use TechraysLabs\Webhooker\Facades\Webhook;

// Dispatch to specific endpoints
$batch = Webhook::dispatchBatch([1, 2, 3], 'order.created', [
    'order_id' => 12345,
    'total' => 99.99,
]);

// Broadcast to all active outbound endpoints as a batch
$batch = Webhook::broadcastBatch('order.shipped', [
    'order_id' => 12345,
    'tracking_number' => 'ABC123',
]);

// Check batch progress
$batch = Webhook::batchStatus($batch->id);
echo $batch->status;          // pending, processing, completed, partial_failure, failed
echo $batch->success_count;
echo $batch->failure_count;
```

```
// config/webhooks.php
'batching' => [
    'enabled' => true,
    'max_batch_size' => 1000,
    'allow_partial_failure' => true,
],
```

Endpoint Health History
-----------------------

[](#endpoint-health-history)

Capture periodic health snapshots for trend analysis:

```
// config/webhooks.php
'health_history' => [
    'enabled' => false,
    'snapshot_interval' => 60,   // Minutes between snapshots
    'retention_days' => 90,
],
```

Schedule the snapshot command:

```
$schedule->command('webhook:health:snapshot')->hourly();
```

Access health history programmatically:

```
use TechraysLabs\Webhooker\Contracts\WebhookMetrics;

$metrics = app(WebhookMetrics::class);
$history = $metrics->endpointHealthHistory($endpointId, days: 30);

foreach ($history as $point) {
    echo "{$point->date}: {$point->successRate}% ({$point->status})";
}
```

Multi-Database Support
----------------------

[](#multi-database-support)

Route reads to a replica and writes to the primary database:

```
// config/webhooks.php
'storage' => [
    'driver' => 'eloquent',

    'drivers' => [
        'eloquent' => [
            'connection' => 'mysql',              // Primary for writes
            'read_connection' => 'mysql-replica',  // Replica for reads
        ],
    ],
],
```

All repository queries are automatically routed to the correct connection.

Table Partitioning
------------------

[](#table-partitioning)

For high-volume installations, partition the `webhook_events` and `webhook_attempts` tables:

```
// config/webhooks.php
'partitioning' => [
    'enabled' => false,
    'strategy' => 'monthly',
    'tables' => ['webhook_events', 'webhook_attempts'],
    'future_partitions' => 3,
],
```

Publish the partition migration stubs:

```
php artisan vendor:publish --tag=webhooker-stubs
```

Manage partitions via Artisan:

```
# Create future partitions
php artisan webhook:partition:create

# Drop old partitions
php artisan webhook:partition:drop --before=2025-01
```

Supports MySQL (RANGE partitioning) and PostgreSQL (declarative partitioning).

Horizontal Scaling
------------------

[](#horizontal-scaling)

For multi-worker deployments, enable distributed locking to prevent duplicate event processing:

```
// config/webhooks.php
'scaling' => [
    'enabled' => false,
    'lock_driver' => 'cache',
    'lock_ttl' => 300,           // Lock timeout in seconds
    'unique_jobs' => true,
],
```

When enabled, each webhook job acquires a distributed lock before processing. This ensures that even with multiple queue workers, each event is processed exactly once.

You can provide your own lock implementation by binding the `WebhookLock` contract:

```
use TechraysLabs\Webhooker\Contracts\WebhookLock;

$this->app->bind(WebhookLock::class, MyRedisLockProvider::class);
```

Testing
-------

[](#testing)

Use the testing facade in your application's test suite:

```
use TechraysLabs\Webhooker\Facades\Webhook;

Webhook::fake();

// ... trigger your application code ...

Webhook::assertDispatched('order.created');
Webhook::assertDispatched('order.created', function ($event) {
    return $event->payload['order_id'] === 123;
});
Webhook::assertNothingDispatched();
Webhook::assertDispatchedTimes('order.created', 3);
```

Or use the trait:

```
use TechraysLabs\Webhooker\Testing\InteractsWithWebhooks;

class MyTest extends TestCase
{
    use InteractsWithWebhooks;

    public function test_something(): void
    {
        $fake = $this->fakeWebhooks();
        // ... trigger your app code ...
        $fake->assertDispatched('order.created');
    }
}
```

Debug Mode
----------

[](#debug-mode)

Enable verbose logging in development:

```
// config/webhooks.php
'debug' => [
    'enabled' => env('WEBHOOK_DEBUG', false),
    'log_full_payload' => false,
    'log_full_headers' => false,
    'log_full_response_body' => false,
],
```

A runtime warning is logged if debug mode is enabled in a production environment.

Laravel Events
--------------

[](#laravel-events)

The package fires native Laravel events at key lifecycle points:

EventFires When`WebhookSending`Before outbound HTTP call`WebhookSent`After successful delivery`WebhookFailed`After a failed attempt`WebhookRetriesExhausted`All retries used up`WebhookReplayRequested`Replay triggered`InboundWebhookReceived`Inbound payload arrives`InboundWebhookProcessed`Inbound processing succeeds`InboundWebhookFailed`Inbound processing fails`EndpointDisabled`Endpoint disabled`EndpointEnabled`Endpoint re-enabled`EndpointCircuitOpened`Circuit breaker trips`EndpointCircuitClosed`Circuit breaker recovers`EndpointSecretRotated`Secret rotation completed`WebhookMovedToDeadLetter`Event moved to dead-letter queue`WebhookBatchCompleted`All events in a batch succeeded`WebhookBatchPartiallyFailed`Batch completed with mixed resultsCLI Commands
------------

[](#cli-commands)

CommandDescription`webhook:prune`Delete events older than retention period`webhook:replay {event_id}`Re-dispatch a single event`webhook:replay --status= --endpoint=`Bulk replay with filters`webhook:endpoint:list`List all registered endpoints`webhook:endpoint:disable {id}`Disable an endpoint`webhook:endpoint:enable {id}`Enable an endpoint`webhook:health`Show health status of all endpoints`webhook:circuit:status`Show circuit breaker states`webhook:circuit:reset {endpoint_id}`Reset circuit breaker`webhook:simulate {type}`Simulate inbound webhook delivery`webhook:secret:rotate {endpoint_id}`Rotate endpoint secret`webhook:secret:cleanup`Remove expired previous secrets`webhook:dead-letter list|retry|purge|count`Manage dead-letter queue`webhook:health:snapshot`Capture endpoint health snapshots`webhook:partition:create`Create future table partitions`webhook:partition:drop`Drop old table partitionsConfiguration Reference
-----------------------

[](#configuration-reference)

```
// config/webhooks.php
return [
    'retry' => [
        'max_attempts' => 5,
        'base_delay_seconds' => 10,
        'multiplier' => 2,
    ],
    'timeout' => 30,
    'signing_algorithm' => 'sha256',
    'signature_header' => 'X-Webhook-Signature',
    'queue' => [
        'connection' => null,
        'name' => 'webhooks',
    ],
    'retention_days' => 30,
    'store_response_body' => true,
    'log_request_headers' => false,
    'dashboard' => [
        'enabled' => true,
        'prefix' => 'webhooks',
        'middleware' => ['web', 'auth'],
        'gate' => 'viewWebhookDashboard',
        'max_bulk_size' => 100,
    ],
    'metrics' => [
        'cache_ttl' => 60,
        'healthy_threshold' => 95,
        'degraded_threshold' => 70,
    ],
    'circuit_breaker' => [
        'enabled' => true,
        'failure_threshold' => 10,
        'cooldown_seconds' => 300,
        'success_threshold' => 2,
    ],
    'logging' => [
        'channel' => env('WEBHOOK_LOG_CHANNEL', null),
        'log_payload' => false,
        'log_headers' => false,
        'log_level' => 'info',
    ],
    'debug' => [
        'enabled' => env('WEBHOOK_DEBUG', false),
        'log_full_payload' => false,
        'log_full_headers' => false,
        'log_full_response_body' => false,
    ],
    'rate_limiting' => [
        'enabled' => false,
        'default_per_minute' => 60,
    ],
    'payload_validation' => [
        'enabled' => false,
        'schemas' => [],
    ],
    'inbound' => [
        'ip_allowlist' => [
            'enabled' => false,
            'global' => [],
            'trust_proxy' => false,
        ],
    ],
    'secret_rotation' => [
        'grace_period_hours' => 24,
    ],
    'storage' => [
        'driver' => env('WEBHOOK_STORAGE_DRIVER', 'eloquent'),
        'drivers' => [
            'eloquent' => [
                'connection' => null,
                'read_connection' => null,
            ],
        ],
    ],
    'dead_letter' => [
        'enabled' => false,
        'auto_move' => true,
        'retention_days' => 90,
    ],
    'batching' => [
        'enabled' => true,
        'max_batch_size' => 1000,
        'allow_partial_failure' => true,
    ],
    'health_history' => [
        'enabled' => false,
        'snapshot_interval' => 60,
        'retention_days' => 90,
    ],
    'partitioning' => [
        'enabled' => false,
        'strategy' => 'monthly',
        'tables' => ['webhook_events', 'webhook_attempts'],
        'future_partitions' => 3,
    ],
    'scaling' => [
        'enabled' => false,
        'lock_driver' => 'cache',
        'lock_ttl' => 300,
        'unique_jobs' => true,
    ],
];
```

Upgrade Guide
-------------

[](#upgrade-guide)

### Upgrading from v0.1.0 to v2.0.0

[](#upgrading-from-v010-to-v200)

v2.0.0 introduces breaking changes to the `WebhookRepository` contract, `DispatchWebhookJob`, and `ProcessInboundWebhookJob`. If you have custom implementations of these contracts, you will need to update them.

1. Run the new migrations:

```
php artisan migrate
```

2. If you have a custom `WebhookRepository` implementation, add the new method signatures from the contract.
3. If you dispatch jobs manually (outside the facade), update `handle()` calls to include the `WebhookLock` parameter.
4. Review the new config sections added to `config/webhooks.php` and publish updated config if needed:

```
php artisan vendor:publish --tag=webhooker-config --force
```

Roadmap
-------

[](#roadmap)

### v0.1.0 (Released)

[](#v010-released)

Core webhook engine: outbound/inbound delivery, retry, signatures, circuit breaker, dashboard, tagging, rate limiting, payload validation, IP allowlist, secret rotation, idempotency, testing facade, debug mode.

### v2.0.0 (Released)

[](#v200-released)

- Storage driver abstraction
- Dead-letter queue
- Event batching
- Endpoint health history
- Multi-database support
- Table partitioning support
- Horizontal scaling support

### Future

[](#future)

- Webhook event transforms (modify payload per endpoint)
- Webhook event filtering (subscribe endpoints to specific event patterns)
- GraphQL / REST API for programmatic management
- Webhook delivery analytics dashboard
- Webhook event schema registry
- Real-time delivery monitoring via WebSockets
- Plugin system for third-party integrations

Contributing
------------

[](#contributing)

Contributions are welcome. Please follow these guidelines:

1. Fork the repository
2. Create a feature branch (`feature/your-feature`)
3. Write tests for your changes
4. Ensure all tests pass (`vendor/bin/phpunit`)
5. Format code with Laravel Pint (`vendor/bin/pint`)
6. Use conventional commits (`feat:`, `fix:`, `refactor:`, `test:`, `docs:`)
7. Submit a pull request

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE) for details.

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance81

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 58.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~10 days

Total

4

Last Release

102d ago

Major Versions

0.2.1 → 1.0.02026-03-24

### Community

Maintainers

![](https://www.gravatar.com/avatar/fbc81921c8cd498bd1d838e44ad7cad57b73e08cdfefa576289e9afe4cb88273?d=identicon)[techrays-labs](/maintainers/techrays-labs)

---

Top Contributors

[![claude](https://avatars.githubusercontent.com/u/81847?v=4)](https://github.com/claude "claude (21 commits)")[![chirag-techrayslabs](https://avatars.githubusercontent.com/u/160377961?v=4)](https://github.com/chirag-techrayslabs "chirag-techrayslabs (15 commits)")

---

Tags

laravelqueuewebhooksretryhmacreplaywebhook-engineoutbound-webhooksinbound-webhooks

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/techrays-labs-laravel-webhooker/health.svg)

```
[![Health](https://phpackages.com/badges/techrays-labs-laravel-webhooker/health.svg)](https://phpackages.com/packages/techrays-labs-laravel-webhooker)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M132](/packages/laravel-pulse)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M131](/packages/roots-acorn)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.6k29.9M147](/packages/laravel-cashier)[api-platform/laravel

API Platform support for Laravel

58171.6k14](/packages/api-platform-laravel)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77022.3M151](/packages/laravel-mcp)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
