Reference
Configuration reference
php artisan vendor:publish --tag=webhook-signature-config
endpoints
A map of endpoint name to its configuration. Empty by default — until you declare one, every lookup throws, because deny-by-default applies to configuration as much as to signatures.
'endpoints' => [
'github' => [
'scheme' => 'github',
'secrets' => ['current' => env('GITHUB_WEBHOOK_SECRET')],
'tolerance' => 300,
'replay' => true,
],
],
| Key | Type | Default | Meaning |
|---|---|---|---|
scheme |
string | required | A registered scheme name |
secrets |
string | list | map | — | The live secrets. Also accepted as secret |
tolerance |
int | null | scheme default | Window in seconds. null disables it. Omit to inherit |
replay |
bool | — | false opts this endpoint out of single-use enforcement |
secrets
'secrets' => 'one-secret',
'secrets' => ['secret-a', 'secret-b'],
'secrets' => ['new' => 'secret-b', 'old' => 'secret-a'], // preferred
For an asymmetric scheme (postal) these hold PEM public keys rather than shared
secrets. They are not confidential and cannot be used to sign, but they rotate the same way,
so the shape is the same.
A list because rotation is not atomic. Labels are
reported back as VerifiedWebhook::$secretId, which is how you know when the old secret can
safely be removed.
The first secret signs outbound messages.
Empty and null entries are dropped. An endpoint that ends up with none refuses everything
with no_secret_configured — an unset environment variable must not read as "verification
off".
tolerance
Two levels, not three: the endpoint's value if it set one, otherwise the scheme's own
default. Omitting the key inherits; setting it to null explicitly disables the window.
A scheme that binds no timestamp cannot gain a window from configuration, whatever you write here. There is nothing signed to check against.
schemes
Extra schemes built by the generic HMAC driver. Empty by default. See custom schemes for the key list.
Registered after the bundled drivers, so an entry named github replaces the bundled
GitHub scheme rather than colliding with it.
replay
'replay' => [
'enabled' => env('WEBHOOK_SIGNATURE_REPLAY', false),
'store' => env('WEBHOOK_SIGNATURE_REPLAY_STORE'),
'ttl' => 3600,
],
| Key | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | false |
Master switch for single-use enforcement |
store |
string | null | null |
Cache store name; null uses the application default |
ttl |
int | 3600 |
Seconds a delivery is remembered as seen |
Off by default because it is only correct against a store shared by every node — see
replay protection. Set store to Redis,
Memcached, or a shared database store before enabling.
ttl must be at least as long as your widest tolerance window, or a delivery could age out
of the guard while still passing the timestamp check.
Environment variables
The package reads only what its own config file references:
| Variable | Used for |
|---|---|
WEBHOOK_SIGNATURE_REPLAY |
replay.enabled |
WEBHOOK_SIGNATURE_REPLAY_STORE |
replay.store |
Secrets are referenced by whatever names you choose in your own endpoints block.
What the package registers
Route middleware
Aliased as webhook.signature, taking the endpoint name as its parameter:
->middleware('webhook.signature:github')
Responses on refusal: 401 for anything the caller got wrong, 500 when the failure is our own configuration — so a provider retries a misconfigured receiver instead of discarding events it delivered correctly.
HTTP client macro
Http::webhookSignature($endpoint, ?int $timestamp = null) returns a PendingRequest that
signs whatever it finally sends:
Http::webhookSignature('outbound')->post($subscriber->url, $payload);
Registered only if nothing else has claimed the name, so an application macro of the same name keeps precedence.
Console commands
php artisan webhook:sign {endpoint} prints the headers — or, with --curl, a runnable
command — for a payload signed with the endpoint's real secret.
php artisan webhook:verify {endpoint} takes a delivery you actually received and explains
the outcome, distinguishing a stale delivery from a forged one. See
debugging a failed verification.
Facade
Webhooks (Cbox\WebhookSignature\Facades\Webhooks), aliased by package discovery. Use it
for the cases the macro and the middleware do not cover: verifying something other than the
current request, or signing with a per-subscriber secret.