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; driver details become available.
  • delivery.en_route — driver left the pickup. Driver location webhooks start firing on the interval you configure.
  • delivery.completed — delivered. Wallet is debited for delivery_fee.
  • 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
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.
test_mode required
boolean
True when the order was created with a test-mode key. See Test mode.
amount required
number
Order amount (echoes your payment.amount).
created_at required
ISO-8601 date-time
When the order was created.
currency required
string
Merchant currency, e.g. KWD, SAR.
delivery_fee required
number
Fee Armada charges for this delivery. Billed from the wallet when the order reaches completed.
customer required
object
Drop-off customer details.
customer.name required
string
Customer name.
customer.phone required
string
Customer phone.
customer.address required
string
Drop-off address text.
customer.latitude optional
number | null
Drop-off latitude when available.
customer.longitude optional
number | null
Drop-off longitude when available.
driver required
object
Assigned driver details. Empty strings/null coordinates until a driver is assigned.
driver.name required
string
Assigned driver name when available.
driver.phone required
string
Assigned driver phone when available.
driver.latitude optional
number | null
Current driver latitude when available.
driver.longitude optional
number | null
Current driver longitude when available.
logistics required
object
Distance, duration, tracking, and pickup QR links.
logistics.estimated_distance required
number
Driving distance in meters.
logistics.estimated_duration required
number
Estimated driving duration in seconds.
logistics.tracking_url required
string
Customer-facing tracking URL. Safe to share.
logistics.pickup_qr_url required
string
Pickup QR URL for handoff verification.
200 OK
{
  "code": "A1B2",
  "status": "pending",
  "test_mode": true,
  "amount": 4.5,
  "created_at": "2026-04-16T18:12:03.117Z",
  "currency": "KWD",
  "delivery_fee": 2,
  "customer": {
    "name": "John Doe",
    "phone": "+96590000000",
    "address": "Salmiya, Block 5, Street 3",
    "latitude": 29.3759,
    "longitude": 47.9774
  },
  "driver": {
    "name": "",
    "phone": "",
    "latitude": null,
    "longitude": null
  },
  "logistics": {
    "estimated_distance": 4820,
    "estimated_duration": 743,
    "tracking_url": "https://tracking.armadadelivery.com/A1B2",
    "pickup_qr_url": "https://tracking.armadadelivery.com/A1B2?qr=pickup"
  }
}

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 driver.name, driver.phone, and driver.latitude/driver.longitude 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 delivery fee 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.