The endpoint, with secret populated. This is the only response that ever carries it: every later read returns secret_fingerprint instead. Store the secret when you get it. If you lose it, rotate.
Leave enabled_events off and the endpoint receives everything. Rotation keeps the previous secret valid for 24 hours, so you can deploy the new one without dropping deliveries signed with the old.
!
Verify every payload. Compare the BillKit-Signature header against this endpoint’s secret before
trusting the body.
Test it
Point the endpoint at a tunnel, or skip registration entirely and forward deliveries straight to localhost with billkit listen.
<?phpnamespace App\Listeners;use BillKit\Laravel\Events\WebhookReceived;// The package registers POST /billkit/webhook and verifies the// signature before dispatching this event.class HandleBillKitWebhook{ public function handle(WebhookReceived $event): void { if ($event->payload['type'] === 'invoice.payment_failed') { Dunning::start($event->payload['data']['customer_id']); } }}
Request · React
// Webhooks are server to server, and the signing secret must never// reach a browser. Handle the event on your backend and let the page// read the state your own API exposes afterwards.