Skip to main content

Create delivery

Places a booking on the Dash Express fleet. Returns a deliveryID in status ALLOCATING. The driver is assigned asynchronously — track progress via webhooks.

POST/express/v1/deliveries

The legacy path POST /v1/deliveries (category chosen via serviceCategory) is deprecated (21 May 2026) and will be obsoleted on 21 November 2026. New integrations must use /express/v1/deliveries.

Request body​

providerOrderIDstringrequired
Your AWB / order reference. Echoed in every webhook and the Get Delivery response.
serviceCategorystringoptional
One of EXPRESS, LOGISTIC. This page documents EXPRESS.
serviceTypestringrequired
For EXPRESS: INSTANT or SAME_DAY. Must match a tier returned by the quote.
paymentMethodstringoptional
CASH or CASHLESS. Default CASHLESS.
cashOnDeliveryobjectconditional
Required when paymentMethod = "CASH". Contains amount (IDR).
packages[]arrayrequired
Package rows; same shape as the quote request.
packages[].namestringrequired
Display name.
packages[].typestringoptional
One of REGULAR, SPECIAL, SENSITIVE, HIGH_VALUE, OTHER. Omitted, null, or empty is stored as REGULAR. See Package type.
packages[].descriptionstringrequired
Free-form description of the items.
packages[].quantityintegerrequired
Item count.
packages[].weightdecimalrequired
Weight in kilograms.
packages[].insuranceobjectoptional
Optional package insurance object. Requires provider, premi, coverage. Can optionally include label.
packages[].price / width / length / height / descriptionvariousoptional
Optional metadata, see Quote endpoint.
senderobjectrequired
Sender contact details.
sender.firstNamestringrequired
Sender first name.
sender.phonestringrequired
Sender phone (e.164 or local format).
sender.lastName / companyNamestringoptional
Optional sender metadata.
recipientobjectrequired
Recipient contact.
recipient.firstNamestringrequired
Recipient first name.
recipient.lastName / companyName / email / phonestringoptional
Optional recipient metadata.
originobjectconditional
Required for EXPRESS; optional for LOGISTIC.
origin.addressstringrequired
Human-readable pickup address.
origin.coordinates.latitude / longitudedecimalrequired
WGS-84 decimal.
origin.province / city / district / subDistrict / postalCodestringoptional
Optional address metadata.
origin.notesstringoptional
Free-form pickup note shown to the driver. Trimmed; omit or send null for none.
destinationobjectrequired
Dropoff location with the same shape as origin. Coordinates required for EXPRESS.
destination.notesstringoptional
Free-form dropoff note shown to the driver at handover. Trimmed; omit or send null for none.
instructions[]arrayoptional
Up to 1 instruction object (see below).
scheduleobjectoptional
Optional pickup window (ISO-8601). Max 3 days ahead, EXPRESS only.
forceUnavailablebooleanoptional
Sandbox only. Send true on an INSTANT delivery without schedule to get the 409 EXPRESS_DRIVER_UNAVAILABLE refusal. Rejected in Production. See Testing a refused booking in Sandbox.

Package type​

packages[].type labels what is inside the package. It is optional and accepts exactly five values — REGULAR, SPECIAL, SENSITIVE, HIGH_VALUE, OTHER. Omit it, or send null or an empty string, and the package is stored as REGULAR. Anything else is rejected with 400. Surrounding whitespace is trimmed before the value is checked, so " HIGH_VALUE " is accepted as HIGH_VALUE — on this endpoint and on Get delivery quote.

The stored value is returned per package by this endpoint and by Get delivery details.

"packages": [
{ "name": "Cincin emas", "type": "HIGH_VALUE", "quantity": 1, "weight": 0.1 }
]

type is a label only. Sending HIGH_VALUE does not change the fare, the courier chosen, or how the delivery is batched with others — the value is recorded and echoed back, nothing else. If a package needs special handling, arrange it with Dash Ops.

Cash on Delivery​

When paymentMethod is CASH, pass a cashOnDelivery.amount in IDR. The driver collects this on handover.

{
"paymentMethod": "CASH",
"cashOnDelivery": { "amount": 250000 }
}

Instructions​

Optional per-delivery instruction shown to the driver. At most one instruction is supported today. Setting type: "WEBVIEW" opens the URL inside the courier app.

"instructions": [
{
"type": "WEBVIEW",
"text": "Please do something on this delivery",
"url": "https://example.com/runbook"
}
]

Testing a refused booking in Sandbox​

Sandbox never runs the courier check, so a Sandbox booking is never refused for lack of couriers on its own. Add "forceUnavailable": true to the body to make Create Delivery return the 409 EXPRESS_DRIVER_UNAVAILABLE refusal, so you can build and test your retry path before the check is enabled for your account in Production.

  • Sandbox, true, INSTANT without schedule — refused with 409 EXPRESS_DRIVER_UNAVAILABLE. Nothing is booked and no webhook is sent. This works whether or not the courier check is enabled for your account.
  • Sandbox, true, SAME_DAY or with schedule — ignored. The courier check never applies to these, so the delivery is created as usual.
  • Sandbox, false, null or omitted — ignored; the delivery is created as usual.
  • Sandbox, any other value — 400 VALIDATION_FAILED, Field `forceUnavailable` harus berupa boolean.
  • Production — rejected with 400 UNKNOWN_FIELD, Field tidak dikenali: [forceUnavailable], so it can never affect a real booking. Remove it before going live.
"serviceType": "INSTANT",
"forceUnavailable": true

To get an available quote in Sandbox before you book, see sandboxAvailability on Get delivery quote.

Error responses​

201

Delivery created in ALLOCATING. Courier is assigned asynchronously.

Every error below carries an errorCode — branch on it. The error message is Indonesian display copy and may change. Refusals before the request reaches this endpoint (token, timezone header) carry none — see Errors.

400REQUEST_BODY_EMPTY
Empty request body. Butuh request body.
400UNKNOWN_FIELD
Unrecognised top-level key, named in the message. Field tidak dikenali: [<field>]
400VALIDATION_FAILED
Payload validation failed; the message names the first failing field. Includes a serviceType other than INSTANT / SAME_DAY, coordinates outside ±90 / ±180, and a packages[].type outside the accepted list.
400CASH_ADVANCE_AMOUNT_REQUIRED
Cash-advance COD sent without a positive amount.
400SCHEDULE_TIMEZONE_UNKNOWN
Scheduled delivery with an x-client-time-zone that is not a recognised IANA zone.
400DELIVERY_SCHEDULE_PAST_TIME
Scheduled time has already passed. Ups! Sepertinya waktu pengantaran yang Anda pilih sudah lewat. Yuk, pilih waktu lain yang masih tersedia.
400DELIVERY_SCHEDULE_OUT_OF_RANGE
Scheduled time is outside your scheduling window (3 days ahead unless configured otherwise; the message names yours). A pickup more than a day in the past also lands here. Pengantaran hanya dapat dijadwalkan dalam rentang hari ini hingga maksimal N hari ke depan
400SERVICE_NOT_AVAILABLE
Origin area is not covered for the requested schedule. Layanan tidak tersedia di area ini. Silakan pilih layanan lain.
400OPERATIONAL_HOURS_NOT_AVAILABLE
No driver shift covers the requested schedule. Layanan tidak tersedia pada jam ini
409EXPRESS_DRIVER_UNAVAILABLE
Instant delivery with no eligible courier free right now, when the courier check is enabled for your account. A later retry may succeed. In Sandbox, trigger it with forceUnavailable: true. Kurir belum tersedia.
422LOCATION_TOO_FAR
No pricing tier covers the distance or weight (both interpolated into the message), or no drivable route exists between origin and destination (Rute tidak ditemukan. Pastikan rute antar titik sesuai.).
500INTERNAL_SERVICE_ERROR
Unexpected error on our side. Quote the requestId when contacting us.
503EXPRESS_ELIGIBILITY_UNAVAILABLE
Courier availability could not be checked. Temporary — retry shortly. Layanan sedang tidak dapat diproses. Silakan coba beberapa saat lagi.