Developers

Build on ParcelOps

Quote, book, track and pull documents for your shipments over a clean REST API, and let webhooks push status changes to you. The whole reference is on this page — no sales call between you and the docs.

Base URL
api.parcelops.co.za/api/v1
Authentication
Bearer key with a po_ prefix
Format
JSON in, JSON out · ISO 8601 dates

Quick start

Your first request in under a minute

  1. 01Log in to your courier’s customer portal and create a key under Integrations → API Keys. The key acts as your customer account — it sees your shipments, your invoices, nothing else.
  2. 02Send it as a Bearer token:
curl https://api.parcelops.co.za/api/v1/customer/shipments \
  -H "Authorization: Bearer po_YOUR_API_KEY"

Not on ParcelOps yet? Any courier running ParcelOps can enable portal access for you — or start a trial and issue your own keys.

Webhooks

Six events, pushed to you

Subscribe from the portal (Integrations → Webhooks) and ParcelOps POSTs each event to your endpoint as it happens — no polling.

shipment.collectedThe parcel has been picked up from the sender
shipment.out_for_deliveryOn a vehicle for final delivery
shipment.deliveredDelivered, with POD captured
shipment.failed_deliveryA delivery attempt failed, with the reason
invoice.issuedAn invoice has been raised on your account
invoice.paidA payment has been receipted against an invoice

The delivery contract

  • Every delivery is signed: X-Parcelops-Signature carries an HMAC-SHA256 of the raw body, keyed with your endpoint’s secret.
  • X-Parcelops-Delivery-Id is unique per delivery — use it to deduplicate.
  • Respond with any 2xx within 15 seconds. Anything else is retried five times with exponential backoff, starting a minute later.

Example payload

{
  "id": "9f3c2a44-1c1e-4b7e-9a1d-8c2f6f5e7d10",
  "event": "shipment.delivered",
  "timestamp": "2026-09-09T14:32:07.000Z",
  "tenantSlug": "your-courier",
  "data": {
    "waybillNumber": "ABC-000123",
    "status": "DELIVERED"
  }
}

Verifying the signature (Node)

import crypto from "crypto";

// X-Parcelops-Signature: sha256=<hex hmac of the raw body>
function verify(rawBody, header, secret) {
  const expected = "sha256=" +
    crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}

Reference

Every endpoint, in full

The complete customer API — request and response schemas, try-it-out, and copy-paste examples in your language.

Get started

Ship your integration this week

An API key from the portal is all you need. If you get stuck, a developer answers — not a ticket queue.