Skip to main content

Shipment Lifecycle

Every shipment moves through a state machine. The same statuses cover both same-city and regional deliveries — only the path differs.

State machine

PENDING
│ (transient — only seen if you use gateway payment instead of wallet)

CONFIRMED payment cleared, dispatch starts


PICKUP_DISPATCHED first-mile rider assigned, heading to sender


PICKED_UP rider has the package

├── (same-city) ──────────┐
│ │
▼ (regional) │
IN_TRANSIT │ hub-to-hub transit via bus partner
│ │
▼ ▼
OUT_FOR_DELIVERY last-mile rider heading to receiver


DELIVERED ✅

Terminal states: DELIVERED, CANCELLED, FAILED.

Status reference

StatusMeaningWhat happens
pendingJust created, awaiting paymentFor wallet shipments, this exists only for a fraction of a second before flipping to confirmed
confirmedPayment receivedAuto-dispatch begins — engine picks the nearest available rider
pickup_dispatchedRider assignedRider has the job in their app and is heading to the sender
picked_upRider has the packageSender's part is done
in_transitRegional only — hub-to-hubPackage is on a bus between cities
out_for_deliveryLast-mile rider heading to receiverFinal leg
deliveredSuccessfully deliveredTerminal — proof-of-delivery captured
cancelledCancelled before pickupWallet refunded
failedDelivery attempts exhaustedReturned or held for resolution

Same-city vs regional

StatusSame-cityRegional
pending
confirmed
pickup_dispatched
picked_up
in_transit(skipped)
out_for_delivery
delivered

Same-city shipments go directly from picked_upout_for_delivery. Regional shipments pass through in_transit while the package is on a bus between sorting hubs.

Journey legs

Each shipment has 1 or 3 legs — segments handled by different actors:

LegDirectionHandled byUsed in
first_mileSender → origin hub (or full route for same-city)RiderBoth
transitOrigin hub → destination hubBus partnerRegional only
last_mileDestination hub → receiverRiderRegional only

Legs appear in the legs array of every shipment response. Each leg has its own status (pending, in_progress, completed, failed) so you can show progress per segment in your UI.

Hub sub-events (regional)

Regional shipments pass through sorting hubs. These don't change the top-level status but are recorded in the events array:

Event descriptionWhen
Shipment received at {hub_name}Package checked in at origin hub
Package containerized for transitLoaded onto an outgoing container
Container dispatched via {partner}Bus departed
Container arrived at {hub_name}Bus arrived at destination hub
Last-mile rider assignedLocal rider picked up from destination hub

Use the events array on GET /merchant/shipments/{id} to surface fine-grained progress.

Webhook mapping

Each status transition fires a corresponding webhook. See Webhooks for payloads.

TransitionEvent
confirmedshipment.created, shipment.paid
picked_updelivery.picked_up
delivereddelivery.delivered
cancelledshipment.cancelled
faileddelivery.failed

Cancellation rules

Cancellable from: pending, confirmed, pickup_dispatched.

Not cancellable from: picked_up, in_transit, out_for_delivery, delivered, cancelled, failed.

Once the rider has the package, contact support for resolution.