DELIVERIES
Create a delivery
roadrunnerzw.com/api/v1/deliveries
The delivery is accepted immediately and sent to a courier network in
the background, so the response is 202 Accepted with a pending
delivery rather than 201 Created. Watch for the delivery.dispatched
or delivery.dispatch_failed webhook, or poll this delivery, to learn
the outcome.
An Idempotency-Key header is required: retrying with the same key
returns the original response instead of creating a second delivery.
curl -X POST https://roadrunnerzw.com/api/v1/deliveries \
-H 'Authorization: Bearer rr_live_your_key_id' \
-H 'X-RR-Timestamp: $(date +%s)' \
-H 'X-RR-Signature: $SIGNATURE' \
-H 'Idempotency-Key: $(uuidgen)' \
-H 'Content-Type: application/json' \
-d '{
"client_reference": "ABC-10432",
"pickup": {
"name": "ABC",
"phone": "+263242000000",
"address": "10 Example Avenue, Harare, Zimbabwe",
"instructions": "Collect from the front counter"
},
"dropoff": {
"name": "John Doe",
"phone": "+263770000000",
"email": "john@example.com",
"address": "45 Example Road, Harare, Zimbabwe",
"country": "Zimbabwe",
"instructions": "Gate code 4471. Call on arrival."
},
"items": [
{
"name": "Widget, large",
"quantity": 2,
"unit_price": 1250,
"notes": "Handle with care"
}
],
"delivery_fee": 500,
"tax": 0,
"currency": "USD",
"payment_type": "prepaid",
"metadata": {
"order_type": "retail"
}
}'
{
"id": "dlv_01JAV3K2QX8M4N7P",
"object": "delivery",
"client_reference": "ABC-10432",
"status": "pending",
"test_mode": false,
"pickup": {
"name": "ABC",
"phone": "+263242000000",
"address": "10 Example Avenue, Harare, Zimbabwe",
"instructions": "Collect from the front counter"
},
"dropoff": {
"name": "John Doe",
"phone": "+263770000000",
"email": "john@example.com",
"address": "45 Example Road, Harare, Zimbabwe",
"instructions": "Gate code 4471. Call on arrival."
},
"items": [
{
"name": "Widget, large",
"quantity": 2,
"unit_price": 1250,
"notes": "Handle with care"
}
],
"payment_type": "prepaid",
"cash_to_collect": null,
"pricing": {
"subtotal": {
"amount": 2500,
"currency": "USD"
},
"delivery_fee": {
"amount": 500,
"currency": "USD"
},
"tax": {
"amount": 0,
"currency": "USD"
},
"total": {
"amount": 3000,
"currency": "USD"
}
},
"scheduled_for": null,
"tracking_url": "https://staging.roadrunnerzw.com/t/8f2a9c1e4b",
"courier": null,
"eta": null,
"proof_of_delivery": null,
"created_at": "2026-09-21T14:30:00+02:00",
"updated_at": "2026-09-21T14:30:06+02:00",
"dispatched_at": null,
"delivered_at": null,
"cancelled_at": null,
"cancellation_reason": null
}
Headers
-
Idempotency-Keystring REQUIREDREQUIRED. A unique string of your choosing, at most 255 characters: a UUID is the usual choice. Retrying with the same key returns the original response instead of creating a second delivery, so reuse it on every retry of the same intent and change it for a new one. Reusing a key with a different body returns 409.
Body
-
quote_idstringThe id from a POST /v1/quotes response. Supply it to hold the price you were quoted; leave it out and the delivery is priced when we receive it.
-
client_referencestring REQUIREDYour own order number. It must be unique to your account, and it is what you will recognise the delivery by in the portal, on the tracking page and in support conversations.
-
pickup_locationstringA saved pickup location by id (
pl_…, from GET /v1/pickup-locations). Send this orpickup, not both; send neither and we use your default location. -
pickupobjectWhere the courier collects. Leave it out and we use the pickup address held on your account.
-
namestringWho to ask for at collection, if not your business name.
-
phonestringA number the courier can call if they cannot find the counter.
-
addressstringStreet address including the suburb, e.g. "10 Example Avenue, Msasa, Harare". Required once you send a pickup object at all.
-
instructionsstringAnything the courier needs to know to collect: which door, which counter, who to ask for.
-
-
dropoffobject REQUIREDWhere the parcel is going, and who is waiting for it.
-
namestring REQUIREDThe recipient's name as they gave it to you. One field, not two: the tracking page shows only the first word of it.
-
phonestring REQUIREDA Zimbabwean mobile number the courier can call on arrival. Accepted as 07…, 2637… or +2637….
-
emailstringOptional. Only used if we ever need to reach the recipient in writing; it never appears on the public tracking page.
-
addressstring REQUIREDStreet address including the suburb. The suburb is what the recipient sees on the tracking page and what the price is measured against, so a vague address costs you accuracy.
-
countrystringDefaults to Zimbabwe. We deliver inside Zimbabwe only, so an address anywhere else is refused before a courier is sent.
-
instructionsstringGate codes, floor numbers, "call on arrival": whatever the courier needs to complete the drop without phoning you.
-
-
itemsarray of objects REQUIREDWhat is in the parcel. At least one item, at most 100.
-
namestring REQUIREDWhat the item is, in words a courier would understand.
-
quantityinteger REQUIREDHow many of this item. Whole numbers, at least 1.
-
unit_priceinteger REQUIREDPrice for ONE of this item, in cents. 1250 is $12.50.
-
notesstringHandling notes for this item: fragile, cold chain, upright.
-
-
delivery_feeintegerWhat you are charging your customer for delivery, in cents. This is your figure, not ours; it does not change what we bill you. Leave it out and we price the delivery ourselves.
-
taxintegerTax on the order, in cents, if you itemise it.
-
currencystringThree-letter code, e.g. "USD". Defaults to USD.
-
payment_typestring"prepaid" if the customer has already paid you, or "cash_on_delivery" if the courier must collect money. Defaults to prepaid.
One of
prepaidcash_on_delivery -
service_levelstringHow fast you need it:
standard,expressorscheduled. Express costs more and scheduled can cost less; what your account pays for each is on your profile page. Defaults to standard, which is what every delivery booked before this existed was.One of
standardexpressscheduled -
cash_to_collectintegerHow much the courier must collect, in cents. Required when payment_type is cash_on_delivery, and refused otherwise.
-
scheduled_forstringBook a collection for later instead of now. ISO 8601, read as UTC, at least a minute ahead and at most seven days out.
-
metadataarray of stringsUp to 20 key/value pairs of your own. We store them and hand them back on every read; we never act on them.
Responses
202 Accepted
Accepted and queued. The delivery exists with status pending; a courier has not been assigned yet.
401 Unauthenticated
The signature, key or timestamp did not check out. Also returned for a revoked key, and for a timestamp more than 300 seconds from ours.
403 Forbidden
The key is valid but was not issued the scope this endpoint requires. Scopes are fixed at issue, so this needs a new key rather than a retry.
409 Conflict
This Idempotency-Key was already used with a different request body. Reuse a key only when retrying the same intent.
422 Validation failed
The request was understood and refused. Same envelope as every other error; details names each field at fault, so retrying unchanged will fail the same way.
429 Too many requests
Too many requests for this client. Back off and retry; the response carries Retry-After and X-RateLimit-* headers.