API Reference

Build delivery into anything

A clean REST API with predictable JSON responses, idempotent keys, and HMAC-signed webhooks. Integrate in hours, not weeks.

terminal
curl -X POST https://daas.errand4me.com/api/v1/deliveries \
  -H "x-api-key: em_live_a1b2c3d4..." \
  -H "Content-Type: application/json" \
  -d '{
    "pickup_address": "15 Independence Ave, Accra",
    "dropoff_address": "42 Ring Road East, Accra",
    "dropoff_contact_name": "Jane Doe",
    "dropoff_contact_phone": "+233209876543"
  }'

# Response
{
  "success": true,
  "data": {
    "tracking_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "dispatched",
    "price": { "total": 25, "currency": "GHS" }
  }
}
Authentication

Two authentication methods

Use API keys for server-to-server integrations. JWT for dashboard sessions.

API

API Key

Recommended for server-to-server

Keys follow the format em_live_<64-hex-chars> (72 chars total). Generated once — store securely. Revocable at any time.

# All protected endpoints
GET /api/wallet HTTP/1.1
Host: daas.errand4me.com
x-api-key: em_live_a1b2c3d4e5f6...
JWT

JWT Bearer Token

For dashboard sessions

Login with email/password to receive an access token (8h expiry) and a refresh token. Use Authorization: Bearer <token>.

# Dashboard users
POST /api/auth/login
{ "email": "...", "password": "..." }

# Then use the returned token:
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Quickstart

Up and running in 4 steps

01

Register your business

Create an account at the DaaS portal. A verification email is sent immediately.

http
POST https://daas.errand4me.com/api/auth/register
Content-Type: application/json

{
  "business_name": "My Store",
  "slug": "my-store",
  "email": "admin@mystore.com",
  "owner_name": "Jane Smith",
  "password": "secure-password-min-8-chars"
}
02

Verify email & get approved

Click the link in your email to verify. Your account is reviewed within 24 hours. You'll receive an approval email.

03

Generate an API key

Log in to your dashboard and generate your first API key. It's shown only once — copy it to your secrets manager.

http
POST https://daas.errand4me.com/api/keys
Authorization: Bearer <your_access_token>

{ "name": "Production Key" }

# Response: { "key": "em_live_a1b2c3d4..." }  ← store this!
04

Send your first delivery

Use your API key to dispatch a delivery. You'll get back a tracking_id and real-time status via webhooks.

javascript
const res = await fetch('https://daas.errand4me.com/api/v1/deliveries', {
  method: 'POST',
  headers: {
    'x-api-key': process.env.DAAS_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    pickup_address: '15 Independence Ave, Accra',
    dropoff_address: '42 Ring Road East, Accra',
    dropoff_contact_name: 'John Doe',
    dropoff_contact_phone: '+233209876543',
  }),
})
const { data } = await res.json()
console.log(data.tracking_id) // "550e8400-..."
console.log(data.status)      // "dispatched"
console.log(data.price.total) // 25
API Reference

Endpoints

Base URL: https://daas.errand4me.com/api

A Requires full_service or both planB Requires delivery_api or both plan
Method
Endpoint
Description
Plan
POST
/auth/register
Register a new business account
POST
/auth/login
Login and receive JWT tokens
POST
/auth/refresh
Refresh access token
POST
/auth/verify-email
Verify email with token
POST
/auth/resend-verification
Resend verification email
GET
/wallet
Get wallet balance and currency
GET
/wallet/transactions
List wallet transactions (paginated)
POST
/wallet/topup/initialize
Initialize Paystack top-up
GET
/wallet/topup/verify/:reference
Verify and apply top-up
POST
/listings
Create a product or service listing
A
GET
/listings
List all listings (paginated)
A
GET
/listings/:id
Get a single listing
A
PATCH
/listings/:id
Update listing details
A
DELETE
/listings/:id
Delete a listing
A
POST
/orders
Create an order (dispatches a carrier)
A
GET
/orders
List orders (paginated)
A
GET
/orders/:id
Get order with fulfillment and items
A
POST
/orders/:id/cancel
Cancel an order (refunds wallet)
A
GET
/v1/deliveries/price-estimate
Estimate delivery price by coordinates
B
POST
/v1/deliveries
Create a delivery (dispatch carrier)
B
GET
/v1/deliveries
List deliveries (paginated)
B
GET
/v1/deliveries/:id
Get delivery details and status
B
POST
/v1/deliveries/:id/cancel
Cancel a delivery (refunds wallet)
B
GET
/v1/webhooks/logs
List webhook delivery attempt logs
B
POST
/keys
Generate a new API key (shown once)
GET
/keys
List API keys (metadata only, no raw key)
DELETE
/keys/:id
Revoke an API key
GET
/settings/webhook
Get webhook URL and secret
PATCH
/settings/webhook
Update webhook URL or rotate secret
Webhooks

Real-time event delivery

Configure a HTTPS endpoint and we'll POST signed events for every delivery status change. Retries 3 times on failure.

Event
Description
Trigger
delivery.createdDelivery accepted and dispatched to carrier networkPOST /v1/deliveries succeeds
delivery.assignedA carrier accepted the errandCarrier manually accepts
delivery.picked_upCarrier has picked up the packageCarrier marks pickup done
delivery.deliveredDelivery completed successfullyCarrier marks delivery done
delivery.cancelledDelivery was cancelled by business or systemPOST /v1/deliveries/:id/cancel
delivery.failedDelivery could not be completedNo carrier found or failed attempt

Request headers

X-DaaS-Signature: sha256=<hmac-sha256-hex>
X-DaaS-Event: delivery.delivered
X-DaaS-Timestamp: 2026-03-08T10:30:00Z
Content-Type: application/json

Retry policy

Attempt 1Immediately
Attempt 2After 5 seconds
Attempt 3After 30 seconds
Final attemptAfter 2 minutes

All attempts logged. View via GET /v1/webhooks/logs

Payload shape

json
{
  "event": "delivery.delivered",
  "delivery_id": "550e8400-e29b-41d4-a716-446655440000",
  "business_id": "biz-uuid-here",
  "timestamp": "2026-03-08T10:30:00.000Z",
  "data": {
    "tracking_id": "550e8400-e29b-41d4-a716-446655440000",
    "external_ref": "ORDER-001",
    "status": "delivered",
    "errand_id": "errand-uuid"
  }
}

Signature verification

javascript
// Node.js — verify incoming webhook signature
const crypto = require('crypto')

function verifyWebhook(rawBody, signature, secret) {
  const expected = 'sha256=' +
    crypto.createHmac('sha256', secret)
          .update(rawBody)
          .digest('hex')
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  )
}

// Express example
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-daas-signature']
  if (!verifyWebhook(req.body, sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature')
  }
  const event = JSON.parse(req.body)
  console.log(event.event)  // "delivery.delivered"
  res.sendStatus(200)
})
Code Examples

Working examples

Copy-paste ready code for creating deliveries, estimating prices, and cancelling.

import fetch from 'node-fetch'  // or built-in fetch in Node 18+

const DAAS_API_KEY = process.env.DAAS_API_KEY
const BASE_URL = 'https://daas.errand4me.com/api'

async function createDelivery(order) {
  const res = await fetch(`${BASE_URL}/v1/deliveries`, {
    method: 'POST',
    headers: {
      'x-api-key': DAAS_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      external_ref: order.id,
      pickup_address: order.store.address,
      pickup_contact_name: order.store.name,
      pickup_contact_phone: order.store.phone,
      dropoff_address: order.customer.address,
      dropoff_contact_name: order.customer.name,
      dropoff_contact_phone: order.customer.phone,
      package_description: order.items.join(', '),
      package_fragile: order.hasFragile,
    }),
  })
  if (!res.ok) throw new Error(`DaaS error: ${res.status}`)
  const { data } = await res.json()
  return data  // { tracking_id, status, price, errand_id }
}

async function getPriceEstimate(pickupLat, pickupLng, dropoffLat, dropoffLng) {
  const params = new URLSearchParams({
    pickup_lat: pickupLat, pickup_lng: pickupLng,
    dropoff_lat: dropoffLat, dropoff_lng: dropoffLng,
  })
  const res = await fetch(`${BASE_URL}/v1/deliveries/price-estimate?${params}`, {
    headers: { 'x-api-key': DAAS_API_KEY },
  })
  const { data } = await res.json()
  return data  // { base_fee: 10, distance_fee: 12.5, total: 22.5, currency: "GHS" }
}

Ready to integrate?

Sign up, get approved, and generate your API key. No credit card required.

Get API Key — Free