Gozem Developer DocsDocs

A trip moves through a defined set of statuses from the moment you book it to the moment it is delivered, canceled, or expired. This page lists every status, what triggers each change, which states are terminal, and the full set of webhook events the Courier API emits. The status field on a trip always holds its current state.

Statuses

Each status change fires the matching webhook event. Subscribe to the events you need when configuring a webhook in the Partner Portal; each event’s data object holds the resource the event is about. The envelope and signature verification are covered in the platform Webhooks guide.

Status Meaning Webhook event
pending Trip created, waiting for a driver to be assigned courier.trip.created
assigned A driver is available and on the way to pickup; driver details are now available courier.trip.assigned
at_pickup The driver has arrived at the pickup location courier.trip.at_pickup
started Pickup is done and the driver is delivering courier.trip.started
completed All dropoffs delivered; the trip is finished courier.trip.completed
canceled The trip was canceled by you, the driver, or the system courier.trip.canceled
expired No driver was assigned within the acceptance window courier.trip.expired

The usual order

A delivery that goes smoothly progresses from pending to completed. From any active state before delivery it can also be canceled, and a trip that is never accepted expires.

Trip status transitionsA trip starts as pending, then moves through assigned, at_pickup and started to completed. From pending, assigned or at_pickup it can instead become canceled. A pending trip that is never accepted becomes expired. Completed, canceled and expired are terminal.pendingassignedat_pickupstartedcompletedexpiredcanceled
Terminal states are outlined: a trip in completed, canceledor expired does not change again.

Multiple dropoffs

A trip can have more than one dropoff. While the trip is started, the driver works through the dropoffs in order, and each stop emits its own events as it begins and finishes:

courier.trip.stop.started    → driver is heading to a dropoff
courier.trip.stop.completed  → that dropoff was delivered

The trip stays started across all the intermediate stops and moves to completed only once the final dropoff is delivered. These stop events fire once per dropoff, including on a single-dropoff trip, where you see exactly one pair between started and completed. If you only handle single-dropoff deliveries, you can rely on started and completed alone and treat the stop events as optional detail.

Note: The stop events always fire, even for a single dropoff, because they carry per-destination delivery detail, such as which dropoff was served and its delivery confirmation. Firing them on every trip means you handle one and many dropoffs with the same code path, and gives you a single, consistent place to capture proof of delivery per destination.

Terminal and cancelable states

completed, canceled, and expired are terminal. A trip in any of these states does not change again, and trying to cancel one is rejected with a 409 Conflict.

A trip can be canceled while it is still pending, assigned, or at_pickup, using POST /courier/v1/trips/:trip_id/cancellation. A trip that is never accepted moves to expired on its own.

Following the lifecycle

In production, the reliable way to follow these transitions is webhooks: subscribe to the Courier trip events and react as each fires. You can also read the current state at any time with GET /courier/v1/trips/:trip_id. For the delivery mechanism and signature verification, see the platform Webhooks guide.

Webhook events

The status-transition events are listed in the Statuses table above (courier.trip.created through courier.trip.expired). In addition, the Courier API emits the per-dropoff, messaging, and payment events below.

Per-dropoff events

courier.trip.stop.started — The driver is heading to one of the trip’s dropoffs. Fires once per dropoff, including on a single-dropoff trip.

courier.trip.stop.completed — A dropoff was delivered. Fires once per dropoff as each delivery is completed, including on a single-dropoff trip.

Messaging events

courier.trip.chat.message — A new message was sent in the trip chat between the client and the driver. Use it to sync conversation activity or trigger a notification.

Payment events

courier.trip.payment.completed — Payment for the trip was processed successfully.

courier.trip.payment.refunded — A refund was issued against the trip’s payment.

In sandbox

Sandbox has no live drivers, so a booked trip stays at pending and none of these transitions happen on their own. To move a sandbox trip through its lifecycle and generate the matching events, use the sandbox testing tools provided with your sandbox access — see Testing the full lifecycle in sandbox. They are the only way to reproduce driver activity in sandbox.