Get a Statistics Canada table by its id

Narwhal API reads a Statistics Canada series by vector id, such as statcan:v41690973. A Statistics Canada table id such as 10-10-0106-01 finds the table in the catalogue search. Read the vector number for your chosen series from the table's page at statcan.gc.ca, then pass it to the series route. There is no route that lists a table's vectors yet. The catalogue search returns table entries, so keep the table number and the series vector number separate as you work.

Do it with the API

  1. Set your API key Put your Narwhal API key in NARWHAL_API_KEY and install the Python requests library. Each Python example reads the key from that environment variable and sends it in the Authorization header. Run the examples in the same shell where you set the variable. You can create an account if you need a key.
    Prepare your shell
    export NARWHAL_API_KEY="YOUR_API_KEY"
    python -m pip install requests
  2. Search for the table Search with q and source=statcan. Use the table number when you have it, or search by a subject such as consumer price. Print the title, frequency, first period and last period to check the result. The catalogue search is open on every plan and makes no call to Statistics Canada. A table search result has the template statcan:v{vector}; you still need the series vector number.
    Find a Statistics Canada table
    import os
    import requests
    
    response = requests.get(
        "https://api.narwhalapi.com/v1/economics/catalogue",
        headers={"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"},
        params={"q": "10-10-0106-01", "source": "statcan", "limit": 25},
        timeout=10,
    )
    response.raise_for_status()
    for table in response.json()["results"]:
        print(
            table["title"],
            table["frequency"],
            table.get("first_period"),
            table.get("last_period"),
            sep=" | ",
        )
  3. Copy the series vector number Read the table number from the result's title. For example, the consumer price search includes a monthly result whose title contains Statistics Canada table 10-10-0106-01. Open the page of the table you chose at statcan.gc.ca and copy the vector number for the series you want. A vector looks like v followed by digits, such as v41690973. Add the statcan: prefix for the API request. The table number identifies the table; the vector identifies the series you will read.
  4. Check the series definition Send the full series id in the id query parameter. Check the returned title, frequency and unit_label before you use its values. For statcan:v41690973, the title is Canada;All-items, the frequency is monthly and the unit label is 2002=100. The response also carries attribution and a licence URL. Keep those details with any data you retain or display.
    Read the vector definition
    import os
    import requests
    
    response = requests.get(
        "https://api.narwhalapi.com/v1/economics/catalogue/series",
        headers={"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"},
        params={"id": "statcan:v41690973"},
        timeout=10,
    )
    response.raise_for_status()
    series = response.json()
    for field in ("id", "title", "frequency", "unit_label", "attribution", "licence_url"):
        print(f"{field}: {series[field]}")
  5. Read several latest values together For several vectors, send their full ids as one comma-separated ids parameter to the latest route. A batch accepts up to 50 distinct ids and is charged in one step, with one call per series returned. The example starts with v41690973, the Canada all-items consumer price index, which comes from table 18-10-0004-01. Add the other vector numbers you copied to the list, then inspect both the returned observations and the missing list.
    Batch latest vector values
    import os
    import requests
    
    vectors = ["v41690973"]  # Add other vector numbers copied from table pages.
    ids = list(dict.fromkeys(f"statcan:{vector}" for vector in vectors))
    if not 1 <= len(ids) <= 50:
        raise ValueError("Supply between 1 and 50 distinct series ids")
    
    response = requests.get(
        "https://api.narwhalapi.com/v1/economics/catalogue/latest",
        headers={"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"},
        params={"ids": ",".join(ids)},
        timeout=10,
    )
    response.raise_for_status()
    data = response.json()
    for observation in data["observations"]:
        print(observation["id"], observation["period"], observation["value"])
    print("Missing:", data["missing"])
  6. Read history and calculate the monthly change Use the observations route for a period range. Start and end are inclusive and must use the same period format; monthly series use YYYY-MM. This complete example requests July through September 2026 and calculates September's change from August. Values arrive as decimal strings, so the calculation uses Decimal. The printed result is rounded to two decimal places.
    Calculate the CPI month-on-month change
    import os
    from decimal import Decimal
    import requests
    
    response = requests.get(
        "https://api.narwhalapi.com/v1/economics/catalogue/series/observations",
        headers={"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"},
        params={
            "id": "statcan:v41690973",
            "start": "2026-07",
            "end": "2026-09",
            "limit": 100,
        },
        timeout=10,
    )
    response.raise_for_status()
    series = response.json()
    values = {}
    for observation in series["observations"]:
        values[observation["period"]] = Decimal(observation["value"])
        print(
            observation["period"],
            observation["value"],
            observation.get("released_on", ""),
            observation.get("status", ""),
        )
    
    change = (values["2026-09"] / values["2026-08"] - Decimal("1")) * Decimal("100")
    print(f"September 2026 month-on-month change: {change:.2f}%")

Calculate a monthly change from the CPI vector

The captured response for statcan:v41690973 contains these Canada all-items CPI observations. Each row has an observation period, a decimal value and a release date. Keep the release date separate from the month the value describes.

PeriodCPI, 2002=100Released
2026-07169.917 August 2026
2026-08169.814 September 2026
2026-09170.019 October 2026

September's month-on-month change is (170.0 / 169.8 - 1) * 100, or approximately 0.1178%. Rounded to two decimal places, the result is 0.12%. The calculation compares consecutive monthly index levels. The returned seasonal_adjustment is not_stated, so preserve that label alongside the result.

Statistics Canada responses carry the Open Government Licence - Canada attribution and licence URL. The series has no revision history or vintages. History access follows your plan: Free has the last 12 months, Basic the last 5 years, and Pro full history. See the series API reference for pagination and plans for access limits.

Which Statistics Canada series are not available?

Daily, weekly, multi-year, fiscal-year and fiscal-quarter vectors return 404 not_found. Narwhal supports monthly, quarterly and annual Statistics Canada vectors. Check the frequency in the catalogue result before you copy a vector number from the table page.

A malformed vector id returns 400 invalid_series_id. Its detail says that a Statistics Canada series id is v<vector number>. Pass the complete id, such as statcan:v41690973, through the id parameter. See API errors for error handling.

How do I read the status of a value?

Read the optional status field on each observation. It is present when a value has a status such as provisional or estimated. Preserve it with the period and value so a calculation retains that context.

Keep released_on when present, and use fetched_at for the retrieval timestamp. A response has stale: true only when Narwhal serves its last kept copy because the source was unreachable. Observation status and response freshness describe separate properties.

Published .

Next steps