Skip to main content

Package Size Tiers

A size tier is a short code (e.g. "small", "medium") that bundles a canonical weight_kg + length_cm + width_cm + height_cm so your UI can present users with a friendly picker instead of asking them to measure their parcel.

Tiers are a client-side UX convention

The Dodo API is dimensional — it accepts only raw weight_kg + length_cm + width_cm + height_cm per item. Tiers exist so your frontend can render a picker; on submit, you expand the picked tier into those four fields locally and post the dims, not the tier code. The server never sees a tier.

You're free to adopt the platform's preset list, fork it for your own packaging, or skip the tier UX entirely and ask for raw dimensions.

GET /package-size-tiers

Public endpoint — no authentication required. Returns the current admin-curated preset list, sorted by display order. This is reference data your clients can use to populate their own pickers.

curl https://api.dodo.co.tz/api/v1/package-size-tiers

Response (200 OK):

[
{ "code": "envelope", "label": "Envelope", "length_cm": 30, "width_cm": 22, "height_cm": 2, "weight_kg": 0.5, "sort_order": 1 },
{ "code": "small", "label": "Small", "length_cm": 25, "width_cm": 20, "height_cm": 15, "weight_kg": 3, "sort_order": 2 },
{ "code": "medium", "label": "Medium", "length_cm": 40, "width_cm": 30, "height_cm": 25, "weight_kg": 10, "sort_order": 3 },
{ "code": "large", "label": "Large", "length_cm": 60, "width_cm": 45, "height_cm": 40, "weight_kg": 25, "sort_order": 4 },
{ "code": "heavy", "label": "Heavy", "length_cm": 50, "width_cm": 40, "height_cm": 40, "weight_kg": 50, "sort_order": 5 },
{ "code": "long", "label": "Long", "length_cm": 150, "width_cm": 20, "height_cm": 20, "weight_kg": 15, "sort_order": 6 },
{ "code": "oversized","label": "Oversized","length_cm": 200, "width_cm": 100, "height_cm": 80, "weight_kg": 80, "sort_order": 7 }
]
FieldTypeDescription
codestringIdentifier within your UI — useful for highlighting the selected tile
labelstringDisplay name for your UI
length_cmnumberCanonical length to copy into the item payload
width_cmnumberCanonical width
height_cmnumberCanonical height
weight_kgnumberCanonical weight
sort_orderintegerDisplay order

The list is admin-curated. Codes are stable (e.g. "small" will always be "small"), but the canonical dimensions behind a code may be retuned over time. Refresh the list periodically — the values are advisory at the time you posted them.

Picking a tier — typical contents

The seven seeded tiers map roughly to these everyday parcels. Use the heuristic to self-classify without trial and error.

codeTypical contentsVehicle fit
envelopeDocuments, photos, single thin itemMotorcycle
smallSingle meal, pharmacy bag, phone case, paperbackMotorcycle
mediumMulti-meal restaurant order, shoebox, laptop bagMotorcycle / car
largeMicrowave, monitor box, small electronics orderCar / van
heavyStacked groceries, single heavy appliance, water dispenserCar / van
longCurtain rod, fishing rod, golf bag, light long itemVan / pickup
oversizedBicycle, large TV box, furniture flat-packPickup / truck

If your parcel doesn't fit any tier (unusual aspect ratio, off-spec density, etc.) just ask the user for raw weight + L/W/H instead. The API treats both inputs identically — there's no "tier" path on the server.

The expand-and-submit flow looks like this:

// Fetch the platform's reference presets at app load and cache them.
const tiers = await fetch(
'https://api.dodo.co.tz/api/v1/package-size-tiers'
).then(r => r.json());

// Render a picker keyed by `code`, labelled by `label`.
const options = tiers.map(t => ({ value: t.code, label: t.label }));

// When the user picks a tier, expand it into the raw fields the API expects.
function itemFromPickedTier(description, pickedCode, quantity, isFragile) {
const tier = tiers.find(t => t.code === pickedCode);
if (!tier) throw new Error('Unknown tier picked');
return {
description,
weight_kg: tier.weight_kg,
length_cm: tier.length_cm,
width_cm: tier.width_cm,
height_cm: tier.height_cm,
is_fragile: isFragile,
quantity,
};
}

Always offer a "Custom" option in your picker that falls through to manual weight + L/W/H entry. Cargo and odd-shaped parcels need that escape hatch.

Errors

This endpoint never errors during normal operation (no auth, no body). If you encounter a 5xx, retry with backoff — the response is cacheable on your side so you don't need it fresh on every render.