Deliveries
A delivery is the core resource of the v2 API: an order that moves a package from a pickup location to a drop-off location, performed by an Armada driver. This page walks through the full lifecycle, the address formats, and every endpoint on the resource.
Lifecycle
Every delivery moves through a fixed sequence of statuses. A partner never writes directly to status — it's always Armada's dispatcher and driver actions that advance it.
Terminal states: completed, canceled, failed. From any
non-terminal status you can call cancel. From failed (dispatcher couldn't find a driver, or driver gave up) you can call retry.
What webhooks fire
See Webhooks for configuration. In lifecycle order:
delivery.accepted— a driver is assigned;driverIdis set.delivery.en_route— driver left the pickup. Driver location webhooks start firing on the interval you configure.delivery.completed— delivered. Wallet is debited fordeliveryFee.delivery.canceled— you or the merchant canceled before terminal state. No fee.delivery.failed— dispatcher exhausted retries or driver aborted. No fee.
Origin & destination formats
The same request body supports several address shapes, so you don't have to normalize customer data yourself. Pick the format that matches what you have — Armada handles the geocoding.
Origin formats
branch_format— reference an existing branch by id. Use this when the pickup is one of the merchant's registered locations. Required field:branch_id.location_format— an ad-hoc pickup anywhere. Useful for same-day errand-style orders. Required fields:contact_name,contact_phone,latitude,longitude. Optional:first_line,floor,apartment,instructions.
Destination formats
location_format— lat/lng anywhere. Fields:contact_name,contact_phone,latitude,longitude,first_line/floor/apartment/instructions(optional).kuwait_format— structured Kuwait address. Fields:area,block,street,building. Optional floor / apartment.bahrain_format— same shape askuwait_format.ksa_format— structured Saudi address. Fields:city,district,street,building.ksa_short_format— Saudi short address code. Fields:short_address(8-char alphanumeric).
/v2/deliveriesCreate a delivery
Creates a delivery. Returns the new order with status: "pending"; the
dispatcher will assign a driver and advance the status via webhooks.
Permission: delivery:write.
Request
reference requiredstringpayment.amount requirednumberpayment.type requiredstringpaidcashorigin_format requiredstringorigin object. Use branch_format for a registered branch, location_format for an ad-hoc pickup point. branch_formatlocation_formatdestination_format requiredstringdestination object. location_formatkuwait_formatbahrain_formatksa_formatksa_short_formatscheduled_date optionalISO-8601 date-timeTS=$(date +%s%3N)
BODY='{"reference":"order-100245","payment":{"amount":4.5,"type":"paid"},"origin_format":"branch_format","origin":{"branch_id":"66af6f6c2f85f4b4c36f2031"},"destination_format":"location_format","destination":{"contact_name":"John Doe","contact_phone":"+96590000000","latitude":29.3759,"longitude":47.9774,"first_line":"Salmiya, Block 5, Street 3"}}'
SIG=$(printf "%s.POST./v2/deliveries.%s" "$TS" "$BODY" \
| openssl dgst -sha256 -hmac "$ARMADA_API_SECRET" -hex | awk '{print $NF}')
curl -sS -X POST https://api.armadadelivery.com/v2/deliveries \
-H "Authorization: Key $ARMADA_API_KEY" \
-H "x-armada-timestamp: $TS" \
-H "x-armada-signature: $SIG" \
-H "Content-Type: application/json" \
-d "$BODY"Response
id requiredstringreference requiredstringstatus requiredstringpendingaccepteddispatcheden_routecompletedcanceledfailedcode requiredstringamount requirednumberpayment.amount). currency requiredstringKWD, SAR. deliveryFee requirednumbercompleted. distance requirednumberduration requirednumberdriverId optionalstring | nullaccepted. driverName optionalstring | nulldriverLocation requiredobjecten_route. Refreshes on every driver.location_updated webhook. trackingLink requiredstringcreatedAt requiredISO-8601 date-time{
"id": "670f2a4e1f6b3c0012abcd12",
"reference": "order-100245",
"code": "A1B2",
"status": "pending",
"amount": 4.5,
"currency": "KWD",
"deliveryFee": 2,
"distance": 4820,
"duration": 743,
"customerName": "John Doe",
"customerPhone": "+96590000000",
"driverId": null,
"driverName": null,
"driverLocation": { "latitude": null, "longitude": null },
"trackingLink": "https://tracking.armadadelivery.com/A1B2",
"testMode": false,
"createdAt": "2026-04-16T18:12:03.117Z"
}Errors
400— validation failure. Response body carrieserrorandmessagenaming the offending field (e.g.destination.latitude: is required for location_format).401— missing or invalid HMAC signature, or timestamp drift > 30 s. See Authentication.403— key lacksdelivery:write.422— wallet balance insufficient for the estimated fee (only when the merchant hasforceWalletPaymenton).
/v2/deliveries/:idRetrieve a delivery
Fetch the current state of an order. Use this for reconciliation or when you need the live status without waiting for the next webhook.
Permission: delivery:read.
curl -sS https://api.armadadelivery.com/v2/deliveries/670f2a4e1f6b3c0012abcd12 \ -H "Authorization: Key $ARMADA_API_KEY" \ -H "x-armada-timestamp: $TS" \ -H "x-armada-signature: $SIG"
The returned object has the same shape as the create
response. Fields like driverId, driverName, and driverLocation fill in as the order progresses.
/v2/deliveries/:id/cancelCancel a delivery
Cancels an order before it reaches a terminal state. Safe to call from any status except completed, canceled, or failed.
Permission: delivery:cancel.
Request
reason optionalstringcurl -sS -X POST https://api.armadadelivery.com/v2/deliveries/670f2a4e.../cancel \
-H "Authorization: Key $ARMADA_API_KEY" \
-H "x-armada-timestamp: $TS" \
-H "x-armada-signature: $SIG" \
-H "Content-Type: application/json" \
-d '{"reason":"customer canceled"}'/v2/deliveries/:id/retryRetry a failed delivery
Puts a failed order back in the dispatch queue. Resets the driver-search
counter to zero and moves the status to pending.
Permission: delivery:retry.
curl -sS -X POST https://api.armadadelivery.com/v2/deliveries/670f2a4e.../retry \ -H "Authorization: Key $ARMADA_API_KEY" \ -H "x-armada-timestamp: $TS" \ -H "x-armada-signature: $SIG"
Errors
409— order is not infailedstatus. You can't retry a completed or canceled order; create a new one instead.404— order not found or not owned by this merchant.
/v2/deliveries/estimateEstimate a delivery fee
Preview the deliveryFee before creating the order. Same address-format options
as create; you don't need to send reference or payment.
Permission: delivery:write.
curl -sS -X POST https://api.armadadelivery.com/v2/deliveries/estimate \
-H "Authorization: Key $ARMADA_API_KEY" \
-H "x-armada-timestamp: $TS" \
-H "x-armada-signature: $SIG" \
-H "Content-Type: application/json" \
-d '{"origin_format":"branch_format","origin":{"branch_id":"..."},"destination_format":"location_format","destination":{"contact_name":"x","contact_phone":"x","latitude":29.37,"longitude":47.98}}'The /estimate/static variant uses fixed pricing (no live traffic); useful when
you want a predictable quote.
Idempotency
Every create request requires a reference. If the network fails and you retry
with the same reference, Armada returns the original order rather than creating a
duplicate. Treat reference as your source-of-truth id — something like a
database primary key, a UUID, or your own order number.