ShipPlus Open API

Multi-carrier shipping aggregation. Integrate once to rate, label, and track across UniUni, Stallion, Canada Post, UPS and more.

Base URL: https://api.shipplus.caVersion: v1

Authentication

ShipPlus issues a keyID + secretToken for your account (billed at your contract rate). Pass the secretToken in a header on every request — any of the following works:

X-API-Key: <secretToken>
X-Secret-Token: <secretToken>
Authorization: Bearer <secretToken>
Authorization: Basic base64(keyID:secretToken)

The secretToken is sensitive — keep it safe. If leaked, contact ShipPlus to revoke and reissue.

Errors

Non-2xx responses use a consistent shape:

{ "error": { "code": "invalid_request", "message": "..." } }

unauthorized (401) · invalid_request (400) · invalid_rate_id (400) · rating_failed (502) · label_failed (502) · not_found (404) · account_suspended (402) · credit_limit_exceeded (402) · insufficient_balance (402) · request_in_progress (409) · idempotency_key_reused (422)

1. Rates

POST/api/v1/rates

Get available carrier services and prices (sorted ascending).

Request

{
  "from": { "city": "Toronto", "province": "ON", "postal_code": "M5V3A8", "country": "CA" },
  "to":   { "city": "Burnaby", "province": "BC", "postal_code": "V5H4M1", "country": "CA" },
  "parcels": [
    { "weight": 1.0, "weight_unit": "kg",
      "length": 20, "width": 15, "height": 10, "dimension_unit": "cm" }
  ]
}

weight_unit: kg/g/lb/oz (default kg) · dimension_unit: cm/in (default cm) · include city + province for full carrier coverage (some carriers e.g. UniUni require the destination city/province)

Response

{
  "rates": [
    {
      "rate_id": "eyJwIjoic3RhbGxpb24i...",
      "carrier": "Stallion",
      "carrier_code": "stallion",
      "service": "fleet-optics-ground",
      "service_name": "Fleet Optics Ground",
      "price": 14.48,
      "currency": "CAD",
      "transit_days": 4
    }
  ]
}

rate_id is an opaque token — pass it back verbatim when creating a shipment (short-lived; re-quote if expired).

2. Create shipment

POST/api/v1/shipments

Create a shipment and buy a label using a rate_id. from / to require full addresses.

Strongly recommended: send an Idempotency-Key header (a unique string, e.g. a UUID). Retrying with the same key after a timeout is safe — the same key buys a label and bills only once, and returns the original result.

Headers

X-API-Key: <your secretToken>
Idempotency-Key: 3f9a1c2e-...  (recommended)

Request

{
  "from": { "name": "Warehouse A", "phone": "6470000000", "street1": "50 Wellesley St E",
            "city": "Toronto", "province": "ON", "postal_code": "M5V3A8", "country": "CA" },
  "to":   { "name": "Jane Li", "phone": "6041234567", "street1": "4700 Kingsway",
            "city": "Burnaby", "province": "BC", "postal_code": "V5H4M1", "country": "CA" },
  "parcels": [ { "weight": 1.0, "weight_unit": "kg", "length": 20, "width": 15, "height": 10 } ],
  "rate_id": "eyJwIjoic3RhbGxpb24i..."
}

Response (201)

{
  "shipment": {
    "id": "SP...",
    "tracking_number": "...",
    "carrier": "stallion",
    "service": "fleet-optics-ground",
    "label_url": "https://.../label.pdf",
    "cost": 14.48,
    "currency": "CAD",
    "status": "created"
  }
}

3. Tracking

GET/api/v1/tracking/{tracking_number}

Response

{
  "tracking_number": "...",
  "status": "in_transit",
  "events": [
    { "status": "in_transit", "timestamp": "2026-07-07T10:00:00Z",
      "location": "Toronto, ON", "description": "..." }
  ]
}

4. Account & usage

GET/api/v1/account

View your billing account: credit limit / balance, status, and this period's shipment count and amount. If credit is exhausted or the account is suspended, the create-shipment call returns 402.

{
  "account": {
    "company_name": "...", "billing_mode": "postpaid",
    "currency": "CAD", "status": "active",
    "credit_limit": 500.00, "current_due": 42.15, "balance": 0
  },
  "current_period": { "period": "2026-07", "shipments": 6, "amount": 42.15 }
}
GET/api/v1/usage?period=2026-07

List billed line items for a period (defaults to the current month).

{
  "period": "2026-07", "count": 6, "total": 42.15, "currency": "CAD",
  "records": [
    { "shipment_id": "...", "carrier": "uniuni", "service": "uniuni-standard",
      "amount": 7.83, "currency": "CAD", "invoiced": false,
      "created_at": "2026-07-14T15:00:00Z" }
  ]
}

Billing: postpaid accrues against a credit limit and is invoiced monthly; prepaid is deducted from your balance in real time.

Integration flow

  1. 1Call /api/v1/rates, pick a rate_id
  2. 2Call /api/v1/shipments with rate_id to get tracking_number + label_url
  3. 3Print the label and ship
  4. 4Poll /api/v1/tracking/{tracking_number}
Billing: labels are billed to your account at your contract rate and settled periodically. Request an API key from ShipPlus.