Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Nova Webhooks Laravel Package

opscale-co/nova-webhooks

opscale-co/nova-webhooks adds webhook management to Laravel Nova. Create and manage outgoing webhook endpoints, configure events, and monitor deliveries from your Nova admin panel. A straightforward tool for integrating webhook support into Laravel applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire it up

composer require opscale-co/nova-webhooks
php artisan vendor:publish --provider="Opscale\NovaWebhooks\NovaWebhooksServiceProvider"
php artisan migrate

Then register the tool/resource in app/Nova/NovaServiceProvider.php (tools() or resources()) unless the package auto-discovers it. Confirm the required PHP, Laravel, and Nova majors against the package's composer.json before you commit — the changelog does not state whether v1.2.0 raises any version floors.

Where to look first, in order

  1. config/nova-webhooks.php (after publishing) — queue connection, signing secret, retry/timeout, event mappings. This is the file that answers 80% of your questions.
  2. The package service provider — it shows which model events are hooked and how delivery is dispatched (job class, queue name, sync vs. queued).
  3. The Nova resource(s) — webhook endpoints and delivery logs. Read the fields to learn what the package actually persists.
  4. The migrations — the delivery-log schema tells you what debugging data you get (status code, response body, attempt count, payload).
  5. If you use opscale-co/actions directly, its v4 upgrade notes — v1.2.0's only change is adopting actions v4.

First use case (do this before anything else)

Create one webhook endpoint pointing at a request bin (webhook.site, ngdst, or php artisan serve + a dump route). Subscribe it to created on a low-risk test model. Set the signing secret. Confirm a queue worker is running. Create a record. Inspect the delivery log — status code, payload body, headers. That single loop validates config, queue, event wiring, serialization, and signing all at once.

Do not start by wiring up a production consumer. You need to see one payload first.

Implementation Patterns

Endpoint-per-system, not one catch-all

Create one webhook row per external system per environment. A single "send everything to one URL" endpoint forces the receiver to route by event type, duplicates retry/backoff semantics across unrelated consumers, and makes disabling one integration impossible without disabling all of them.

Use the active/inactive toggle as your rollout mechanism

This is the package's main day-to-day operational lever. Register the endpoint inactive, deploy the consumer, verify it can accept and validate a payload, then flip it on in Nova. If the consumer breaks in production, flip it off — no redeploy, no queue drain, no stuck jobs. This is the reason to keep endpoint config in the database rather than in config files.

Keep secrets out of the database where you can

The Nova UI is convenient for URLs and event subscriptions. Signing secrets are the one thing worth sourcing from environment/secret manager if the package supports it. If it only stores secrets in the DB, then treat DB read access as equivalent to secret read access and gate accordingly (see Gotchas).

Subscribe narrowly

Prefer explicit created/updated/deleted on the specific models that matter. Broad subscriptions multiply outbound requests by fan-out: one internal event with N subscribers is N HTTP calls and N log rows. On a high-write model that is your queue backlog and your storage bill, not the webhook package's problem to solve for you.

Normalize the payload at the source

Webhook payloads are a public contract with an external team. If the package supports payload transformers or custom resources, put serialization there — never ship raw $model->toArray(). Raw attributes leak internal column names, expose fields you added later without thinking, and change shape every time you touch a migration. A stable, deliberately-versioned payload is worth the small amount of extra code.

Trigger from domain actions, not controllers

If you are dispatching webhooks from your own code, do it from a service class or action so the same event fires regardless of entry point (HTTP, console, queue, Nova action). With opscale-co/actions v4 in the dependency graph, align your action signatures with the contract the package expects — a mismatch here surfaces as silently-missing deliveries, not an exception.

Test with fakes, at the right layer

  • Queue::fake() if the package dispatches a job — assert the job was pushed, not that HTTP happened. This is the fast test.
  • Http::fake() if delivery is synchronous or you are testing the job in isolation — assert URL, headers, and signature header.
  • For the retry path, Http::fake() with a sequenced 500-then-200 response and run the job directly a few times.
  • Keep one slow integration test against a real request bin in your staging suite only — not in CI.

Multi-tenant scoping

If you run multi-tenant, scope both endpoints and delivery logs by tenant. The dangerous failure here is a shared endpoint whose payload for tenant A gets delivered to a consumer that assumes tenant B — or worse, a delivery log that lets a tenant admin read payloads containing another tenant's data.

Gotchas and Tips

v1.2.0 is a dependency bump. Treat it as one.

The release note says only "adopt opscale-co/actions v4." That is a major bump of the dispatch/execution layer inside a minor package release. The changelog does not state whether behavior changed. Before upgrading, diff composer.json between v1.1.0 and v1.2.0 — if the only diff is the actions constraint, you have bounded the risk in fifteen minutes. If the PHP/Laravel/Nova floors also moved, you have a decision to make.

Practical exposure: retry/backoff defaults, job payload shape, and middleware all live in that dependency. Those are exactly the behaviors a smoke test will not catch. Run v1.2.0 in a branch with a receiver that deliberately returns 4xx and 5xx, and watch the retry pattern before merging.

"Nothing happened" is almost never the package

Debug in this order: (1) Is the event actually subscribed? (2) Is the webhook active? (3) Is a queue worker running with the right connection? (4) Is the job in failed_jobs? (5) What does the delivery log say? Nine times out of ten it is step 3.

Config changes need a restart, not a save

php artisan config:clear
php artisan queue:restart

Long-running workers hold the old config in memory. Changing the queue connection or signing secret and then wondering why nothing changed is the single most common self-inflicted wound with any webhook package.

Assume at-least-once delivery

Verify with your consumer team that duplicates are tolerated. If the package does not emit a delivery ID or idempotency key header, add one via a payload transformer or header extension point — retrofitting idempotency into a consumer after it has processed duplicates in production is expensive. Retry semantics are exactly the thing the actions v4 bump could have altered, so re-verify after upgrading.

Rotate secrets with an overlap window

The package's secret rotation story is unverified. The safe pattern regardless of implementation: accept both old and new secret on the consumer for a window, swap the secret in Nova, wait out the longest in-flight retry backoff, then drop the old secret. Rotating without overlap drops every delivery already queued with the old signature.

Restrict outbound URLs — this is an SSRF surface

Anyone with Nova access to create a webhook can make your server issue HTTP requests to arbitrary internal addresses (169.254.169.254, localhost, internal admin panels on 10.x). If your Nova users are all trusted admins, note it and move on. If not, add an allowlist or push endpoint creation behind an approval workflow, and apply egress network policy as a second layer.

Gate the Nova resource with a policy

Webhook endpoints and delivery logs contain signing secrets and full model payloads. Default-deny: write a Nova policy and restrict to the smallest group that needs it. A delivery log showing a User payload with hashed passwords or an Order with customer PII is a data-exposure incident, not a convenience.

Watch delivery-log growth

Logs accumulate per attempt, including retries. A flapping consumer endpoint generates retries whose log rows outnumber successful deliveries. Confirm whether there is pruning/retention support before launch; if not, schedule a pruning job against the log table yourself from day one. Otherwise this table quietly becomes your fastest-growing storage cost.

Queue worker concurrency is your throughput ceiling

Per-endpoint HTTP timeout × worker count determines maximum throughput. Size for peak event volume, not average. A consumer that gets slow (not down — just slow) will hold workers and back up unrelated jobs in the same queue. Isolate webhook delivery onto its own queue if the package's config allows it — that one setting prevents a flapping external endpoint from delaying your application's own background work.

Keep the integration thin

Given the low star count, unknown maintainer cadence, and a delivery path now spanning two packages from the same vendor organization, keep business logic out of the package's extension points. Payload transformation should be thin and declarative; domain logic stays in your actions. If support degrades, replacing the dispatcher becomes a config change rather than a rewrite.

Don't fight an existing dispatcher

If you already run spatie/laravel-webhook-server or an in-house implementation, evaluate whether this adds real value — the Nova admin UI and delivery logs are the differentiator. Delivery itself, signing, and retries are commodities. Adding a second dispatcher to the same app to get the UI is a bad trade; adding it to replace the first one is worth a dual-run period before cutover.

Clear extension points after every upgrade

If you've published config or added payload transformers, re-check them after any opscale-co/actions bump. Extensions are the part that breaks silently — the package works, your transform throws, and you find out when a consumer complains about missing fields.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings