Skip to main content

Manage Shipments

Once a shipment is created, use these endpoints to list, inspect, and cancel.

List shipments

GET /merchant/shipments

Returns your shipments, most recent first.

curl "https://api.dodo.co.tz/api/v1/merchant/shipments?status=delivered&page=1&per_page=20" \
-H "X-API-Key: $DODO_API_KEY"

Query parameters:

ParamTypeDescription
statusstringFilter by shipment statuspending, confirmed, pickup_dispatched, picked_up, in_transit, out_for_delivery, delivered, cancelled, failed
typestringsame_city or regional
searchstringMatch against shipment_number, tracking_code, or merchant_reference
pageintegerPage number (default: 1)
per_pageintegerPage size (default: 20, max: 100)

Response (200 OK):

[
{
"id": 12345,
"shipment_number": "SHP-20260515-A1B2C3",
"tracking_code": "DODO7K9M2P4QR8",
"merchant_reference": "your-internal-order-id-123",
"type": "same_city",
"status": "delivered",
"sender_name": "Malaika Restaurant",
"receiver_name": "Jane Doe",
"pickup_address": "Samora Ave, Dar es Salaam",
"dropoff_address": "Apartment 4B, Msasani, Dar es Salaam",
"total_amount": 4100,
"payment_status": "paid",
"estimated_delivery_at": "2026-05-15T11:30:00Z",
"created_at": "2026-05-15T10:30:00Z"
}
]

The list endpoint returns the trimmed list-view object — call Get details for items, legs, and the event log.

Get shipment details

GET /merchant/shipments/{id}

Full shipment record including items, journey legs, and the complete event log.

curl https://api.dodo.co.tz/api/v1/merchant/shipments/12345 \
-H "X-API-Key: $DODO_API_KEY"

The response shape matches the POST /merchant/shipments response, but with up-to-date status and a populated events array.

Event log

events is the timeline of what happened to this shipment. Use it to display delivery progress in your UI when you can't easily wire up webhooks.

"events": [
{
"id": 102,
"status": "delivered",
"leg_type": "first_mile",
"description": "Package delivered to Jane Doe",
"location_address": null,
"actor_type": "rider",
"occurred_at": "2026-05-15T11:28:14Z"
},
{
"id": 101,
"status": "out_for_delivery",
"leg_type": "first_mile",
"description": "Rider James M. heading to receiver",
"actor_type": "rider",
"occurred_at": "2026-05-15T11:05:42Z"
},
{
"id": 100,
"status": "picked_up",
"leg_type": "first_mile",
"description": "Package collected from Malaika Restaurant",
"actor_type": "rider",
"occurred_at": "2026-05-15T10:48:09Z"
}
]

Events are ordered newest first.

Cancel a shipment

POST /merchant/shipments/{id}/cancel

Cancel a shipment before pickup. Refunds the wallet immediately.

curl -X POST https://api.dodo.co.tz/api/v1/merchant/shipments/12345/cancel \
-H "X-API-Key: $DODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "Customer changed their mind" }'

Request:

FieldTypeRequiredDescription
reasonstringyesWhy you're cancelling (5–500 chars) — appears in admin reports

Response: the updated shipment record with status: "cancelled" and the wallet credit reflected.

Cancellable states

Cancellation is only allowed in pending, confirmed, or pickup_dispatched status. Once the rider has the package (picked_up and beyond), the API returns:

{ "detail": "Shipment in status 'picked_up' cannot be cancelled." }

For post-pickup issues, contact support — we'll work with the rider and refund where appropriate.

What happens on cancel

  1. Shipment status flips to cancelled
  2. Wallet credit posted for the full total_amount
  3. Webhook shipment.cancelled fires
  4. If a rider was already dispatched, they're notified
  • Webhooks — get status updates pushed to your server instead of polling
  • Shipment Lifecycle — full state machine including which transitions can cancel
  • Errors — error codes and retry strategy