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

Filament Webhook Client Laravel Package

tapp/filament-webhook-client

Filament resource and policy for Spatie Webhook Client. Adds a WebhookCall resource to your Filament panel with configurable models, policies, navigation, and translations. Requires Spatie Webhook Client installed and configured.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a thin UI layer: it adds a read-only Filament resource so you can eyeball the rows that Spatie Webhook Client already writes to your webhook_calls table. It does not receive, validate, process, or dispatch webhooks — Spatie does. Treat the install as "Spatie first, plugin second."

  1. Install and configure Spatie Webhook Client (the README explicitly flags this as a prerequisite). You need the webhook_calls migration published and migrated, plus at least one profile in config/webhook-client.php with a signing secret and a WebhookProcessor. If the table doesn't exist, this plugin's resource will 500 on you.

  2. Install the UI package, matching the Filament major:

    composer require tapp/filament-webhook-client:"^4.0"   # Filament 4.x / 5.x
    # Filament 3.x → use 1.x instead
    
  3. Publish the config so you have something to edit:

    php artisan vendor:publish --tag="filament-webhook-client-config"
    
  4. Register the plugin in your panel provider:

    use Tapp\FilamentWebhookClient\FilamentWebhookClientPlugin;
    
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->plugins([
                FilamentWebhookClientPlugin::make(),
            ]);
    }
    

Where to look first: the generated config/filament-webhook-client.php maps four things — resources.WebhookCallResource, models.webhook-call, policies.webhook-call, and navigation.{sort,icon}. Everything you'll ever want to change lives there or in a subclass of the resource. Then open the panel and hit Webhook Calls in the sidebar: the list shows url/method/created_at, and the view page renders payload and headers as formatted JSON (a deliberate choice since v1.0.1, replacing the old KeyValueEntry).

First real use case: you've just wired up a Stripe/GitHub/Shopify endpoint and the signature check is failing or your processor is silently doing nothing. Fire a test webhook, then open the record in the panel to read the raw payload, headers, url, method, and — when processing blew up — the stored exception. That exception field is the single most valuable thing this package surfaces; it's Spatie's job-failure trace sitting in a column you'd otherwise be querying by hand.

Implementation Patterns

The daily loop is "receive → inspect → fix processor." Your WebhookProcessor::process() throws, Spatie stores the call with the exception attached, and you read it in the panel. Keep the resource purely diagnostic — resist the urge to make it a workflow tool.

Restrict access via the policy, not the panel. The bundled WebhookCallPolicy allows viewAny and view for everyone who can reach the panel. In any multi-role app that's too loose:

// config/filament-webhook-client.php
'policies' => [
    'webhook-call' => \App\Policies\WebhookCallPolicy::class,
],
class WebhookCallPolicy
{
    public function viewAny(User $user): bool
    {
        return $user->hasRole('admin');
    }

    public function view(User $user, WebhookCall $call): bool
    {
        return $user->hasRole('admin');
    }
}

Since the default policy grants no delete/update, the resource is effectively read-only unless you write those abilities yourself — which is usually the right call, because deleting a stored call destroys your only forensic record.

Subclass the resource when you need columns, filters, or a different nav label. The v4.1.2 fix ("Resource pages to use the class from the config file") means page classes now resolve through the configured resource class, so this override pattern actually works end to end:

namespace App\Filament\Resources;

use Tapp\FilamentWebhookClient\Resources\WebhookCallResource as BaseResource;

class WebhookCallResource extends BaseResource
{
    // add a filter, change default sort, add a "replay" action, etc.
}
'resources' => [
    'WebhookCallResource' => \App\Filament\Resources\WebhookCallResource::class,
],

Swap the model if you've extended Spatie's. A very common day-two change is adding a status or processed_at column to webhook_calls. If you did, point the config at your model so the resource's table queries the right class:

'models' => [
    'webhook-call' => \App\Models\WebhookCall::class,
],

Rename the nav item. There's no label key in the published config — the label comes from translations. Publish them (--tag="filament-webhook-client-translations") and edit rather than trying to force it through navigation.

Multi-panel apps: register the plugin only on the panel where support staff live. Registering it on a customer-facing panel and relying on the policy to hide it is a worse pattern — the resource will still be discoverable to anyone who can guess the route, and policy mistakes become data leaks.

Pair it with your existing logging. The plugin shows you one call. When you need correlation across calls, a webhook_calls row, and your processor's own logs, keep the Spatie call id in your log context so you can pivot between the panel and your log viewer.

Gotchas and Tips

  • Version/compat traps. ^4.0 is the only line that works with Filament 4/5; 1.x is Filament 3. Composer will happily resolve an incompatible pair if your constraints are loose, and you'll get opaque Livewire/Filament errors rather than an install failure. Pin explicitly.
  • The table grows forever. The plugin gives you zero retention tooling. Webhook payloads are fat (often 5–50 KB of JSON each). Add a pruning command or a model Prunable on the underlying WebhookCall early, or you'll be looking at a multi-GB table in a year.
  • Rendering huge payloads is slow. The view page pretty-prints the full JSON. A 2 MB payload from a bulk-import webhook will make the browser miserable. If that's your traffic profile, subclass the view page and truncate or lazy-load.
  • PII and secrets in payloads. Headers include signature headers; payloads routinely carry customer emails, addresses, and partial card metadata. The default "anyone in the panel can view" policy is a real compliance hazard. Audit it before deploying.
  • Spatie configuration is the usual root cause. "Webhooks aren't appearing" is almost never this plugin. Check, in order: is the route registered and reachable, does the profile's signing_secret match, does WebhookProcessor exist at the configured class, and is the request actually passing signature validation (invalid signatures are rejected before storage). Once the row exists, the plugin will show it.
  • Conflicting policy registration. If you also register a Gate::policy() for the webhook model in an AuthServiceProvider, the two can fight. Pick one registration path — the config key here is the cleaner one.
  • Debugging the resource itself: it's a normal Filament resource, so livewire(ListWebhookCalls::class)->assertCanSeeTableRecords(...) works in tests, and the usual Filament table-debugging advice applies when columns look wrong after an upgrade (v4.1.2 reworked the default table).
  • Don't build business logic on this. 11 stars, zero dependents, and a changelog dominated by Dependabot bumps — the maintenance surface is small and the real implementation risk sits in Spatie's package. Use it for inspection, use the config keys for customization, and don't fork the resource into something your application depends on.
  • Extension points worth knowing: the four config maps (resource/model/policy/navigation) plus the translations file. That's the entire customization API — anything deeper means subclassing, and subclassing means diffing against upstream on every ^4.0 bump.
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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator