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.
Authorization: Bearer aeolus_sk_live_abc123def456Keep 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
| Field | Type | Status | Description |
|---|---|---|---|
origin_postal | string | required | Canadian origin postal code (e.g. "V5K0A1"). Spaces are stripped automatically. |
dest_postal | string | required | Canadian destination postal code (e.g. "M5V3L9"). |
weight_kg | number | required | Package weight in kilograms. Must be positive, max 30. |
length_cm | number | required | Package length in centimeters. Must be positive. |
width_cm | number | required | Package width in centimeters. Must be positive. |
height_cm | number | required | Package height in centimeters. Must be positive. |
{
"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).
| Field | Type | Description |
|---|---|---|
quotes | array | Array of quote objects |
quotes[].service | string | Canada Post service code (e.g. DOM.RP, DOM.EP, DOM.PC) |
quotes[].name | string | Human-readable service name |
quotes[].price | string | Total price as string with 2 decimal places |
quotes[].currency | string | Always "CAD" |
quotes[].delivery_date | string | Estimated delivery date (ISO 8601 format) |
{
"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": {
"code": "VALIDATION_ERROR",
"message": "weight_kg must be a positive number",
"field": "weight_kg"
}
}| Status | Name | Description |
|---|---|---|
400 | Bad Request | Invalid or missing request parameters. Check the response body for specific field errors. |
401 | Unauthorized | Missing or invalid API key. Ensure your Authorization header contains a valid Bearer token. |
429 | Too Many Requests | Rate limit exceeded. Check the Retry-After header and upgrade your plan for higher limits. |
502 | Bad Gateway | Canada 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:
X-RateLimit-Limit: 10000 # Monthly quota
X-RateLimit-Remaining: 9847 # Remaining this period
X-RateLimit-Reset: 2026-08-01 # Quota reset date| Plan | Monthly Quota | Burst Limit |
|---|---|---|
| Starter | 100 requests | 10 / min |
| Builder | 2,000 requests | 30 / min |
| Growth | 10,000 requests | 60 / min |
| Scale | 50,000 requests | 120 / min |
| Enterprise | Unlimited requests | Custom |
Code Examples
Copy-paste examples in popular languages. Replace YOUR_API_KEY with your actual API key from the dashboard.
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
}'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);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