The Confirmation Desk

Reconciling Bookings When the Confirmation Never Arrives

Polling and webhooks both fail silently—here's how to catch them when they do.

Reporter · · 7 min read · Updated
Cover illustration for “Reconciling Bookings When the Confirmation Never Arrives”
Features · August 19, 2026 · 7 min read · 1,525 words

A booking gets submitted, the airline or hotel or rental car company takes its sweet time, and your system sits there with a request in limbo. No confirmation, no rejection, just silence. This piece is about what you actually do when that silence hits: how to poll for it, when to trust a webhook, and where to set the timeout clock before you either double-book a customer or leave money on the table.

Anyone who's built against a reservation API knows the happy path is a lie we tell in documentation. Request goes out, confirmation comes back in 200 milliseconds, everybody claps. Real systems don't work that way. Airlines batch things through GDS systems that were designed when disco was still cool. Rental car companies proxy through three vendors before your request even hits their inventory system. And "asynchronous" in an API spec often just means "we'll get back to you, maybe, eventually, no promises."

Polling: the annoying cousin who keeps texting "you up?"

Polling is the simplest fix and the one everyone reaches for first. You fire off a request, get back a reservation ID, and then ask "is it done yet?" every few seconds until someone answers.

I once inherited a booking system that polled a rental car vendor every second, flat, no backoff, for up to ten minutes per reservation. Nobody had touched the code in two years because it "worked." What it actually did was rack up enough API calls that the vendor throttled our account during a holiday weekend, which is a genuinely fun thing to discover on a Friday night. Polling without discipline is just an expensive way to ask the same question until someone gets annoyed enough to answer.

A few things make polling tolerable instead of wasteful:

  • Exponential backoff. Don't poll every second for ten minutes straight. Start at 2 seconds, then 4, then 8, capping somewhere around 60 seconds. Most reservation systems resolve within the first minute or two anyway, so you want density early and patience later.
  • A hard ceiling. Pick a number, say 15 or 20 polls, and stop. If the answer hasn't come by then, you're not looking at a slow confirmation, you're looking at a stuck one.
  • Jitter. If you've got thousands of bookings polling at the same intervals, you'll create a thundering herd against the vendor's API. Add some randomness (plus or minus a few hundred milliseconds) so your requests don't all land in the same second.

The real cost of polling is the false negatives. You poll, get "pending," poll again, get "pending," and on the fourth check you finally see "confirmed." Except the reservation actually confirmed on check number two. You just didn't ask fast enough. That gap between "vendor knows" and "you know" is where inventory mismatches live.

Webhooks: the confirmation that's supposed to just show up

Webhooks flip the model. Instead of you asking, the vendor tells you, the second something changes. This can mean less compute, less latency, less awkward silence.

In practice, webhooks are the friend who says "I'll call you" and then doesn't, because their phone died, or your phone number changed, or there was a system outage nobody warned you about. I've watched a supposedly "instant" webhook take 40 minutes to fire because a message queue on the vendor's end backed up during a regional outage. The booking had confirmed. Nobody told us for the better part of an hour.

So webhooks need three things polling doesn't:

Idempotency keys. Vendors retry webhooks that they think failed, even when your server processed them fine and just took too long to send back a 200. Without a way to recognize "I've already seen this exact confirmation," you'll double-process it, and now the customer's reservation email arrives twice, or worse, you double-charge them.

A dead man's switch. If you haven't heard from a webhook in a reasonable window (say, five minutes for something that usually confirms in 30 seconds), you fall back to polling. Treat the webhook as the primary channel and polling as the backup generator that kicks in when the power's out.

Signature verification. Anyone can send a POST request to your webhook endpoint pretending to be a booking vendor. Verify the signature, or you're accepting confirmations from strangers. Trusting an unsigned webhook is like trusting a stranger who calls claiming to be your bank — technically possible they're legit, but you're not wiring money on that basis.

Timeout policy: deciding when "still waiting" becomes "never happening"

This is the part nobody wants to own, because setting a timeout means admitting you'll sometimes be wrong. Too short, and you cancel bookings that would've confirmed 10 seconds later. Too long, and you've got a customer staring at a spinner while their flight fills up with other people's seats.

There's no universal number here, and anyone who tells you "always timeout at 30 seconds" hasn't worked with rental car aggregators. What matters is matching the timeout to the vendor's actual behavior, not some spec sheet number. A few principles that hold up across most reservation systems:

Set your timeout based on the vendor's observed 95th or 99th percentile response time, not their advertised average. Averages lie. If a vendor says "confirmations typically arrive in 3 seconds" but their 99th percentile is 45 seconds, and you time out at 10, you're going to nuke a lot of perfectly good bookings. Pull the actual distribution from your logs after a few weeks of live traffic and set the timeout at the tail, not the middle.

Separate "timeout" from "failure." When a reservation request times out, that means you don't know, and that's a big difference from a real failure. A timed-out booking might still confirm on the vendor's side five minutes later, and if you've already told the customer "sorry, didn't work" and released the inventory, you're now dealing with a phantom reservation nobody's tracking. The fix: put timed-out requests into a "pending reconciliation" state, not a "failed" state, and keep checking (via polling) for a longer window, maybe 30-60 minutes, before you give up for good.

Build a reconciliation job that runs independently of the live booking flow. Every so often, sweep through anything sitting in "pending" past its expected window and check status directly against the vendor, outside of the webhook or polling flow that already gave up on it. Think of this as the overnight audit that catches what the daytime shift missed. It's unglamorous work. It's also the only thing standing between you and a customer who shows up at a rental counter with a confirmation email for a car that was never actually reserved.

The strategy that actually works: run both, trust neither fully

Pure polling is slow and wasteful. Pure webhooks are fast until they're not, and when they fail, they fail silently. The systems that handle this well treat webhooks as the express lane and polling as the safety net underneath it, and they never assume either one is telling the whole truth on its own.

Here's the pattern, roughly:

  1. Submit the booking, get a reservation ID, and start listening for a webhook immediately.
  2. Kick off a polling loop in parallel with backoff, but don't check aggressively for the first 10-15 seconds, since a webhook is likely to beat it anyway.
  3. Whichever channel reports a status first wins, but always cross-check against the vendor's direct API before finalizing, especially for anything involving payment capture.
  4. If both channels go quiet past your timeout window, move to "pending reconciliation" instead of "failed."
  5. Run the reconciliation sweep on a schedule (every 5-10 minutes for active pendings) until you either get a real answer or hit an outer boundary, like 24 hours, where a human has to look at it.

That last step matters more than people think. At some point, an unresolved booking stops being an engineering problem and becomes a customer service one. Somebody needs to call the airline. Automating your way out of every edge case is a nice ambition, but reservation systems built by different companies, on different tech stacks, with different definitions of "confirmed," will occasionally require a human to pick up a phone. That's just Tuesday in the travel industry.

Q: How do you know when a distributed booking system is finally at peace with itself? A: When "pending" stops feeling like a threat and starts feeling like an honest answer.

Why this actually matters

Get the timeout wrong and you'll cancel real reservations while telling customers they're confirmed for something that never happened. Get the reconciliation wrong and you'll double-book a hotel room the same week it hosts a wedding and a business conference. Neither mistake shows up in a load test. Both show up in a review with one star and a full paragraph of well-earned rage.

The fix requires accepting that "asynchronous" means the vendor's silence is data too, and building a system that treats "we don't know yet" as a real state, not a bug to be papered over. Polling, webhooks, and timeouts are one problem, wearing three different hats, and the moment you stop treating them as interchangeable, your bookings stop ghosting your customers.

More in Features