paypal webhook PAYMENT.SALE.COMPLETED never arrives for a billing agreement
Diagnoses missing PayPal PAYMENT.SALE.COMPLETED webhooks for billing agreements. Use when renewals happen but your webhook endpoint never fires, or when you need a polling fallback. Not for missing webhooks on one-time payments, delayed webhooks on other event types, or IPN issues.
PayPal webhook PAYMENT.SALE.COMPLETED never arrives for a billing agreement
TL;DR
When the webhook never fires for billing-agreement sales, the cause is usually subscription config: the event type is not subscribed on your webhook, or the sale is reported under a different event name. Verify your webhook subscriptions in the developer dashboard, use the webhooks simulator to prove your endpoint works, and add a polling fallback so renewals are never silently missed.
paypal webhook PAYMENT.SALE.COMPLETED never arrives for a billing agreementSteps
- In the PayPal developer dashboard, open your webhook's event subscriptions and confirm the sale-related events are checked. Success check: the subscription list includes the events you expect for billing-agreement sales.
- Check you are looking at the right environment: sandbox webhooks only fire for sandbox transactions, live for live. Success check: the missing sale and the webhook config are in the same environment.
- Use the webhooks simulator to send a test event to your endpoint. Success check: your endpoint receives it and returns 200, proving the URL, TLS, and handler work.
- Look up the actual sale in the PayPal dashboard or via the transaction APIs and confirm it completed. Success check: you have a completed sale with a timestamp that should have produced a webhook.
- Add a polling fallback: on a schedule, list recent billing-agreement transactions and reconcile any sale your webhooks missed. Success check: a deliberately dropped webhook is caught by the poller within one cycle.
When this applies
- Billing-agreement renewals complete but PAYMENT.SALE.COMPLETED never hits your endpoint.
- An agent-built integration relies solely on webhooks for renewal fulfillment.
- You need a belt-and-suspenders design for PayPal recurring revenue.
When it doesn't
- One-time payment webhooks are missing; check the same subscription list but the event names differ.
- You are still on IPN; that is a separate legacy system with its own debugging.
- Webhooks arrive late but do arrive; that is latency, not loss.
Tool + version compatibility
PayPal webhooks v1, PayPal Subscriptions API / billing agreements, developer dashboard webhook simulator.
"paypal subscription webhook not received"
Same checklist. Start with event subscriptions and environment mismatch; those two cover most cases.
"paypal billing agreement no ipn webhook"
If you migrated from IPN, make sure the old IPN listener is not the thing you are watching; webhooks and IPN are separate channels.
"paypal sale completed event missing"
Verify the sale actually completed first (step 4). No sale, no event.
Why it happens
Billing-agreement sales flow through PayPal's subscription engine, and the events they emit depend on your webhook's subscription list. Agent-generated integrations often subscribe to the obvious payment events during setup and miss the subscription-specific ones, or they test in sandbox while watching the live endpoint. Either way the sale happens and the webhook is never sent, so the integration looks broken when it is just misconfigured.
Edge cases / pitfalls
- PayPal may retry a failed webhook delivery for a while, then stop; a 200 from your endpoint on a half-processed event still counts as delivered, so make handlers idempotent.
- Event names have changed across PayPal API generations; confirm the exact event name your integration expects against the current docs.
- The simulator proves your endpoint works but does not prove your subscription list is right; do both checks.
- Reconciliation polling should be idempotent too: never fulfill the same sale twice because the poller and a late webhook both saw it.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_3IhJh2tBvcJcJkG5DtE9Ww