Canada Routing Number Validation
A Canadian routing number identifies the financial institution and the branch (transit) that hold a bank account. Together with the account number it's what you need to send a direct deposit, pre-authorized debit or EFT payment within Canada.
The same routing number is written in two different ways depending on where it's used, and mixing them up is the most common source of errors.
Paper (MICR) format - printed on cheques as XXXXX-YYY, transit number first. For example, 24182-001:
- 24182 - transit (branch) number
- 001 - financial institution number (001 is Bank of Montreal)
Electronic (EFT) format - used in payroll and direct-deposit files as nine digits 0YYYXXXXX: a leading zero, the institution number, then the transit number. The same branch as above is 000124182.
What the API checks
- Format - the routing number must match either
XXXXX-YYY(with the dash) or the nine-digit EFT form starting with0. Both are accepted and converted to the paper format, so000124182and24182-001return the same branch. Anything else returns400 Invalid Canada Routing Number. - Existence - the transit and institution pair must be listed in the Payments Canada directory. A well-formed but unknown routing number returns
404.
Canadian routing numbers have no check digit, unlike US ABA numbers, so the directory lookup is the only way to catch a mistyped digit.
How to validate a Canada routing number
To start using our Fin Codes API sign up here and create your API key. Pass this key as a bearer token in the Authorization HTTP header, e.g. Authorization: Bearer your-api-key-here.
To validate a routing number call /v2/crn/{routing_number} endpoint using HTTP client of your preference, i.e.:
curl 'https://api.fincodesapi.com/v2/crn/24182-001' \
--header 'Authorization: Bearer your-api-key-here' \
--header 'Accept: application/json'
# INSTALLATION
$ composer require guzzlehttp/guzzle
# REQUEST
<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.fincodesapi.com/v2/crn/24182-001', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer your-api-key-here',
],
]);
echo $response->getBody();
# INSTALLATION
$ python -m pip install requests
# REQUEST
import requests
url = "https://api.fincodesapi.com/v2/crn/24182-001"
headers = {
"Accept": "application/json",
"Authorization": "Bearer your-api-key-here"
}
response = requests.request("GET", url, headers=headers)
print(response.text)
# INSTALLATION
$ npm install node-fetch --save
// REQUEST
import fetch from 'node-fetch';
const url = 'https://api.fincodesapi.com/v2/crn/24182-001';
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer your-api-key-here'
}
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
const options = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer your-api-key-here'
}
};
fetch('https://api.fincodesapi.com/v2/crn/24182-001', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
The response should be:
{
"success": true,
"data": {
"id": "24182-001",
"branch_name": "King & University",
"address": "200 King St. W.",
"city": "Toronto",
"province": "ON",
"postcode": "M5H 3T4",
"institution_type": 1,
"bank": {
"id": "2a8e87fd-ba6f-443f-a437-c59081730566",
"country_id": "CA",
"code": "001",
"name": "BANK OF MONTREAL"
}
}
}
Response fields
id- the routing number inXXXXX-YYYformbranch_name,address,city,province,postcode- the branch's locationinstitution_type- 1 for banks, 2 for credit unions and caisses populaires, 3 for trust companies, loan companies and other deposit-taking institutionsbank- the financial institution identified by the three-digit institution number
Common mistakes
- Swapping the order between formats - the paper format puts the transit first, the EFT format puts the institution first. Reading a cheque and typing the digits straight into an EFT field gives a different, usually invalid, number.
- Dropping the leading zero - the EFT format always starts with
0. Without it the number is eight digits and won't be accepted. - Confusing it with a US routing number - US ABA routing numbers are also nine digits and can also start with
0, so a nine-digit number on its own doesn't tell you the country. Confirm the account is Canadian first, and use the US routing number endpoint for those.
Where the data comes from
Routing numbers are imported from the financial institution directory published by Payments Canada and are refreshed weekly.
You can find full documentation here.