Orders API

Connect your own system to PrimoRoute and create, update, read or cancel orders programmatically.

Getting an API key

Go to Settings → Integrations → API in the PrimoRoute dashboard and generate a key. The full key is shown once. Copy it immediately and store it somewhere safe. From then on it is only shown masked (e.g. pr_api_••••3f2a).

This key is independent from any Zapier connection your company may have, so regenerating or revoking it never affects Zapier, and vice versa.

Authentication

Send your API key in the X-Api-Key header on every request. There is no OAuth flow and no session. The header alone identifies your company.

X-Api-Key: pr_api_your_key_here

A missing, invalid or revoked key returns 401 with errorCode: "INVALID_API_KEY". Your key only ever sees and modifies your own company's orders. There is no way to reach another company's data with it.

Base URL

https://api.primoroute.com

Rate limits

Each API key is limited to 60 requests per minute. Exceeding it returns 429 with errorCode: "RATE_LIMIT_EXCEEDED". Wait a minute and retry. The window resets on a rolling basis, not on the clock minute.

Errors

Every error response is JSON with a human-readable message and a stable, language-independent errorCode. Branch your integration on errorCode, not on the message text. Field-level validation errors also include an errors object keyed by field name.

{
  "message": "Validation failed",
  "errorCode": "VALIDATION_ERROR",
  "errors": {
    "Recipient.Name": ["Recipient name is required"],
    "Financial.TotalAmount": ["Total amount is required"]
  }
}

Endpoints

Create an order

POST/api/v1/orders

Creates a new order. Coordinates are resolved from the address automatically if you don't send them. Same validation rules as the PrimoRoute dashboard: a delivery window is required unless noDeliveryTimeConstraint is set.

Request body
{
  "sourceType": "PickupAddress",
  "recipient": {
    "name": "Ada Lovelace",
    "primaryPhoneNumber": "+31600000000",
    "street": "Prinsengracht 1",
    "city": "Amsterdam",
    "country": "NL"
  },
  "sender": {
    "name": "My Warehouse",
    "street": "Havenstraat 10",
    "city": "Rotterdam",
    "country": "NL"
  },
  "logistics": {
    "totalWeight": 3.5,
    "totalVolume": 0.02,
    "pieceCount": 1
  },
  "financial": {
    "totalAmount": 49.90,
    "currency": "Eur"
  },
  "timeline": {
    "deliveryStartDate": "2026-09-19T08:00:00Z",
    "deliveryDate": "2026-09-19T18:00:00Z"
  }
}
Response: 200 OK
{
  "data": {
    "id": "b3f1c2a4-...",
    "orderNumber": "PR-000482",
    "trackingCode": "TRK-9F2K",
    "status": "Pending",
    "sourceType": "PickupAddress",
    "isAssigned": false,
    "recipient": {
      "name": "Ada Lovelace",
      "primaryPhoneNumber": "+31600000000",
      "street": "Prinsengracht 1",
      "city": "Amsterdam",
      "country": "NL",
      "latitude": 52.3702,
      "longitude": 4.8952
    },
    "sender": {
      "name": "My Warehouse",
      "street": "Havenstraat 10",
      "city": "Rotterdam",
      "country": "NL"
    },
    "logistics": {
      "totalWeight": 3.5,
      "totalVolume": 0.02,
      "pieceCount": 1,
      "priority": "Medium"
    },
    "financial": {
      "totalAmount": 49.9,
      "currency": "Eur"
    },
    "timeline": {
      "createdAt": "2026-09-18T09:00:00Z",
      "deliveryStartDate": "2026-09-19T08:00:00Z",
      "deliveryDate": "2026-09-19T18:00:00Z"
    }
  },
  "message": "Success"
}

Update an order

PUT/api/v1/orders/{id}

Partially updates an order: only the fields you send are changed, everything else is left untouched. Send status: 'Cancelled' here to cancel (or use the dedicated cancel endpoint below).

Request body
{
  "logistics": {
    "totalWeight": 4.0
  },
  "timeline": {
    "deliveryDate": "2026-09-20T18:00:00Z"
  }
}
Response: 200 OK
{
  "data": {
    "id": "b3f1c2a4-...",
    "orderNumber": "PR-000482",
    "trackingCode": "TRK-9F2K",
    "status": "Pending",
    "sourceType": "PickupAddress",
    "isAssigned": false,
    "recipient": {
      "name": "Ada Lovelace",
      "primaryPhoneNumber": "+31600000000",
      "street": "Prinsengracht 1",
      "city": "Amsterdam",
      "country": "NL",
      "latitude": 52.3702,
      "longitude": 4.8952
    },
    "sender": {
      "name": "My Warehouse",
      "street": "Havenstraat 10",
      "city": "Rotterdam",
      "country": "NL"
    },
    "logistics": {
      "totalWeight": 3.5,
      "totalVolume": 0.02,
      "pieceCount": 1,
      "priority": "Medium"
    },
    "financial": {
      "totalAmount": 49.9,
      "currency": "Eur"
    },
    "timeline": {
      "createdAt": "2026-09-18T09:00:00Z",
      "deliveryStartDate": "2026-09-19T08:00:00Z",
      "deliveryDate": "2026-09-19T18:00:00Z"
    }
  },
  "message": "Success"
}

Get an order

GET/api/v1/orders/{id}

Reads a single order by its PrimoRoute id.

Response: 200 OK
{
  "data": {
    "id": "b3f1c2a4-...",
    "orderNumber": "PR-000482",
    "trackingCode": "TRK-9F2K",
    "status": "Pending",
    "sourceType": "PickupAddress",
    "isAssigned": false,
    "recipient": {
      "name": "Ada Lovelace",
      "primaryPhoneNumber": "+31600000000",
      "street": "Prinsengracht 1",
      "city": "Amsterdam",
      "country": "NL",
      "latitude": 52.3702,
      "longitude": 4.8952
    },
    "sender": {
      "name": "My Warehouse",
      "street": "Havenstraat 10",
      "city": "Rotterdam",
      "country": "NL"
    },
    "logistics": {
      "totalWeight": 3.5,
      "totalVolume": 0.02,
      "pieceCount": 1,
      "priority": "Medium"
    },
    "financial": {
      "totalAmount": 49.9,
      "currency": "Eur"
    },
    "timeline": {
      "createdAt": "2026-09-18T09:00:00Z",
      "deliveryStartDate": "2026-09-19T08:00:00Z",
      "deliveryDate": "2026-09-19T18:00:00Z"
    }
  },
  "message": "Success"
}

Cancel an order

POST/api/v1/orders/{id}/cancel

Cancels the order. If it is already assigned to a route, it is removed from that route as part of the same request. A cancelled order cannot be un-cancelled through this API.

Response: 200 OK
{
  "data": {
    "id": "b3f1c2a4-...",
    "orderNumber": "PR-000482",
    "trackingCode": "TRK-9F2K",
    "status": "Cancelled",
    "sourceType": "PickupAddress",
    "isAssigned": false,
    "recipient": {
      "name": "Ada Lovelace",
      "primaryPhoneNumber": "+31600000000",
      "street": "Prinsengracht 1",
      "city": "Amsterdam",
      "country": "NL",
      "latitude": 52.3702,
      "longitude": 4.8952
    },
    "sender": {
      "name": "My Warehouse",
      "street": "Havenstraat 10",
      "city": "Rotterdam",
      "country": "NL"
    },
    "logistics": {
      "totalWeight": 3.5,
      "totalVolume": 0.02,
      "pieceCount": 1,
      "priority": "Medium"
    },
    "financial": {
      "totalAmount": 49.9,
      "currency": "Eur"
    },
    "timeline": {
      "createdAt": "2026-09-18T09:00:00Z",
      "deliveryStartDate": "2026-09-19T08:00:00Z",
      "deliveryDate": "2026-09-19T18:00:00Z"
    }
  },
  "message": "Success"
}