Skip to main content

Webhooks

Subscribd automatically registers a webhook endpoint for each configured gateway at /subscribd/webhook/{gateway}. Incoming payloads are verified, deduplicated, and translated into Laravel events that your application can listen to.

Endpoint URLs

GatewayEndpoint
Stripehttps://yourapp.com/subscribd/webhook/stripe
PayPalhttps://yourapp.com/subscribd/webhook/paypal
Braintreehttps://yourapp.com/subscribd/webhook/braintree
Paddlehttps://yourapp.com/subscribd/webhook/paddle
FastSpringhttps://yourapp.com/subscribd/webhook/fastspring
Squarehttps://yourapp.com/subscribd/webhook/square
All endpoints are automatically excluded from Laravel’s CSRF protection.

Signature verification

Subscribd verifies every incoming webhook signature before processing. Configure the appropriate secret for each gateway:
# Stripe
STRIPE_WEBHOOK_SECRET=whsec_...

# PayPal
PAYPAL_WEBHOOK_ID=...

# Braintree
BRAINTREE_WEBHOOK_SECRET=...

# Paddle
PADDLE_WEBHOOK_SECRET=...

# FastSpring
FASTSPRING_WEBHOOK_SECRET=...

# Square
SQUARE_WEBHOOK_SIGNATURE_KEY=...
Requests with invalid signatures receive a 403 response and are never processed. Do not disable signature verification in production.

Idempotency

Subscribd records every processed webhook event in subscribd_webhook_events. If a gateway retries delivery, the duplicate payload is detected by its event ID and acknowledged without reprocessing. This table is pruned automatically according to subscribd.webhook.retention_days (default: 30).

Events dispatched by webhook handlers

When a verified webhook payload is processed, Subscribd dispatches the corresponding Laravel event. Your listeners receive a fully hydrated local model — you do not need to interact with the gateway API inside your listener.
Gateway eventSubscribd event
Subscription created / activatedSubscriptionCreated
Subscription updatedSubscriptionUpdated
Subscription canceledSubscriptionCanceled
Subscription past dueSubscriptionPastDue
Trial ending soonTrialEndingSoon
Invoice paidInvoicePaid
Invoice payment failedInvoicePaymentFailed
Checkout completed (Paddle/FastSpring)SubscriptionCreated
See Hooks and Events for the full event reference and listener registration.

Configuring webhooks per gateway

Stripe

In the Stripe Dashboard, create an endpoint pointing to https://yourapp.com/subscribd/webhook/stripe and enable:
  • customer.subscription.created
  • customer.subscription.updated
  • customer.subscription.deleted
  • invoice.paid
  • invoice.payment_failed
  • invoice.payment_action_required
  • checkout.session.completed
Copy the Signing secret and set it as STRIPE_WEBHOOK_SECRET.

PayPal

In your PayPal Developer App, add a webhook for https://yourapp.com/subscribd/webhook/paypal. Enable:
  • BILLING.SUBSCRIPTION.CREATED
  • BILLING.SUBSCRIPTION.ACTIVATED
  • BILLING.SUBSCRIPTION.UPDATED
  • BILLING.SUBSCRIPTION.CANCELLED
  • PAYMENT.SALE.COMPLETED
  • PAYMENT.SALE.DENIED
Set the webhook ID as PAYPAL_WEBHOOK_ID.

Braintree

In the Braintree Control Panel under Settings > Webhooks, add https://yourapp.com/subscribd/webhook/braintree and enable:
  • subscription_charged_successfully
  • subscription_charged_unsuccessfully
  • subscription_canceled
  • subscription_expired
  • subscription_went_past_due
  • subscription_trial_ended

Paddle

In the Paddle Dashboard, create a notification destination for https://yourapp.com/subscribd/webhook/paddle and enable:
  • subscription.created
  • subscription.updated
  • subscription.canceled
  • subscription.paused
  • subscription.resumed
  • transaction.completed
  • transaction.payment_failed
Copy the Secret key and set it as PADDLE_WEBHOOK_SECRET.

FastSpring

In your FastSpring Dashboard under Developer > Webhooks, configure https://yourapp.com/subscribd/webhook/fastspring and enable:
  • subscription.activated
  • subscription.updated
  • subscription.canceled
  • subscription.deactivated
  • order.completed
  • order.failed
Set the HMAC Secret as FASTSPRING_WEBHOOK_SECRET.

Square

In the Square Developer Dashboard, configure https://yourapp.com/subscribd/webhook/square and enable:
  • subscription.created
  • subscription.updated
  • subscription.canceled
  • subscription.expired
  • invoice.payment_made
  • invoice.payment_failed
  • payment.completed
  • payment.failed
Copy the Signature Key and set it as SQUARE_WEBHOOK_SIGNATURE_KEY.

Local development

Use the Stripe CLI to forward Stripe webhooks to your local app:
stripe listen --forward-to http://localhost:8000/subscribd/webhook/stripe
The CLI outputs a webhook signing secret — set it as STRIPE_WEBHOOK_SECRET in your .env while developing locally. For other gateways, tools like ngrok or Expose can create a public tunnel to your local server.

Queue configuration

Webhook processing runs on the queue. Ensure your queue worker is running:
php artisan queue:work
All webhook jobs use the queue connection and queue name configured in subscribd.queue:
// config/subscribd.php
'queue' => [
    'connection' => env('SUBSCRIBD_QUEUE_CONNECTION', 'default'),
    'queue'      => env('SUBSCRIBD_QUEUE', 'default'),
],
For production, a dedicated billing queue is recommended:
SUBSCRIBD_QUEUE=billing

Replaying webhook events

Replay a previously received webhook event by its ID:
php artisan subscribd:webhook:replay {id}
This re-dispatches the stored payload through the full processing pipeline, including deduplication bypass. Useful for recovering from a failed listener or missed processing window.

Next steps

  • Hooks and Events — Full event reference and listener registration
  • Dunning — Automatic retry logic for failed payments