Skip to content
Kien

The shape of integration work

· 5 min read

"So you call other people's APIs" is the usual summary of my job, and it is wrong in an instructive way. Around 150 supplier codes on about 90 integrations, two documented offer patterns, two execution models behind one public contract, and suppliers that answer 200 with an error inside — a tour of what the work actually consists of, and why it is architecture.

  • integrations
  • architecture
  • API design
  • distributed systems
On this page
  1. The numbers first
  2. One contract, ninety opinions
  3. Two ways to say "a room"
  4. Two execution models behind one door
  5. The part nobody advertises
  6. Why this is architecture

When I describe my job, the reply I get most often is some polite version of "so you call other people's APIs". It is technically true the way "a compiler reads text files" is technically true. I want to write down the actual shape of the work, because the shape is the argument.

The numbers first

The platform I work on aggregates travel suppliers across five product lines — hotel, flight, tour, transfer, car hire. Roughly 150 supplier codes run on about 90 distinct integrations; on the hotel side alone, 75 codes sit on 31 modules. The gap between those two numbers is white-labelling: one integration resold under many brand codes, with the differences held in configuration rather than forked code.

If integration work were "calling an API", those would be counts of API calls. They are not. They are counts of opinions — 90 different opinions about what a room is, what a price is, what an error is, and what "yes" means — that all have to answer one question through one contract.

One contract, ninety opinions

The first structural decision: every supplier gets exactly one module, written against a fixed contract, and the module is registered by its code in a single registry. The point is not tidiness. The point is that when a supplier is wrong — and one of ninety is always wrong — the difference between that supplier and everyone else lives in one file. You do not go hunting for where supplier-specific behaviour leaked into shared code, because the contract made that leak a compile-time-shaped problem instead of an archaeology problem.

Two ways to say "a room"

You might expect the room-and-rate model to be the easy part. It is where the deepest fork lives. There are two documented offer patterns, because the suppliers' models genuinely differ and no amount of mapping makes them the same thing:

In pattern A, the supplier returns a single token that books N rooms — one offer, one confirmation, done. In pattern B, each room's rate is independent, and an "offer" for a two-room search does not exist until we materialise it: the offer list is the computed matrix of valid combinations. Same search, same screen, and underneath, one supplier is selling you an object while another is selling you the parts of one.

Pretending these are one pattern produces bookings where room two silently gets room one's rate. Documenting them as two, and forcing every new integration to declare which one it is, is a design decision — the kind that never shows up in a demo.

Two execution models behind one door

Protocols range from JSON over HTTP to SOAP/XML; the XML side is mapped with camaro and xmlbuilder rather than a DOM walk, because at search volume the parser is a cost centre. But the bigger split is temporal.

Hotel, flight and car search are asynchronous: a queue, one job per supplier, each guarded by a Redis lock, workers writing results into a shared cache hash plus a meta hash that marks completion. The HTTP layer aggregates whatever has landed and reports a progress fraction, under an absolute 30-second deadline — after that, whoever has not answered is not in the results. Tour and transfer search are synchronous: a single server process, no worker, no polling.

The client sees neither. Both models sit behind the same public API contract. That sentence is short and cost a great deal, because "the same contract" means the async side has to answer questions the sync side never faces — what does "half done" look like, what happens to the supplier that answers at second 31 — and the answers must be invisible from outside.

The part nobody advertises

Here is the honest centre of the job: most of the work is deciding what to do when the other side is wrong, slow, or silent.

Suppliers answer 200 with an error body — a success status wrapping a failure, which means the transport layer's opinion of the call is worthless and every response needs a second, supplier-specific reading. Suppliers time out at exactly the moment money is in flight, leaving you to decide whether a booking exists. Suppliers return prices that disagree with the prices they returned one search earlier. None of this is an edge case; at 90 integrations it is the weather. I have not counted what fraction of integration code handles the unhappy paths versus the happy one — so I will not put a number on it — but the happy path is the part you finish first and think about least.

One more structural choice belongs here: cross-call state rides inside a composite versioned offer identifier — source, contract, hotel, uuid — decoded at prebook. No server-side session. Every fact the next step needs travels inside the ID the client already holds, which means a prebook can land on any instance, survive a deploy in the middle of a customer's checkout, and be debugged from the identifier alone.

Why this is architecture

Look back at the list: a fixed contract with one module per opinion; two offer patterns instead of one false one; two execution models behind one public face; error semantics rebuilt on top of a transport that lies; state packed into an identifier instead of a session. Not one of these is "calling an API". Every one of them is a boundary — a line where somebody decided what the rest of the system is allowed to assume, and accepted responsibility for the cases where that assumption breaks.

Plumbing moves water that behaves like water. This job federates ninety parties who each behave differently, and makes them answer one question, within 30 seconds, in one shape. The pipes are the easy part.

Related posts

· 4 min read

In most systems the expensive test outcome is red. In a booking system it is green — a passing test just bought something. How the full flow gets tested anyway: a selection rule that doubles as the safety mechanism, and an evidence pack, not a checkmark, as the thing partners actually review.

  • testing
  • integrations
  • QA
  • evidence

· 5 min read

Not the integration mechanics — the domain underneath them. Inventory that changes between search and book, prices with a shelf life, cancellation policies that are data rather than a flag, five product lines whose shapes genuinely differ, and supply that is other companies. The hard part is what you are selling, not how you call it.

  • travel tech
  • domain modelling
  • distributed systems
  • architecture