## Real API Integration Is Harder Than Tutorials Make It Look
At Traviyo, I worked on three travel platforms — Airtravellab, MytoursPlan, and T2TWorld. One of the most complex challenges was integrating flight and bus APIs for real-time booking. Here's what I learned that no tutorial will tell you.
## The Basic Flow (What You Think It Is)
User searches → Call API → Show results → User books → Done
User searches → Call API → Show results → User books → Done
## The Actual Flow (What It Really Is)
User searches → Call API (may timeout) → Handle rate limits → Cache results → Show results → User selects → Reprice (prices change!) → Initiate booking → Handle partial failures → Confirm → Send tickets → Handle cancellations → Process refunds
See the difference?
## Challenge 1: API Response Time
Flight APIs are slow. A search request can take 3-8 seconds. You cannot make users stare at a blank screen.
**Solution: Async loading with progress indicators**
```csharp
public async Task<IActionResult> SearchFlights(FlightSearchModel model)
{
// Start search, return immediately with a search token
var searchToken = Guid.NewGuid().ToString();
_ = Task.Run(() => FetchAndCacheFlights(searchToken, model));
return Json(new { searchToken });
}
// Client polls this endpoint
public async Task<IActionResult> GetSearchResults(string searchToken)
{
var results = await _cache.GetAsync<FlightResults>(searchToken);
if (results == null)
return Json(new { status = "processing" });
return Json(new { status = "complete", data = results });
}
```
## Challenge 2: Price Changes
Flight prices change every few minutes. A price shown at search time may not be available at booking time.
**Solution: Always reprice before booking confirmation**
```csharp
public async Task<BookingResult> InitiateBooking(BookingRequest request)
{
// Never trust cached price
var currentPrice = await _flightApi.GetCurrentPrice(request.FlightId);
if (currentPrice != request.QuotedPrice)
{
return new BookingResult {
Status = "PriceChanged",
NewPrice = currentPrice,
Message = "Price has changed. Please confirm new price."
};
}
// Proceed with booking
}
```
## Challenge 3: Handling API Failures Gracefully
Third-party APIs go down. Your system should not go down with them.
```csharp
public async Task<FlightResults> SearchWithFallback(SearchModel model)
{
try
{
return await _primaryApi.Search(model);
}
catch (ApiException ex) when (ex.StatusCode == 503)
{
_logger.LogWarning("Primary API down, trying fallback");
return await _fallbackApi.Search(model);
}
}
```
## Challenge 4: Caching Strategy
You can't call the API on every user interaction — rate limits and cost make that impossible.
**What I cached:**
- Search results: 5 minutes (prices change fast)
- Airport/city data: 24 hours (static)
- Airline logos and info: 7 days (rarely changes)
## Results After Proper Implementation
- Booking efficiency improved by 25%
- API timeout errors reduced by 80%
- User drop-off during search reduced significantly
## Key Takeaways
1. Always handle the "what if API is down" scenario
2. Never trust a cached price at booking time
3. Log every API call with request/response for debugging
4. Implement retry logic with exponential backoff
5. Rate limiting from your side prevents API bans
## Conclusion
API integration is where senior developers and junior developers show the biggest difference. The basic call is easy — handling every failure mode gracefully is the actual skill. Build for failure, and success takes care of itself.