Laravel Polar automatically verifies and processes Polar.sh webhooks, dispatching typed Laravel events for every order, subscription, checkout, and more.
Use this file to discover all available pages before exploring further.
Webhooks are how Polar.sh tells your application what has happened — a subscription was created, an order was placed, a checkout expired. Laravel Polar handles signature verification and payload parsing automatically, then dispatches typed Laravel events your listeners can react to.You don’t need to write any webhook verification code. This page explains the endpoint, the 21 events that are dispatched, and the two ways to register listeners.
When you install the package it registers a POST /polar/webhook route. Every incoming request is processed in this order:
Verified against your POLAR_WEBHOOK_SECRET — invalid signatures are rejected with a 400 response before any event is dispatched.
Parsed into a typed payload object using the Polar PHP SDK.
Synced to your database — for example, creating or updating a Subscription record when a subscription.created event arrives.
Dispatched as a typed Laravel event so your own listeners can run custom logic (send emails, provision access, update feature flags, etc.).
You must exempt polar/* from CSRF verification in bootstrap/app.php, otherwise Polar’s requests will be rejected with a 419 response before verification can run. See the installation guide for the exact snippet.
The package dispatches a unique Laravel event class for each Polar event type. All events carry a $payload property with the full typed Polar SDK payload. Some events also expose convenience properties ($billable, $order, $subscription) for direct access to your local Eloquent models — no manual lookups required.
Events with $billable and $order convenience properties.
Event class
Polar event
Convenience properties
Danestves\LaravelPolar\Events\OrderCreated
order.created
$billable, $order, $payload
Danestves\LaravelPolar\Events\OrderUpdated
order.updated
$billable, $order, $payload
use Danestves\LaravelPolar\Events\OrderCreated;public function handle(OrderCreated $event): void{ $order = $event->order; // local Order model $user = $event->billable; // local billable (e.g. User) $raw = $event->payload; // WebhookOrderCreatedPayload}
use Danestves\LaravelPolar\Events\SubscriptionCanceled;public function handle(SubscriptionCanceled $event): void{ $subscription = $event->subscription; // local Subscription model $user = $event->billable;}
After the package finishes processing any webhook — regardless of type — it dispatches Danestves\LaravelPolar\Events\WebhookHandled with the raw payload array. Use this as a catch-all for logging, auditing, or handling event types you have not registered individual listeners for:
use Danestves\LaravelPolar\Events\WebhookHandled;public function handle(WebhookHandled $event): void{ logger('Polar webhook received', ['type' => $event->payload['type']]);}
Laravel 11 and 12 will auto-discover listeners that follow the standard naming convention, so the $listen array registration may be optional in those versions.
If you want to handle multiple event types in one place, create an event subscriber. Register all your listeners inside the subscribe method and then register the subscriber class in your EventServiceProvider:
// app/Listeners/PolarEventSubscriber.phpnamespace App\Listeners;use Danestves\LaravelPolar\Events\CheckoutCreated;use Danestves\LaravelPolar\Events\OrderCreated;use Danestves\LaravelPolar\Events\SubscriptionCanceled;use Danestves\LaravelPolar\Events\WebhookHandled;use Illuminate\Events\Dispatcher;class PolarEventSubscriber{ public function handleOrderCreated(OrderCreated $event): void { // provision access, send a receipt email, etc. $order = $event->order; $user = $event->billable; } public function handleCheckoutCreated(CheckoutCreated $event): void { $checkout = $event->payload->checkout; // track analytics, send a "you started checkout" email, etc. } public function handleSubscriptionCanceled(SubscriptionCanceled $event): void { $subscription = $event->subscription; // send a win-back email, revoke feature flags, etc. } public function handleWebhookHandled(WebhookHandled $event): void { // catch-all: log every webhook for debugging logger('Polar webhook', ['type' => $event->payload['type']]); } public function subscribe(Dispatcher $events): void { $events->listen(OrderCreated::class, [self::class, 'handleOrderCreated']); $events->listen(CheckoutCreated::class, [self::class, 'handleCheckoutCreated']); $events->listen(SubscriptionCanceled::class,[self::class, 'handleSubscriptionCanceled']); $events->listen(WebhookHandled::class, [self::class, 'handleWebhookHandled']); }}
Register the subscriber in your EventServiceProvider:
The subscriber approach works well when your billing logic is concentrated in a single class. The individual listener approach scales better when different parts of your application (notifications, feature flags, analytics) each care about different events.