Delivery
Armada
Armada last-mile delivery provider — estimation, dispatch, tracking, and webhooks.
The @commercejs/delivery-armada package implements the DeliveryProvider interface for Armada, a last-mile delivery platform popular in the MENA region.
Installation
pnpm add @commercejs/delivery-armada
Quick Start
import { ArmadaDeliveryProvider } from '@commercejs/delivery-armada'
const armada = new ArmadaDeliveryProvider({
accessToken: process.env.ARMADA_ACCESS_TOKEN!,
})
// Estimate delivery fee
const estimate = await armada.estimate({
origin: {
contactName: 'Store',
contactPhone: '+966500000000',
firstLine: 'Olaya St, Riyadh',
latitude: 24.7136,
longitude: 46.6753,
},
destination: {
contactName: 'Customer',
contactPhone: '+966512345678',
firstLine: 'King Fahd Rd, Riyadh',
latitude: 24.7743,
longitude: 46.7386,
},
})
Configuration
| Option | Type | Required | Description |
|---|---|---|---|
accessToken | string | ✅ | Armada API access token |
baseUrl | string | — | API base URL (default: https://api.armadadelivery.com/v1) |
fetchFn | typeof fetch | — | Custom fetch function for testing |
Methods
All methods follow the DeliveryProvider interface from @commercejs/types.
estimate
Estimates the delivery fee between two points:
const estimate = await armada.estimate({
origin: { latitude: 24.7136, longitude: 46.6753 },
destination: { latitude: 24.7743, longitude: 46.7386 },
})
console.log(estimate.fee) // 12.5
console.log(estimate.currency) // 'SAR'
console.log(estimate.estimatedDuration) // 25 (minutes)
Armada supports two origin formats:
- Branch origin — pass
{ branchId: 'branch_123' }to use a pre-configured branch - Location origin — pass
{ latitude, longitude }for ad-hoc pickup points
createDelivery
Creates a new delivery order:
const delivery = await armada.createDelivery({
origin: {
contactName: 'Shop Manager',
contactPhone: '+966500000000',
firstLine: 'King Abdullah Road',
latitude: 24.7136,
longitude: 46.6753,
},
destination: {
contactName: 'Ahmed',
contactPhone: '+966512345678',
firstLine: 'Al Malqa District',
latitude: 24.8021,
longitude: 46.6271,
instructions: 'Ring the bell twice',
},
orderId: 'order_123',
})
getDelivery
Retrieves the current state of a delivery:
const delivery = await armada.getDelivery('DEL-ABC123')
console.log(delivery.status) // 'in_transit'
console.log(delivery.driver) // { name: 'Mohammed', phone: '...', latitude: ..., longitude: ... }
cancelDelivery
Cancels an active delivery:
const cancelled = await armada.cancelDelivery('DEL-ABC123')
console.log(cancelled.status) // 'cancelled'
Status Mapping
Armada statuses are normalized to the DeliveryStatus union:
| Armada Status | DeliveryStatus |
|---|---|
pending | pending |
dispatched | assigned |
waiting_pack | pickup |
en_route | in_transit |
completed | delivered |
canceled | cancelled |
failed | failed |
Webhook Verification
Armada sends webhooks for delivery status changes. The verifyWebhook method parses the payload using the x-armada-webhook-topic header:
const event = await armada.verifyWebhook(
request.body, // raw body
request.headers['x-armada-webhook-topic'], // topic header as signature
)
console.log(event.type) // 'delivery.updated' | 'delivery.location'
console.log(event.deliveryId) // 'DEL-ABC123'
console.log(event.status) // 'delivered'
console.log(event.location) // { latitude: 24.73, longitude: 46.69 }
Webhook Topics
| Topic | Event Type |
|---|---|
order.updated | delivery.updated |
order.location.updated | delivery.location |
Using with the Orchestrator
import { createCommerce } from '@commercejs/core'
import { ArmadaDeliveryProvider } from '@commercejs/delivery-armada'
const commerce = createCommerce({
adapter,
delivery: {
armada: new ArmadaDeliveryProvider({
accessToken: process.env.ARMADA_ACCESS_TOKEN!,
}),
},
defaultDelivery: 'armada',
})