Payment confirmed. Customer experience broken. That gap — between what the payment provider sees and what your customer experiences — is where support tickets pile up and engineers get paged at 11 PM.
The failure pattern
A payment event succeeds on the provider side, but the expected app-side effect never completes.
invoice.paidfired — credits were not added to the accountcheckout.session.completedfired — access was never unlockedorders/paidcame in from Shopify — your app never applied the fulfillment effect- A queue job was accepted — but no outcome ever came back
- A recoverable failure happened entirely after payment delivery had already succeeded
These failures are invisible to Stripe and Shopify. The payment provider delivered the event and considers its job done. The gap is entirely on the app side, which means your payment logs will not help you find it.
Why this happens
Payment providers recommend accepting webhook events quickly and processing the business effect asynchronously. That pattern is correct — but it means the actual fulfillment happens after your 200 response, outside the provider’s visibility.
Common causes:
- Queue workers are down when the job is picked up
- App jobs fail after durable acceptance
- Database writes break after the event is acknowledged
- Webhooks arrive more than once and an idempotency bug prevents re-processing
- Tenant or account records do not exist yet at fulfillment time
None of these show up as failures in Stripe or Shopify delivery logs. The provider sees a 200. Your customer sees a broken product.
The SendPromptly recovery workflow
SendPromptly instruments the gap between payment delivery and app-side fulfillment using two signals in your existing webhook handler.
- Your app receives and verifies the event signature
- Your app durably accepts the work (enqueues job)
- Your app signals SendPromptly that the event was accepted
- Your app attempts the business effect (credits, access, or another paid-linked effect)
- Your app signals SendPromptly with success or failure
- If the outcome is missing after the timeout (default 30 minutes) or reports failure, SendPromptly opens an incident
- Your team reviews the incident timeline in the console
- Your team clicks Reprocess — SendPromptly POSTs a signed callback to your repair endpoint
- Your repair endpoint runs your idempotent repair logic
- A success outcome is reported — incident resolves
The audit trail stays available after resolution. A shareable proof link lets you send a customer or support contact a read-only view of the incident timeline without granting console access.
Why this is different from webhook monitoring
Webhook monitoring tells you whether an event reached your endpoint. SendPromptly tracks whether the payment produced the app-side result the customer expected.
| What it measures | Provider logs | SendPromptly |
|---|---|---|
| Event reached your endpoint | ✓ | ✓ |
| Your app returned 200 | ✓ | ✓ |
| Business effect was applied | ✗ | ✓ |
| Incident opened on failure | ✗ | ✓ |
| Safe repair with audit trail | ✗ | ✓ |
| Shareable proof link | ✗ | ✓ |
What recovery should not require
- Manual database edits under pressure
- Guessing intent from payment logs
- Searching queue failures across three systems
- Re-running scripts you are not sure are safe to run twice
- Asking the customer to wait while you investigate
Supported payment providers
Stripe — checkout.session.completed, invoice.paid, customer.subscription.deleted, customer.subscription.updated, charge.refunded, charge.dispute.created
Shopify — orders/paid, orders/fulfilled, customers/create, checkouts/create
Additional payment providers are on the roadmap. If your provider is not listed, contact us.
Get started
Start with the payment path that already generates the most support tickets. You can instrument one flow in an afternoon.
- Developer quickstart — step-by-step integration guide
- What SendPromptly catches — full list of supported failure types
- Pricing — Starter at $29/month, 14-day trial