Symptoms / Fix guide

A customer paid, but the order is not in my CRM. Why?

Matt Turley, Continuum. Updated November 5, 2026.

For founders who can see the payment in Stripe but not the contact, deal or order in HubSpot, GoHighLevel, Pipedrive, Airtable or whatever stores their customers.

The short answer

A customer paid, but the order is not in my CRM. Why?

The payment and the CRM record are two separate events joined by code, and one hop silently failed. Trace one real paid order through three places: the Stripe event, your webhook handler logs and the CRM API response. The first place it stops is the cause, and usually the webhook did not run, the handler swallowed an error, or the CRM call was rejected.

What is really going on

Nothing connects a Stripe payment to your CRM except code that someone wrote. The chain has at least four hops: Stripe takes the payment, Stripe sends an event to your server, your server decides what the event means, and your server calls the CRM's API. Any hop can fail without the others noticing, and a failure in the last two usually produces no visible error at all.

The most dangerous version is the quiet one: the handler catches an error, logs it and returns success. Stripe sees a 200 and never retries, the customer has paid, and the only trace is a line in a log nobody reads.

Because it depends on a chain, the fix is rarely one line. It is making each hop observable, and then making the chain able to recover from a failure at any hop.

Where the chain usually breaks, most common first

  1. The record is created from the browser, not from the webhook

    How to tell The CRM write happens on the checkout success page. Customers who pay and close the tab, lose connection or use a payment method that redirects elsewhere never reach it, so some orders are missing and the missing ones look random.

    The fix Create the record from the server when Stripe confirms the payment (checkout.session.completed or the event for your flow). Keep the success page as a display only.

  2. The webhook never ran

    How to tell The payment is in Stripe, but the endpoint's delivery log shows no attempt, a redirect, a 401 or a 400. Our page on webhooks that do not fire covers each.

    The fix Fix delivery first, then resend the failed events from the Stripe Dashboard so every paid order gets its record.

  3. The handler swallows the error and returns success

    How to tell The handler has a try/catch that logs and returns 200. The delivery log is all green and the CRM is still missing records.

    The fix Return a 5xx for failures you want retried, and write the unfinished work to a durable record (a database row marked pending) so it can be retried even after Stripe stops.

  4. The CRM rejects the request

    How to tell The CRM's API returns 401 (token expired or revoked), 400 (a required field is missing, a dropdown value does not exist, a phone number has the wrong format), 409 (the contact already exists) or 429 (rate limited). The handler never looks at the response.

    The fix Check and log the response status and body for every CRM call. Refresh tokens before they expire, upsert by email instead of blindly creating, and respect rate limits with a retry.

  5. The order cannot be matched to a person

    How to tell Guest checkouts have no Stripe customer, the buyer used a different email than the one on your lead, or the metadata you expected is empty. The CRM write has nothing to match on and creates nothing or the wrong contact.

    The fix Pass your own identifier when you create the checkout session (client_reference_id or metadata), and use it, plus a normalised email, to find or create the contact.

  6. Duplicates and retries are not handled

    How to tell Some orders appear twice, others not at all. Stripe can deliver an event more than once, and a retry of a half-finished handler can repeat the side effects or skip them.

    The fix Store the event id (or checkout session id) and make the whole handler idempotent: processing it twice has the same result as processing it once.

How we diagnose it

  1. Pick one real paid order that is missing. Take a single payment from the last few days. Everything else is guesswork; one traced order shows exactly where the chain stops.
  2. Find its Stripe event and its delivery. Look up the payment in Stripe, open its event, and read the delivery attempts to your endpoint and their response codes.
  3. Find the same event in your logs. Search the production logs for the Stripe event id or the checkout session id and read every line your handler wrote for it, including the swallowed ones.
  4. Find the CRM API call and its response. Look for the outgoing request to the CRM and its status and body. If there is no log line for it, the handler never made the call, which is a finding in itself.
  5. Reconcile in bulk. List the payments for a date range and the matching CRM records, and diff them. That gives the size of the problem and the full list of customers to repair.

What fixing it changes

  • The CRM record is created by the server from the payment event, not by the browser.
  • Every hop logs its outcome with the event id, so a missing order can be traced in minutes.
  • Failed work is stored and retried instead of being lost, and duplicates are harmless.
  • A scheduled reconciliation compares Stripe payments with CRM records and alerts on any gap.
  • Every historical order that was missed is backfilled.

When you do not need us

If it is one order, check whether the buyer used a different email and add the record by hand. If it is a pattern, and especially if orders have been missing for weeks, the fix is a redesign of how the handler works plus a backfill, and that is worth paying for because money and customer trust are involved.

Your next step

A Ship Check reads the checkout, the webhook handler and the CRM integration together and ranks what will break first. If the chain needs rebuilding, a Ship Fix is the fixed-scope job that does it, and a Ship Check is credited against it.

Ship Check, $299: A senior engineer reads your codebase and sends a written verdict (fine, fixable or rewrite), what will break first, a security and data read, and a costed plan, within 48 hours of repo access or it is free. It has a 7-day money-back and is credited against a Ship Fix. Or: See Ship Fix, $4,000 to $15,000.

Get a Ship Check, $299 →See all services and prices →
FAQ

Straight answers

Why do only some orders go missing?
Intermittent loss points to something that depends on timing or on the customer: the success page not loading, a handler timeout, a rate limit or a mismatched email. A systematic miss points to a configuration fault such as a wrong signing secret.
Can I just use Zapier or a native integration instead?
Often that is the right call. A maintained connector handles retries and field mapping for you. Custom code is justified when you need logic the connector cannot express, and then it must be built to retry and to be observable.
How do I recover orders that were already missed?
List Stripe payments for the affected dates, compare them with the CRM, and create the missing records from the payment data. Resending failed events from Stripe also works if the handler is now correct and idempotent.
Keep reading
Why is my Stripe webhook not firing?By symptom. Stripe is usually sending the event and your server is refusing it. How to read the delivery log, the six usual causes, and the fix for each.What breaks in an AI-built e-commerce store?By vertical. Online stores built with AI tools: prices set in the browser, overselling, webhooks, tax, refunds and card data scope. What breaks and how to test it.What breaks in an AI-built marketplace app?By vertical. Two-sided marketplaces built with AI tools: seller onboarding, payouts, fees, refunds, disputes and who sees whose data. What breaks and how to test it.My app broke right after launch. What do I do first?By stage. The first hours after a launch goes wrong: stop the damage, find the failure, protect users and data, then make it stable. What usually breaks, in order.What should I check before launching my AI-built app?By stage. A launch-week checklist for apps built with AI tools: who can see whose data, secrets, the real payment path, email, backups, monitoring and a rollback plan.Why is my app a white screen after a Vercel deploy?By symptom. A white screen after deploy means the page JavaScript failed or its files did not load. How to read the console, the usual causes, and the fix for each.
Sources
  1. 1. Stripe: Fulfill orders, Stripe: Why fulfilment should be driven by webhook events rather than the redirect page.
  2. 2. Stripe: Webhooks, Stripe: Retries, resending events and duplicate deliveries.
  3. 3. Stripe: Idempotent requests, Stripe: The idempotency pattern that makes a repeated operation safe.
A customer paid, but the order is not in my CRM. Why?