## 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

## 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.