Canada Post AddressComplete API allows a user to search for an address within Canada and other countries. Within Canada results can be in both English and French languages. There are two ways to invoke Canada Post API:
- To embed css and JavaScript flies that can be copy and pasted from the Canada Post website
- To directly call Canada Post API
API setup prerequisites
To be able to call Canada Post AddressComplete API there is a need to setup an account with Canada Post which will provide you with an API Key and also allow you to configure particular URLs to be able to issue search requests using that API Key.
This API Key is for all intents and purposes public, since it can be easily discovered by looking at the API calls in the Network tab in a browser’s developer tools. What prevents this API Key from being used by 3rd parties is assigning it to particular URLs that it can be called from and adding rate limiting and other options as discussed here.
Embedded css and JavaScript files
One way to integrate with Canada Post API is to add the following three tags in the head tag of the index.html page of the project.
<head>
<link rel="stylesheet" type="text/css" href="https://ws1.postescanada-canadapost.ca/css/addresscomplete-2.30.min.css?key=<Your API key comes here>" />
<script type="text/javascript" src="https://ws1.postescanada-canadapost.ca/js/addresscomplete-2.30.min.js?key=<Your API key comes here>"></script>
<script type="text/javascript">
var fields = [
{ element: "street", field: "Line1" },
{ element: "city", field: "City", mode: pca.fieldMode.POPULATE },
{ element: "province", field: "ProvinceName", mode: pca.fieldMode.POPULATE },
{ element: "postcode", field: "PostalCode" },
{ element: "country", field: "CountryName", mode: pca.fieldMode.COUNTRY }
],
options = {
key: "YD42-FH68-UZ69-CY67"
},
control = new pca.Address(fields, options);
</script>
...
</head>
Where the css link provides the styling for the Canada Post API script added in the script tag and the second script provides the mapping from the form fields in which you want to use Address Search to the existing fields in the Canada Post API script. More details about how the mapping is done can be found here.
Direct call to Canada Post API
It is also possible to integrate directly with the Canada Post API using their official documentation by using two Find and Retrieve endpoints they expose. More details about each endpoint will be provide below.
Address Lookup Flow
There can be a number of possible scenarios while using Canada Post AddressCompleet API to search for an address. For example, issuing a Find request will return a list of addresses that are similar to the search term used by a user.
Also, what is important each address in that list contains a Next field which can have one of two options: Find or Retrieve. This field is important when one of the search results is a street that has a number of houses or an apartment building with a number of apartments. In this case such an address will have Next field with Find value.
Possible search flow scenarios
Scenario | First endpoint call | Next Action (call) | Result | Notes | |
1 | Look up of a single existing address | Find | Retrieve | Detailed address returned by the Retrieve request | |
2 | Look up of a street or an apartment building address | Find | Find with LastId value from the first call | List of houses/apartments | In this case there is a need to issue additional Retrieve request to get a detailed address. |
3 | Look up of a specific address by ID from Find request result | Retrieve | N/A | Detailed address returned by the Retrieve request |
Find request
https://ws1.postescanada-canadapost.ca/addresscomplete/interactive/find/v2.10/json3.ws
Find request endpoint is described in this official page. Its purpose is to look up addresses similar to the search term provided by the user. This endpoint has the following parameters
NAME | Mandatory | TYPE | DEFAULT | DESCRIPTION | Notes |
Key | Yes | String | API Key | ||
SearchTerm | Yes | String | The search term to find. If the LastId is provided, the SearchTerm searches within the results from the LastId. | URL encoded | |
LastId | No | String | The Id from a previous Find or FindByPosition. | URL encoded | |
Country | No | String | CAN | The name or ISO 2 or 3 character code for the country to search in. Most country names will be recognised but the use of the ISO country code is recommended for clarity. | |
LanguagePreference | No | String | en | The 2 or 4 character language preference identifier e.g. (en, en-gb, en-us etc). | |
MaxSuggestions | No | Integer | 7 | The maximum number of autocomplete suggestions to return. |
It is possible to submit request to this endpoint for free using Canada Post website.
Example request:
https://ws1.postescanada-canadapost.ca/AddressComplete/Interactive/Find/v2.10/json3.ws?Key=<your< API Key comes here>&SearchTerm=390&Country=CAN
Response body
The response consists of Items list with addresses as elements.
Pay attention, as described in the possible flows above, if returned address element contains Next field with the value Find it means that to get detailed address there is a need to issue additional Find request with the LastId set with the Id value from that address element.
For example,
First Find request with Search Term: 234 Drinkwater St
https://ws1.postescanada-canadapost.ca/AddressComplete/Interactive/Find/2.1/json.ws?key=zz99-jd77-nf54-xw26&SearchTerm=234%20Drinkwater%20St
Response:
{
"Items": [
{
"Id": "CA|CP|ENG|ON-SUDBURY-DRINKWATER_ST-234",
"Text": "234 Drinkwater St",
"Highlight": "0-3,4-17",
"Cursor": "0",
"Description": "Sudbury, ON, P3E 3E5 - 7 Addresses",
"Next": "Find"
},
{
"Id": "CA|CP|A|802566926",
"Text": "234 Drinkwater St",
"Highlight": "0-3,4-17",
"Cursor": "0",
"Description": "Sudbury, ON, P3E 3E5",
"Next": "Retrieve"
}
]
}
Second Find request with LastId set to CA|CP|ENG|ON-SUDBURY-DRINKWATER_ST-234
because first result element had Next : Find.
https://ws1.postescanada-canadapost.ca/AddressComplete/Interactive/Find/2.1/json.ws?key=zz99-jd77-nf54-xw26&SearchTerm=234%20Drinkwater%20St&LastId=CA%7CCP%7CENG%7CON-SUDBURY-DRINKWATER_ST-234
Response:
{
"Items": [
{
"Id": "CA|CP|A|9494373",
"Text": "1-234 Drinkwater St",
"Highlight": "",
"Cursor": "0",
"Description": "Sudbury, ON, P3E 3E5",
"Next": "Retrieve"
},
{
"Id": "CA|CP|A|17427664",
"Text": "2-234 Drinkwater St",
"Highlight": "",
"Cursor": "0",
"Description": "Sudbury, ON, P3E 3E5",
"Next": "Retrieve"
},
{
"Id": "CA|CP|A|17427672",
"Text": "6-234 Drinkwater St",
"Highlight": "",
"Cursor": "0",
"Description": "Sudbury, ON, P3E 3E5",
"Next": "Retrieve"
},
{
"Id": "CA|CP|A|22742122",
"Text": "9-234 Drinkwater St",
"Highlight": "",
"Cursor": "0",
"Description": "Sudbury, ON, P3E 3E5",
"Next": "Retrieve"
}
]
}
Responses Fields
The response from the web service is a table containing the elements below. Where no items are found, the response will be empty list (although all endpoints specify the columns). If an error occurs, the response will be an error table instead.
NAME | TYPE | DESCRIPTION | VALUES | EXAMPLE |
Id | String | The Id to be used as the LastId with the Find method. | CAN|PR|X247361852|E|0|0 | |
Text | String | The found item. | 2701 Riverside Dr, Ottawa, ON | |
Highlight | String | A list of number ranges identifying the characters to highlight in the Text response (zero-based start position and end). | 0-2,6-4 | |
Cursor | Integer | A zero-based position in the Text response indicating the suggested position of the cursor if this item is selected. A -1 response indicates no suggestion is available. | 0 | |
Description | String | Descriptive information about the found item, typically if it’s a container. | 102 Streets | |
Next | String | The next step of the search process. | Find or Retrieve | Retrieve |
Example of response
{
"Items": [
{
"Id": "CA|CP|A|17427672",
"Text": "6-234 Drinkwater St",
"Highlight": "",
"Cursor": "0",
"Description": "Sudbury, ON, P3E 3E5",
"Next": "Retrieve"
},
{
"Id": "CA|CP|A|22742122",
"Text": "9-234 Drinkwater St",
"Highlight": "",
"Cursor": "0",
"Description": "Sudbury, ON, P3E 3E5",
"Next": "Retrieve"
}
]
}
Since we are talking about web service here the errors that it returns are returned with 200 response while the error itself is contained in the body of the response. Details about all possible errors can be found on Canda Post website.
Example of an error response
For example, the general error below is shown when the API Key is not assigned to get requests from a particular URL.
{
"Items": [
{
"Error": "5",
"Description": "Request not allowed from this URL",
"Cause": "The request was disallowed from the URL.",
"Resolution": "Check the security settings on the key first. If they look fine, please contact
support as it may be from a URL on our blacklist."
}
]
}
Retrieve endpoint
https://ws1.postescanada-canadapost.ca/addresscomplete/interactive/retrieve/v2.11/json3.ws
Retrieve endpoint returns the full address details based on the Id, which is returned as a result of the Find request.
As was mentioned in the possible flows section above, initial Find request returns a list of addresses that closely match the search term used by the user. Each address contains an Id field. This Id should be used to issue Retrieve request. You can try the request for free on Canada Post website.
Parameters
Each request to the web service requires the following parameters. You can create any number of keys, each of which can be reported on individually and have specific security settings.
NAME | TYPE | Mandatory | DESCRIPTION | DEFAULT | EXAMPLE | Notes |
Key | String | Yes | The key to use to authenticate to the service. | AA11-AA11-AA11-AA11 | ||
Id | String | Yes | The Id from a Find method to retrieve the details for. | CAN|1520704 | Should be URL encoded |
Example of the request
https://ws1.postescanada-canadapost.ca/AddressComplete/Interactive/Retrieve/2.11/json.ws?key=tf36-ku97-ab94-zc85&Id=CA%7CCP%7CA%7C9494373
Response body
The response consists of Items list with two elements: first element is the address in English, second element is the address in French.
Response Fields
The response from the web service is a table containing the elements below. Where no items are found, the response will be empty list (although all endpoints specify the columns). If an error occurs, the response will be an error table instead.
NAME | TYPE | DESCRIPTION | VALUES | EXAMPLE |
Id | String | |||
DomesticId | String | |||
Language | String | |||
LanguageAlternatives | String | |||
Department | String | |||
Company | String | |||
SubBuilding | String | |||
BuildingNumber | String | |||
BuildingName | String | |||
SecondaryStreet | String | |||
Street | String | |||
Block | String | |||
Neighbourhood | String | |||
District | String | |||
City | String | |||
Line1 | String | |||
Line2 | String | |||
Line3 | String | |||
Line4 | String | |||
Line5 | String | |||
AdminAreaName | String | |||
AdminAreaCode | String | |||
Province | String | |||
ProvinceName | String | |||
ProvinceCode | String | |||
PostalCode | String | |||
CountryName | String | |||
CountryIso2 | String | |||
CountryIso3 | String | |||
CountryIsoNumber | Integer | |||
SortingNumber1 | String | |||
SortingNumber2 | String | |||
Barcode | String | |||
POBoxNumber | String | |||
Label | String | |||
DataLevel | String | Unknown Premise RangedPremise Street City |
Example of a response
{
"Items": [
{
"Id": "CA|CP|A|9494373",
"DomesticId": "9494373",
"Language": "ENG",
"LanguageAlternatives": "ENG,FRE",
"Department": "",
"Company": "",
"SubBuilding": "1",
"BuildingNumber": "234",
"BuildingName": "",
"SecondaryStreet": "",
"Street": "Drinkwater St",
"Block": "",
"Neighbourhood": "",
"District": "",
"City": "Sudbury",
"Line1": "1-234 Drinkwater St",
"Line2": "",
"Line3": "",
"Line4": "",
"Line5": "",
"AdminAreaName": "",
"AdminAreaCode": "",
"Province": "ON",
"ProvinceName": "Ontario",
"ProvinceCode": "ON",
"PostalCode": "P3E 3E5",
"CountryName": "Canada",
"CountryIso2": "CA",
"CountryIso3": "CAN",
"CountryIsoNumber": "124",
"SortingNumber1": "",
"SortingNumber2": "",
"Barcode": "",
"POBoxNumber": "",
"Label": "1-234 Drinkwater St\nSUDBURY ON P3E 3E5\nCANADA",
"Type": "Residential",
"DataLevel": "Premise",
"AcIlrc": "R",
"AcUm": "1"
},
{
"Id": "CA|CP|A|9494373",
"DomesticId": "9494373",
"Language": "FRE",
"LanguageAlternatives": "ENG,FRE",
"Department": "",
"Company": "",
"SubBuilding": "1",
"BuildingNumber": "234",
"BuildingName": "",
"SecondaryStreet": "",
"Street": "Rue Drinkwater",
"Block": "",
"Neighbourhood": "",
"District": "",
"City": "Sudbury",
"Line1": "1-234 Rue Drinkwater",
"Line2": "",
"Line3": "",
"Line4": "",
"Line5": "",
"AdminAreaName": "",
"AdminAreaCode": "",
"Province": "ON",
"ProvinceName": "Ontario",
"ProvinceCode": "ON",
"PostalCode": "P3E 3E5",
"CountryName": "Canada",
"CountryIso2": "CA",
"CountryIso3": "CAN",
"CountryIsoNumber": "124",
"SortingNumber1": "",
"SortingNumber2": "",
"Barcode": "",
"POBoxNumber": "",
"Label": "1-234 Rue Drinkwater\nSUDBURY ON P3E 3E5\nCANADA",
"Type": "Residential",
"DataLevel": "Premise",
"AcIlrc": "R",
"AcUm": "1"
}
]
}
Response Errors
Below are the errors specific to this web service. If an error occurs, an error table like the one below (but containing a single row) will be returned. (Developers should test for a 4-column table with columns “Error”, “Description”, “Cause” and “Resolution”.)
ERROR | DESCRIPTION | CAUSE | RESOLUTION |
1001 | Id Invalid | The Id parameter supplied was invalid. | Try again, using only IDs from the Find services. |
1002 | Not Available | This record contains data that is not available on your account. | Please contact support to upgrade your account. |
Example of an error response
For example, the general error below is shown when the account has no money balance to allow for queries.
{
"Items": [
{
"Error": "3",
"Description": "Account out of credit",
"Cause": "Your account is either out of credit or has insufficient credit to service this request.",
"Resolution": "Please check your account balance and top it up if necessary."
}
]
}
References
This is a github repository containing React with classes implementation of two possible ways to integrate with Canada Post AddressComplete API as was explained before. Pay attention that to install the dependencies there is a need to use yarn.