Eazer
Partner Delivery API
Keep your own checkout. Dispatch Eazer couriers for pickup → dropoff, settle fees from a prepaid wallet, and get signed status webhooks in real time.
Overview
v1 is courier-only. Your customers pay you; you pay Eazer for the delivery leg via a prepaid partner wallet.
- Base URL:
https://api.eazer.com/api - Partner routes live under
/partner/v1 - Jobs reuse Eazer’s package delivery engine (matching, tracking, proof of delivery)
- Food / kitchen orders without an Eazer menu, and customer-pay-to-Eazer checkout, are out of scope for v1
Quickstart
Quote a fee, create a delivery with your order id, then poll or wait for webhooks.
- Receive an API key and wallet top-up from Eazer ops
- Call
POST /partner/v1/deliveries/quote - Call
POST /partner/v1/deliverieswith a uniqueexternalId - Share the returned
trackingUrlor pollGET /deliveries/:id - Verify inbound webhooks with your webhook secret
curl -X POST https://api.eazer.com/api/partner/v1/deliveries/quote \
-H "Authorization: Bearer eaz_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "X-Market-Code: NG" \
-d '{
"pickupLat": 6.45,
"pickupLng": 3.39,
"dropoffLat": 6.50,
"dropoffLng": 3.35,
"packageSize": "MEDIUM",
"packageWeightKg": 2
}'Authentication
API keys are issued by Eazer ops. The plaintext key is shown once at creation — store it securely.
Send the key with either header:
Authorization: Bearer eaz_live_…
# or
X-Eazer-Api-Key: eaz_live_…- Keys are stored hashed; revoked keys are rejected immediately
- Partner routes are rate-limited separately (60 requests / minute)
- Do not embed live keys in client-side apps or public repos
Markets
Each partner has a default market and an allow-list of markets.
Override the market with X-Market-Code (for example NG or CA). The code must be allowed for your partner account; otherwise the API returns 403.
Fees and currency follow the market’s package pricing (same rules as in-app package delivery).
Wallet
Delivery fees are deducted from your prepaid partner wallet at create time.
curl https://api.eazer.com/api/partner/v1/wallet \
-H "Authorization: Bearer eaz_live_YOUR_KEY"Insufficient balance returns 402 Payment Required. Ops credits your wallet; cancelled or expired jobs that were never picked up are refunded to the wallet.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /partner/v1/deliveries/quote | Fee and distance estimate |
| POST | /partner/v1/deliveries | Create courier job (debits wallet) |
| GET | /partner/v1/deliveries/:id | Get status, fee, driver, tracking URL |
| GET | /partner/v1/deliveries/by-external/:externalId | Lookup by your order id |
| POST | /partner/v1/deliveries/:id/cancel | Cancel if not yet picked up |
| GET | /partner/v1/wallet | Prepaid wallet balance |
| POST | /partner/v1/webhooks/test | Send a signed test webhook |
| GET | /public/deliveries/track/:token | Public tracking page data (no API key) |
Paths above are relative to https://api.eazer.com/api.
Quote a delivery
Estimate fee and distance before creating a job. Does not debit the wallet.
curl -X POST https://api.eazer.com/api/partner/v1/deliveries/quote \
-H "Authorization: Bearer eaz_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "X-Market-Code: NG" \
-d '{
"pickupLat": 6.45,
"pickupLng": 3.39,
"dropoffLat": 6.50,
"dropoffLng": 3.35,
"packageSize": "MEDIUM",
"packageWeightKg": 2
}'Body fields:
pickupLat,pickupLng,dropoffLat,dropoffLng(required)packageSize—SMALL|MEDIUM|LARGE(default MEDIUM)packageWeightKg(optional)
Create a delivery
Creates a PackageDelivery job, debits your wallet, and notifies online couriers.
curl -X POST https://api.eazer.com/api/partner/v1/deliveries \
-H "Authorization: Bearer eaz_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "X-Market-Code: NG" \
-H "Idempotency-Key: order-1001" \
-d '{
"pickupAddress": "12 Marina, Lagos",
"pickupLat": 6.45,
"pickupLng": 3.39,
"dropoffAddress": "Ikeja City Mall",
"dropoffLat": 6.60,
"dropoffLng": 3.35,
"receiverName": "Ada Okeke",
"receiverPhone": "+2348012345678",
"packageSize": "MEDIUM",
"packageWeightKg": 2,
"packageDescription": "Documents",
"note": "Ring doorbell",
"externalId": "order-1001",
"metadata": { "channel": "web" },
"prohibitedItemsAcknowledged": true
}'Idempotency: the same externalId per partner returns the existing delivery. Optional header Idempotency-Key also keys the wallet debit ledger entry.
Example response:
{
"id": "clx…",
"externalId": "order-1001",
"status": "REQUESTED",
"fee": 1200,
"estimatedFee": 1200,
"finalFee": null,
"distanceKm": 5.6,
"trackingToken": "…",
"trackingUrl": "https://api.eazer.com/api/public/deliveries/track/…",
"pickupAddress": "12 Marina, Lagos",
"dropoffAddress": "Ikeja City Mall",
"receiverName": "Ada Okeke",
"receiverPhone": "+2348012345678",
"packageSize": "MEDIUM",
"paymentMethod": "partner_wallet",
"driver": null,
"createdAt": "2026-10-14T16:00:00.000Z"
}Retrieve & cancel
Fetch by Eazer id or your external id. Cancel is allowed until the package is picked up.
curl https://api.eazer.com/api/partner/v1/deliveries/DELIVERY_ID \
-H "Authorization: Bearer eaz_live_YOUR_KEY" \
-H "X-Market-Code: NG"curl https://api.eazer.com/api/partner/v1/deliveries/by-external/order-1001 \
-H "Authorization: Bearer eaz_live_YOUR_KEY"curl -X POST https://api.eazer.com/api/partner/v1/deliveries/DELIVERY_ID/cancel \
-H "Authorization: Bearer eaz_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "Customer cancelled" }'Cancel is blocked once status is PICKED_UP or IN_TRANSIT. Eligible cancels refund the delivery fee to your partner wallet.
Public tracking
Share a tracking URL with your customer. No API key is required.
curl https://api.eazer.com/api/public/deliveries/track/TRACKING_TOKENResponse includes status, addresses, receiver first name, coarse location label, and a limited driver name — not full phone/PII. Prefer the trackingUrl returned at create time.
Webhooks
Configure a webhook URL with Eazer ops. Events are signed and delivered at-least-once with retries.
Headers
X-Eazer-Timestamp— Unix secondsX-Eazer-Signature— hex HMAC-SHA256 of{timestamp}.{rawBody}using your webhook secret
Event types
delivery.requesteddelivery.assigneddelivery.picked_updelivery.in_transitdelivery.delivereddelivery.cancelleddelivery.test— fromPOST /partner/v1/webhooks/test
{
"id": "evt_clx…_REQUESTED",
"type": "delivery.requested",
"createdAt": "2026-10-14T16:00:00.000Z",
"data": {
"deliveryId": "clx…",
"externalId": "order-1001",
"status": "REQUESTED",
"trackingToken": "…",
"fee": 1200,
"receiverName": "Ada Okeke",
"pickupAddress": "12 Marina, Lagos",
"dropoffAddress": "Ikeja City Mall",
"driver": null
}
}const crypto = require('crypto');
function verifyEazerWebhook(rawBody, timestamp, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected, 'utf8'),
Buffer.from(signature, 'utf8'),
);
}
// Express example
app.post('/eazer-hooks', express.raw({ type: 'application/json' }), (req, res) => {
const timestamp = req.headers['x-eazer-timestamp'];
const signature = req.headers['x-eazer-signature'];
const rawBody = req.body.toString('utf8');
if (!verifyEazerWebhook(rawBody, timestamp, signature, process.env.EAZER_WEBHOOK_SECRET)) {
return res.status(401).send('invalid signature');
}
const event = JSON.parse(rawBody);
// Handle event.type: delivery.assigned, delivery.delivered, …
res.status(200).send('ok');
});Errors
| Status | Meaning |
|---|---|
| 401 | Missing or invalid API key |
| 402 | Insufficient partner wallet balance |
| 403 | Partner inactive or market not allowed for this key |
| 404 | Delivery not found |
| 409 | Duplicate create race (safe to retry / fetch by externalId) |
| 429 | Rate limited (partner routes: 60 req/min) |
Status lifecycle
Each transition emits a matching webhook when a webhook URL is configured.
| Status | Webhook | Notes |
|---|---|---|
| REQUESTED | delivery.requested | Job broadcast to available couriers |
| DRIVER_ASSIGNED | delivery.assigned | Courier accepted the job |
| PICKED_UP | delivery.picked_up | Package collected from pickup |
| IN_TRANSIT | delivery.in_transit | En route to dropoff |
| DELIVERED | delivery.delivered | Completed with proof of delivery |
| CANCELLED | delivery.cancelled | Cancelled or expired; wallet refunded when applicable |
Partner portal
Create an account, link a card (Stripe outside NG, Paystack in NG), generate API keys, and view deliveries and invoices. You are charged when each delivery completes.
Need help from ops first? Use the form below or email info@eazer.com.
