Find an API

Search public APIs with auth details & Postman guides

← All APIs

Canada Post Developer API

canadapost-postescanada.ca · Government

Government Basic Auth Free Tier Government Retail & E-Commerce Transportation & Logistics Shipping Address Validation Postal Code

Canada Post's official developer API suite covering address complete (autocomplete and validation), postal code lookup, rating (shipping rates), shipment creation, manifesting, and parcel tracking. Used by e-commerce platforms, logistics applications, and insurance companies for address standardization and delivery verification. Requires a Canada Post account. REST and SOAP interfaces available.

Authentication

Basic Auth HTTP Basic authentication with your Canada Post username and API key (password). Register at canadapost.ca/cpotools/apps/drc/home?execution=e3s1 to receive credentials.

Sample Requests

POST Get shipping rates

Returns available shipping rates for a parcel from an origin postal code to a destination postal code. Includes service name, price, and delivery time.

https://ct.soa-gw.canadapost.ca/rs/2.0/mailing/rates

Hover any highlighted part to learn what it does

Headers — extra info sent with the request
Accept application/vnd.cpc.ship.rate-v4+xml
Content-Type application/vnd.cpc.ship.rate-v4+xml
Authorization Basic BASE64_USER_APIKEY
Request Body — data you're sending
"<mailing-scenario xmlns=\"http://www.canadapost.ca/ws/ship/rate-v4\"><customer-number>1234567</customer-number><parcel-characteristics><weight>1.5</weight></parcel-characteristics><origin-postal-code>K1A0B1</origin-postal-code><destination><domestic><postal-code>M5H2N2</postal-code></domestic></destination></mailing-scenario>"
curl -X POST "https://ct.soa-gw.canadapost.ca/rs/2.0/mailing/rates" \
  -H "Accept: application/vnd.cpc.ship.rate-v4+xml" \
  -H "Content-Type: application/vnd.cpc.ship.rate-v4+xml" \
  -H "Authorization: Basic YOUR_BASE64_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '"<mailing-scenario xmlns=\"http://www.canadapost.ca/ws/ship/rate-v4\"><customer-number>1234567</customer-number><parcel-characteristics><weight>1.5</weight></parcel-characteristics><origin-postal-code>K1A0B1</origin-postal-code><destination><domestic><postal-code>M5H2N2</postal-code></domestic></destination></mailing-scenario>"'
import requests
headers = {
    "Accept": "application/vnd.cpc.ship.rate-v4+xml",
    "Content-Type": "application/vnd.cpc.ship.rate-v4+xml",
    "Authorization": "Basic YOUR_BASE64_CREDENTIALS"
}
data = "<mailing-scenario xmlns=\"http://www.canadapost.ca/ws/ship/rate-v4\"><customer-number>1234567</customer-number><parcel-characteristics><weight>1.5</weight></parcel-characteristics><origin-postal-code>K1A0B1</origin-postal-code><destination><domestic><postal-code>M5H2N2</postal-code></domestic></destination></mailing-scenario>"
response = requests.post(
    "https://ct.soa-gw.canadapost.ca/rs/2.0/mailing/rates",
    headers=headers,
    json=data,
)
print(response.json())
const url = 'https://ct.soa-gw.canadapost.ca/rs/2.0/mailing/rates';

const response = await fetch(url, {
  method: 'POST',
  headers: {
    'Accept': 'application/vnd.cpc.ship.rate-v4+xml',
    'Content-Type': 'application/vnd.cpc.ship.rate-v4+xml',
    'Authorization': 'Basic YOUR_BASE64_CREDENTIALS'
  },
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify("<mailing-scenario xmlns=\"http://www.canadapost.ca/ws/ship/rate-v4\"><customer-number>1234567</customer-number><parcel-characteristics><weight>1.5</weight></parcel-characteristics><origin-postal-code>K1A0B1</origin-postal-code><destination><domestic><postal-code>M5H2N2</postal-code></domestic></destination></mailing-scenario>"),
}); 
const data = await response.json();
console.log(data);
package main

import (
	"fmt"
	"io"
	"net/http"
	"bytes"
	"encoding/json"
)

func main() {
	targetURL := "https://ct.soa-gw.canadapost.ca/rs/2.0/mailing/rates"
	jsonData, _ := json.Marshal("<mailing-scenario xmlns=\"http://www.canadapost.ca/ws/ship/rate-v4\"><customer-number>1234567</customer-number><parcel-characteristics><weight>1.5</weight></parcel-characteristics><origin-postal-code>K1A0B1</origin-postal-code><destination><domestic><postal-code>M5H2N2</postal-code></domestic></destination></mailing-scenario>")
	req, _ := http.NewRequest("POST", targetURL, bytes.NewBuffer(jsonData))
	req.Header.Set("Accept", "application/vnd.cpc.ship.rate-v4+xml")
	req.Header.Set("Content-Type", "application/vnd.cpc.ship.rate-v4+xml")
	req.Header.Set("Authorization", "Basic YOUR_BASE64_CREDENTIALS")
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, _ := client.Do(req)
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}
require "net/http"
require "json"

uri = URI("https://ct.soa-gw.canadapost.ca/rs/2.0/mailing/rates")

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"

req = Net::HTTP::Post.new(uri)
req["Accept"] = "application/vnd.cpc.ship.rate-v4+xml"
req["Content-Type"] = "application/vnd.cpc.ship.rate-v4+xml"
req["Authorization"] = "Basic YOUR_BASE64_CREDENTIALS"
req["Content-Type"] = "application/json"
req.body = "\"<mailing-scenario xmlns=\\\"http://www.canadapost.ca/ws/ship/rate-v4\\\"><customer-number>1234567</customer-number><parcel-characteristics><weight>1.5</weight></parcel-characteristics><origin-postal-code>K1A0B1</origin-postal-code><destination><domestic><postal-code>M5H2N2</postal-code></domestic></destination></mailing-scenario>\""

res = http.request(req)
puts JSON.parse(res.body)
<?php
$url = "https://ct.soa-gw.canadapost.ca/rs/2.0/mailing/rates";
$opts = ["http" => [
    "method" => "POST",
    "header" => implode("\r\n", [
        "Accept: application/vnd.cpc.ship.rate-v4+xml",
        "Content-Type: application/vnd.cpc.ship.rate-v4+xml",
        "Authorization: Basic YOUR_BASE64_CREDENTIALS",
        "Content-Type: application/json"
    ]),
    "content" => json_encode("<mailing-scenario xmlns=\"http://www.canadapost.ca/ws/ship/rate-v4\"><customer-number>1234567</customer-number><parcel-characteristics><weight>1.5</weight></parcel-characteristics><origin-postal-code>K1A0B1</origin-postal-code><destination><domestic><postal-code>M5H2N2</postal-code></domestic></destination></mailing-scenario>"),
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));
GET Track shipment

Returns tracking events and current status for a Canada Post shipment. Supports domestic and international tracking.

https://ct.soa-gw.canadapost.ca/rs/2.0/tracking/{trackingNumber}/detail

Hover any highlighted part to learn what it does

Headers — extra info sent with the request
Accept application/vnd.cpc.track-v2+xml
Authorization Basic BASE64_USER_APIKEY
curl -X GET "https://ct.soa-gw.canadapost.ca/rs/2.0/tracking/{trackingNumber}/detail" \
  -H "Accept: application/vnd.cpc.track-v2+xml" \
  -H "Authorization: Basic YOUR_BASE64_CREDENTIALS"
import requests
headers = {
    "Accept": "application/vnd.cpc.track-v2+xml",
    "Authorization": "Basic YOUR_BASE64_CREDENTIALS"
}
response = requests.get(
    "https://ct.soa-gw.canadapost.ca/rs/2.0/tracking/{trackingNumber}/detail",
    headers=headers,
)
print(response.json())
const url = 'https://ct.soa-gw.canadapost.ca/rs/2.0/tracking/{trackingNumber}/detail';

const response = await fetch(url, {
  headers: {
    'Accept': 'application/vnd.cpc.track-v2+xml',
    'Authorization': 'Basic YOUR_BASE64_CREDENTIALS'
  },
}); 
const data = await response.json();
console.log(data);
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	targetURL := "https://ct.soa-gw.canadapost.ca/rs/2.0/tracking/{trackingNumber}/detail"
	req, _ := http.NewRequest("GET", targetURL, nil)
	req.Header.Set("Accept", "application/vnd.cpc.track-v2+xml")
	req.Header.Set("Authorization", "Basic YOUR_BASE64_CREDENTIALS")

	client := &http.Client{}
	resp, _ := client.Do(req)
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}
require "net/http"
require "json"

uri = URI("https://ct.soa-gw.canadapost.ca/rs/2.0/tracking/{trackingNumber}/detail")

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"

req = Net::HTTP::Get.new(uri)
req["Accept"] = "application/vnd.cpc.track-v2+xml"
req["Authorization"] = "Basic YOUR_BASE64_CREDENTIALS"

res = http.request(req)
puts JSON.parse(res.body)
<?php
$url = "https://ct.soa-gw.canadapost.ca/rs/2.0/tracking/{trackingNumber}/detail";
$opts = ["http" => [
    "method" => "GET",
    "header" => implode("\r\n", [
        "Accept: application/vnd.cpc.track-v2+xml",
        "Authorization: Basic YOUR_BASE64_CREDENTIALS"
    ]),
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));

Postman Setup Guide

Get Postman ↗
  1. Register at canadapost.ca developer portal to get API credentials (username + API key)
  2. Canada Post API uses XML request/response bodies — not JSON. Content-Type is vendor-specific.
  3. Base64 encode "username:apiKey" for the Authorization: Basic header
  4. Three environments: Sandbox (ct.soa-gw.canadapost.ca), Production (soa-gw.canadapost.ca)
  5. Address Complete API (separate): https://ws1.postescanada-canadapost.ca/AddressComplete/Interactive/
  6. Tracking API base: https://ct.soa-gw.canadapost.ca/vis/track/
  7. Rate API requires your Canada Post customer number in the URL path

What can you build with Canada Post Developer API?

Canada Post Developer API is a Government API. Developers commonly use government APIs for:

  • surfacing public datasets in citizen-facing apps
  • building transparency and civic engagement tools
  • accessing legislation, court records, and official data
  • powering research and journalism tools
  • creating compliance and regulatory monitoring dashboards

Basic authentication. Send your username and password (Base64-encoded) in the Authorization header. Always use HTTPS — Basic auth over plain HTTP exposes your credentials. Canada Post Developer API is free to use up to a usage limit, making it a low-risk choice to experiment with.

New to APIs? Read our beginner's guide · Learn about API keys · What is REST?

Open documentation ↗