Armada Armada API v2

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.

pending
accepted
dispatched
en_route
completed

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; driverId is set.
  • delivery.en_route — driver left the pickup. Driver location webhooks start firing on the interval you configure.
  • delivery.completed — delivered. Wallet is debited for deliveryFee.
  • 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 as kuwait_format.
  • ksa_format — structured Saudi address. Fields: city, district, street, building.
  • ksa_short_format — Saudi short address code. Fields: short_address (8-char alphanumeric).

POST /v2/deliveries

Create 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

Field
Type
Description
reference required
string
Partner-supplied unique order id. Armada de-dupes on this value — retrying a network-failed request with the same reference returns the original order instead of creating a duplicate.
payment.amount required
number
Amount the driver will collect or that has been pre-paid. Positive.
payment.type required
string
How the customer pays.
paidcash
origin_format required
string
Shape of the origin object. Use branch_format for a registered branch, location_format for an ad-hoc pickup point.
branch_formatlocation_format
origin required
object
destination_format required
string
Shape of the destination object.
location_formatkuwait_formatbahrain_formatksa_formatksa_short_format
destination required
object
scheduled_date optional
ISO-8601 date-time
Schedule the pickup for a future time. Omit for immediate dispatch.
POST /v2/deliveries
TS=$(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

Field
Type
Description
id required
string
Armada order id. 24-hex Mongo ObjectId.
reference required
string
Echoes your idempotency key.
status required
string
Current lifecycle status. See Lifecycle.
pendingaccepteddispatcheden_routecompletedcanceledfailed
code required
string
Short human-readable order code (4–6 chars). Used on the tracking page.
amount required
number
Order amount (echoes your payment.amount).
currency required
string
Merchant currency, e.g. KWD, SAR.
deliveryFee required
number
Fee Armada charges for this delivery. Billed from the wallet when the order reaches completed.
distance required
number
Driving distance in meters.
duration required
number
Estimated driving duration in seconds.
driverId optional
string | null
Driver assignment. Null until the order reaches accepted.
driverName optional
string | null
Null until assigned.
driverLocation required
object
Current driver lat/lng. Nulls until the order reaches en_route. Refreshes on every driver.location_updated webhook.
trackingLink required
string
Customer-facing tracking URL. Safe to share.
testMode required
boolean
True when the order was created with a test-mode key. See Test mode.
createdAt required
ISO-8601 date-time
When the order was created.
200 OK
{
  "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 carries error and message naming 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 lacks delivery:write.
  • 422 — wallet balance insufficient for the estimated fee (only when the merchant has forceWalletPayment on).
GET /v2/deliveries/:id

Retrieve 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.

GET /v2/deliveries/:id
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.

POST /v2/deliveries/:id/cancel

Cancel 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

Field
Type
Description
reason optional
string
Free-text reason recorded on the order. Shown in the merchant dashboard.
POST /v2/deliveries/:id/cancel
curl -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"}'
POST /v2/deliveries/:id/retry

Retry 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.

POST /v2/deliveries/:id/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 in failed status. You can't retry a completed or canceled order; create a new one instead.
  • 404 — order not found or not owned by this merchant.
POST /v2/deliveries/estimate

Estimate 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.

POST /v2/deliveries/estimate
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.