Back to home

Overview

The Aeolus API provides real-time Canada Post shipping rate quotes through a clean REST interface. Send a single POST request with origin, destination, and package dimensions — get back a JSON array of available services with prices and estimated delivery dates.

No SOAP, no XML, no Canada Post developer account needed. We handle the upstream integration so you can focus on building your app.

Base URL: https://shipping.dforge.ca

Content Type: application/json

Protocol: HTTPS only. All requests must use TLS.

Authentication

All API requests require a Bearer token in the Authorization header. Generate API keys from your dashboard.

HTTP Header
Authorization: Bearer aeolus_sk_live_abc123def456

Keep your API keys secret. Do not expose them in client-side code, public repositories, or browser requests. Use a server-side proxy for frontend applications.

POST /api/v1/quotes

Get real-time shipping rate quotes for a package between two Canadian postal codes.

Request Body

FieldTypeStatusDescription
origin_postalstringrequiredCanadian origin postal code (e.g. "V5K0A1"). Spaces are stripped automatically.
dest_postalstringrequiredCanadian destination postal code (e.g. "M5V3L9").
weight_kgnumberrequiredPackage weight in kilograms. Must be positive, max 30.
length_cmnumberrequiredPackage length in centimeters. Must be positive.
width_cmnumberrequiredPackage width in centimeters. Must be positive.
height_cmnumberrequiredPackage height in centimeters. Must be positive.
Example Request Body
{
  "origin_postal": "V5K0A1",       // Origin postal code (Canadian)
  "dest_postal":   "M5V3L9",       // Destination postal code
  "weight_kg":     2.5,            // Package weight in kilograms
  "length_cm":     30,             // Length in centimeters
  "width_cm":      20,             // Width in centimeters
  "height_cm":     15              // Height in centimeters
}

Response

A successful response returns 200 OK with an array of available shipping quotes sorted by price (cheapest first).

FieldTypeDescription
quotesarrayArray of quote objects
quotes[].servicestringCanada Post service code (e.g. DOM.RP, DOM.EP, DOM.PC)
quotes[].namestringHuman-readable service name
quotes[].pricestringTotal price as string with 2 decimal places
quotes[].currencystringAlways "CAD"
quotes[].delivery_datestringEstimated delivery date (ISO 8601 format)
Example Response (200 OK)
{
  "quotes": [
    {
      "service":       "DOM.EP",       // Canada Post service code
      "name":          "Xpresspost",   // Human-readable service name
      "price":         "18.54",        // Total price (string, 2 decimal)
      "currency":      "CAD",          // Always CAD
      "delivery_date": "2026-07-09"    // Estimated delivery (ISO 8601)
    },
    {
      "service":       "DOM.RP",
      "name":          "Regular Parcel",
      "price":         "12.87",
      "currency":      "CAD",
      "delivery_date": "2026-07-14"
    },
    {
      "service":       "DOM.PC",
      "name":          "Priority",
      "price":         "26.31",
      "currency":      "CAD",
      "delivery_date": "2026-07-08"
    }
  ]
}

Error Codes

All errors return a consistent JSON error object with a machine-readable code, human-readable message, and (when applicable) the invalid field name.

Error Response Format
{
  "error": {
    "code":    "VALIDATION_ERROR",
    "message": "weight_kg must be a positive number",
    "field":   "weight_kg"
  }
}
StatusNameDescription
400Bad RequestInvalid or missing request parameters. Check the response body for specific field errors.
401UnauthorizedMissing or invalid API key. Ensure your Authorization header contains a valid Bearer token.
429Too Many RequestsRate limit exceeded. Check the Retry-After header and upgrade your plan for higher limits.
502Bad GatewayCanada Post upstream service is temporarily unavailable. Retry with exponential backoff.

Rate Limits

Rate limits are applied per API key. When you exceed your limit, the API returns 429 Too Many Requests with a Retry-After header indicating when you can retry (in seconds).

Rate limit headers are included in every response:

HTTP Headers
X-RateLimit-Limit: 10000          # Monthly quota
X-RateLimit-Remaining: 9847       # Remaining this period
X-RateLimit-Reset: 2026-08-01     # Quota reset date
PlanMonthly QuotaBurst Limit
Starter100 requests10 / min
Builder2,000 requests30 / min
Growth10,000 requests60 / min
Scale50,000 requests120 / min
EnterpriseUnlimited requestsCustom

Code Examples

Copy-paste examples in popular languages. Replace YOUR_API_KEY with your actual API key from the dashboard.

cURL
curl -X POST https://shipping.dforge.ca/api/v1/quotes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "origin_postal": "V5K0A1",
    "dest_postal": "M5V3L9",
    "weight_kg": 2.5,
    "length_cm": 30,
    "width_cm": 20,
    "height_cm": 15
  }'
JavaScript / fetch
const response = await fetch(
  "https://shipping.dforge.ca/api/v1/quotes",
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      origin_postal: "V5K0A1",
      dest_postal:   "M5V3L9",
      weight_kg:     2.5,
      length_cm:     30,
      width_cm:      20,
      height_cm:     15,
    }),
  }
);

const data = await response.json();
console.log(data.quotes);
Python / requests
import requests

response = requests.post(
    "https://shipping.dforge.ca/api/v1/quotes",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "origin_postal": "V5K0A1",
        "dest_postal":   "M5V3L9",
        "weight_kg":     2.5,
        "length_cm":     30,
        "width_cm":      20,
        "height_cm":     15,
    },
)

data = response.json()
for quote in data["quotes"]:
    print(f"{quote['name']}: ${quote['price']} CAD")

Ready to integrate?

Create your free account and get an API key in seconds.

Get Your API Key