Skip to content
العربيةTalk to us
Engineering · 2 min read

What connecting 30+ carriers taught us about integrations

Every courier API is different until you decide to treat them all the same. Five lessons from building the carrier catalog behind our logistics platforms.

Every courier API is different until you decide to treat them all the same. Five lessons from building the carrier catalog behind our logistics platforms.

Our parcel and logistics platforms connect to more than 30 carriers and postal operators: booking, cancellation, rate inquiry and tracking, each through a different API. Some speak REST, some SOAP, some still exchange files on a schedule. The catalog only became easy to maintain when we stopped treating each integration as a project and started treating the catalog as a product.

Here is what changed.

1. Model the shipment once, map it many times

Every carrier has its own idea of what a shipment is. If those ideas leak into your core system, each new carrier makes the whole system harder to change.

We keep one shipment model that belongs to us, and each carrier gets a thin adapter that maps to it and from it. The core never sees a carrier's field names, status codes or quirks. Adding a carrier means writing a new mapping, not changing the platform.

2. Assume every call will be retried

Networks time out after the carrier has already acted. If a booking request times out and you simply try again, you can end up with two pickups for one parcel.

Every call that changes something carries a key that identifies the operation, so a retry is recognized as the same request, not a new one. Where a carrier offers no such support, the adapter checks whether the booking already exists before creating it.

3. Tracking is a stream, not a request

Some carriers push events through webhooks, others only answer when asked, and each uses its own status codes. We normalize them into a short list of statuses that operations teams actually use:

CREATED → PICKED_UP → IN_TRANSIT → OUT_FOR_DELIVERY → DELIVERED
↘ EXCEPTION → RETURNED

The original event is always kept next to the normalized one. When a customer disputes a delivery, the raw carrier record settles it.

4. Put the plumbing in middleware

Queues, retries, scheduled file transfers, webhooks and monitoring are the same problem for every carrier. Solving them again inside each adapter is where integration projects lose months.

That is why we built Bitween, our open-source integration middleware. It handles the messaging, transfers and retries once, so each adapter stays small and focused on mapping. Bitween is used by more than 10 clients handling millions of transactions a day.

5. Make failures visible to operations, not only to engineers

An integration that fails silently becomes a customer complaint days later. Every exchange is logged, failed messages can be replayed with one action, and a carrier that starts failing more than usual raises an alert before the backlog grows.

What this makes possible

With the model, the adapters and the middleware in place, a new carrier is mostly a mapping exercise. The same foundation carried our Amazon integration for a leading regional parcel and logistics firm, delivered ahead of its requirements and timeline.

If you run courier, postal or fulfilment operations and your integrations have become the bottleneck, we would be glad to compare notes.

  • Logistics
  • Integrations
  • APIs
  • Architecture
  • Bitween
Written by

Muhannad Khatib

Let's build what's next.

Tell us what you are working on. An engineer reads every message and replies within one business day.

Amman, JordanPrincess Tharwat Hassan St., Amman, Jordan
Dubai, UAEDubai Design District, Dubai, UAE