# Datasets: API reference

6 endpoints. Base URL `https://princegeorgepulse.ca/api/v1`. Conventions (envelope, paging, fields, formats, limits) are on the [overview](https://princegeorgepulse.ca/developers/). [All endpoints](https://princegeorgepulse.ca/developers/reference/).

## GET /api/v1/datasets {#get-datasets}

Index of every reference dataset behind the dashboards, with where it comes from and how fresh it is.

`kind` is `fetched` (refreshed from an official machine-readable source by a scheduled job) or `seed` (hand-compiled from PDFs or web pages; `reason` says why). `stale` is true when a fetched dataset has not been confirmed recently.

- Cache: 1 h
- Source: [PG Pulse](https://princegeorgepulse.ca)
- Licence: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

Also accepts `fields` (sparse fieldset) and `format` (`json`, `md`).

**Example request**

```bash
curl "https://princegeorgepulse.ca/api/v1/datasets"
```

**Example response** (trimmed)

```json
{
  "data": [
    {
      "id": "population",
      "title": "Population estimates and census counts",
      "group": "People",
      "kind": "fetched",
      "origin": "job",
      "asOf": "2025-07-01",
      "fetchedAt": "2026-10-01T04:27:01.020Z",
      "checkedAt": "2026-10-01T04:27:01.020Z",
      "stale": false,
      "available": true,
      "source": "Statistics Canada, table 17-10-0155, Population estimates, July 1, by census subdivision, 2021 boundaries",
      "sourceUrl": "https://www150.statcan.gc.ca/t1/tbl1/en/tv.action?pid=1710015501",
      "…": "4 more keys"
    },
    {
      "id": "labour-force",
      "title": "Labour force survey: employment, unemployment, participation",
      "group": "Economy",
      "kind": "fetched",
      "origin": "job",
      "asOf": "2026-09",
      "fetchedAt": "2026-10-12T13:20:13.809Z",
      "checkedAt": "2026-10-12T13:20:13.809Z",
      "stale": false,
      "available": true,
      "source": "Statistics Canada, Labour Force Survey",
      "sourceUrl": "https://www150.statcan.gc.ca/t1/tbl1/en/tv.action?pid=1410046401",
      "…": "4 more keys"
    },
    "… 67 more"
  ],
  "meta": {
    "source": "PG Pulse",
    "sourceUrl": "https://princegeorgepulse.ca",
    "updatedAt": null,
    "license": "CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)",
    "attribution": "PG Pulse (princegeorgepulse.ca)"
  },
  "links": {
    "self": "/api/v1/datasets",
    "next": null,
    "docs": "/developers/reference/datasets/#get-datasets"
  }
}
```

## GET /api/v1/datasets/{id} {#get-datasets-id}

One reference dataset, exactly as the site uses it.

- Cache: 1 h
- Source: [PG Pulse](https://princegeorgepulse.ca)
- Licence: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

| Parameter | In | Type | Description |
| --- | --- | --- | --- |
| `id` | path | string | Dataset id from /datasets. Required. Example: `population`. |

Also accepts `fields` (sparse fieldset) and `format` (`json`, `md`).

**Example request**

```bash
curl "https://princegeorgepulse.ca/api/v1/datasets/population"
```

**Example response** (trimmed)

```json
{
  "data": {
    "source": "Statistics Canada, table 17-10-0155, Population estimates, July 1, by census subdivision, 2021 boundaries",
    "sourceUrl": "https://www150.statcan.gc.ca/t1/tbl1/en/tv.action?pid=1710015501",
    "asOf": "2025-07-01",
    "geography": "Prince George, City (CY)",
    "notes": "Annual estimates for July 1, adjusted for census net undercoverage, so they run higher than census counts.",
    "estimates": [
      {
        "year": 2001,
        "value": 75413
      },
      {
        "year": 2002,
        "value": 74158
      },
      "… 23 more"
    ],
    "census": [
      {
        "year": 2016,
        "value": 74003
      },
      {
        "year": 2021,
        "value": 76708
      }
    ],
    "censusSource": "Statistics Canada, 2021 Census Profile"
  },
  "meta": {
    "source": "Statistics Canada, table 17-10-0155, Population estimates, July 1, by census subdivision, 2021 boundaries",
    "sourceUrl": "https://www150.statcan.gc.ca/t1/tbl1/en/tv.action?pid=1710015501",
    "updatedAt": "2026-10-01T04:27:01.020Z",
    "ageSec": 1318883,
    "license": "Statistics Canada Open Licence (https://www.statcan.gc.ca/en/reference/licence)",
    "attribution": "PG Pulse (princegeorgepulse.ca)",
    "dataset": "population",
    "kind": "fetched",
    "asOf": "2025-07-01",
    "checkedAt": "2026-10-01T04:27:01.020Z"
  },
  "links": {
    "self": "/api/v1/datasets/population",
    "next": null,
    "docs": "/developers/reference/datasets/#get-datasets-id"
  }
}
```

## GET /api/v1/datasets/{id}/records {#get-datasets-id-records}

A curated dataset as records (one per item: a place, a venue, a section), with when each was last changed.

Curated datasets (`kind: curated` in /datasets) are stored as records: list items have ids like `places/mcd-victoria`, other sections are one record each. Hidden records are left out.

- Cache: 1 h
- Source: [PG Pulse](https://princegeorgepulse.ca)
- Licence: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)
- Paginated: `limit` (default 100, max 500) and `offset`; also `format=csv`

| Parameter | In | Type | Description |
| --- | --- | --- | --- |
| `id` | path | string | Curated dataset id from /datasets. Required. Example: `late-night`. |
| `section` | query | string | Only one section (e.g. `places`). Example: `places`. |
| `limit` | query | integer | Items per page (default 50, max 500 unless noted). Example: `20`. |
| `offset` | query | integer | Items to skip. Use `links.next` to page. Example: `0`. |

Also accepts `fields` (sparse fieldset) and `format` (`json`, `md`, `csv`).

**Example request**

```bash
curl "https://princegeorgepulse.ca/api/v1/datasets/late-night/records?section=places"
```

**Example response** (trimmed)

```json
{
  "data": [
    {
      "id": "places/mcd-victoria",
      "data": {
        "id": "mcd-victoria",
        "name": "McDonald's, Victoria St",
        "group": "fast-food",
        "street": "2001 Victoria St",
        "area": "Van Bow",
        "slug": "pbr-enterprises-ltd-mcdonalds-restaurants",
        "hours": {
          "all": "06:00-20:00"
        },
        "drive": {
          "all": "24h"
        },
        "driveThru": true,
        "url": "https://www.mcdonalds.com/ca/en-ca/restaurant-locator.html",
        "source": "https://www.mcdonalds.com/ca/en-ca/restaurant-locator.html",
        "sourceNote": "McDonald's Canada restaurant locator, restaurant #10186"
      },
      "updatedAt": "2026-10-01T05:01:26.020Z",
      "corrected": false
    },
    {
      "id": "places/mcd-15th",
      "data": {
        "id": "mcd-15th",
        "name": "McDonald's, 15th Ave",
        "group": "fast-food",
        "street": "3310 15th Ave",
        "area": "West Bowl",
        "hours": {
          "all": "05:00-23:59"
        },
        "drive": {
          "all": "24h"
        },
        "driveThru": true,
        "url": "https://www.mcdonalds.com/ca/en-ca/restaurant-locator.html",
        "source": "https://www.mcdonalds.com/ca/en-ca/restaurant-locator.html",
        "sourceNote": "McDonald's Canada restaurant locator, restaurant #40179"
      },
      "updatedAt": "2026-10-01T05:01:26.020Z",
      "corrected": false
    },
    "… 31 more"
  ],
  "meta": {
    "source": "Each business’s own website or store locator (see each entry)",
    "sourceUrl": "https://princegeorgepulse.ca/food/",
    "updatedAt": "2026-10-01T05:01:26.020Z",
    "ageSec": 1316818,
    "license": "Facts (hours, addresses, services) copied from each business’s own published information, with a link to it",
    "attribution": "PG Pulse (princegeorgepulse.ca)",
    "dataset": "late-night",
    "asOf": "2026-09-30",
    "section": "places",
    "total": 33,
    "count": 33,
    "limit": 100,
    "…": "1 more keys"
  },
  "links": {
    "self": "/api/v1/datasets/late-night/records?section=places",
    "next": null,
    "docs": "/developers/reference/datasets/#get-datasets-id-records"
  }
}
```

## GET /api/v1/datasets/{id}/series {#get-datasets-id-series}

A statistics dataset as tidy rows: series, period, value (filter by series and period).

Every numeric time series in the dataset as one row per period. Without `series`, also lists the available series in `meta.series`. Periods are years (2025), months (2026-08) or dates.

- Cache: 1 h
- Source: [PG Pulse](https://princegeorgepulse.ca)
- Licence: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)
- Paginated: `limit` (default 1000, max 5000) and `offset`; also `format=csv`

| Parameter | In | Type | Description |
| --- | --- | --- | --- |
| `id` | path | string | Statistics dataset id from /datasets (kind fetched or seed). Required. Example: `housing-rents`. |
| `series` | query | string | One series (or a prefix: `averageRent` matches every unit type). Example: `averageRent.Two bedroom`. |
| `from` | query | string | First period (inclusive), e.g. 2015 or 2020-01. Example: `2015`. |
| `to` | query | string | Last period (inclusive). |
| `limit` | query | integer | Items per page (default 50, max 500 unless noted). Example: `20`. |
| `offset` | query | integer | Items to skip. Use `links.next` to page. Example: `0`. |

Also accepts `fields` (sparse fieldset) and `format` (`json`, `md`, `csv`).

**Example request**

```bash
curl "https://princegeorgepulse.ca/api/v1/datasets/housing-rents/series?series=vacancyRate&from=2015"
```

**Example response** (trimmed)

```json
{
  "data": [
    {
      "series": "vacancyRate",
      "period": "2015",
      "value": 4.4
    },
    {
      "series": "vacancyRate",
      "period": "2016",
      "value": 4.1
    },
    "… 9 more"
  ],
  "meta": {
    "source": "Canada Mortgage and Housing Corporation Rental Market Survey, via Statistics Canada table 34-10-0133 and 34-10-0128",
    "sourceUrl": "https://www150.statcan.gc.ca/t1/tbl1/en/tv.action?pid=3410013301",
    "updatedAt": "2026-10-01T04:27:12.099Z",
    "ageSec": 1318872,
    "license": "Statistics Canada Open Licence (https://www.statcan.gc.ca/en/reference/licence)",
    "attribution": "PG Pulse (princegeorgepulse.ca)",
    "dataset": "housing-rents",
    "asOf": "2025-10",
    "total": 11,
    "count": 11,
    "limit": 1000,
    "offset": 0
  },
  "links": {
    "self": "/api/v1/datasets/housing-rents/series?series=vacancyRate&from=2015",
    "next": null,
    "docs": "/developers/reference/datasets/#get-datasets-id-series"
  }
}
```

## GET /api/v1/media {#get-media}

Images hosted by PG Pulse: photo library, guide and dataset images, portraits, heritage photos and business screenshots, with alt text, credit and licence.

Every editorial image the site shows, as served from our media library: responsive WebP variants (and the metadata-free original where kept), alt text, caption, credit, author, licence and the file page to acquire a licence. Reuse each image under its own licence and credit it as given. News and event thumbnails are not listed.

- Cache: 1 h
- Source: [Each image’s own source and licence (see credit, licence and sourcePage on each item)](https://princegeorgepulse.ca/about/)
- Licence: Per image: the licence named on the item (Creative Commons, public domain, official portraits, screenshots of a business’s own site)
- Paginated: `limit` (default 100, max 500) and `offset`; also `format=csv`

| Parameter | In | Type | Description |
| --- | --- | --- | --- |
| `kind` | query | string | One of photos, guides, datasets, heritage, civic, businesses, artists, posts, ads, uploads. One of: `photos`, `guides`, `datasets`, `heritage`, `civic`, `businesses`, `artists`, `posts`, `ads`, `uploads`. |
| `q` | query | string | Text search in alt text, caption and credit. Example: `river`. |
| `limit` | query | integer | Items per page (default 50, max 500 unless noted). Example: `20`. |
| `offset` | query | integer | Items to skip. Use `links.next` to page. Example: `0`. |

Also accepts `fields` (sparse fieldset) and `format` (`json`, `md`, `csv`).

**Example request**

```bash
curl "https://princegeorgepulse.ca/api/v1/media"
```

**Example response** (trimmed)

```json
{
  "data": [
    {
      "id": 100,
      "kind": "businesses",
      "url": "https://princegeorgepulse-media.s3.ca-central-1.amazonaws.com/prince-george/businesses/gosling-website-8cd0a6-640.webp",
      "original": "https://princegeorgepulse-media.s3.ca-central-1.amazonaws.com/prince-george/businesses/gosling-website-8cd0a6-640.webp",
      "width": 640,
      "height": 400,
      "variants": [
        {
          "width": 320,
          "height": 200,
          "url": "https://princegeorgepulse-media.s3.ca-central-1.amazonaws.com/prince-george/businesses/gosling-website-8cd0a6-320.webp"
        },
        {
          "width": 640,
          "height": 400,
          "url": "https://princegeorgepulse-media.s3.ca-central-1.amazonaws.com/prince-george/businesses/gosling-website-8cd0a6-640.webp"
        }
      ],
      "alt": "Screenshot of the Gosling website",
      "caption": null,
      "credit": "Screenshot of Gosling’s website",
      "author": null,
      "licence": null,
      "…": "4 more keys"
    },
    {
      "id": 101,
      "kind": "businesses",
      "url": "https://princegeorgepulse-media.s3.ca-central-1.amazonaws.com/prince-george/businesses/just-diesel-website-52ed67-640.webp",
      "original": "https://princegeorgepulse-media.s3.ca-central-1.amazonaws.com/prince-george/businesses/just-diesel-website-52ed67-640.webp",
      "width": 640,
      "height": 400,
      "variants": [
        {
          "width": 320,
          "height": 200,
          "url": "https://princegeorgepulse-media.s3.ca-central-1.amazonaws.com/prince-george/businesses/just-diesel-website-52ed67-320.webp"
        },
        {
          "width": 640,
          "height": 400,
          "url": "https://princegeorgepulse-media.s3.ca-central-1.amazonaws.com/prince-george/businesses/just-diesel-website-52ed67-640.webp"
        }
      ],
      "alt": "Screenshot of the Just Diesel website",
      "caption": null,
      "credit": "Screenshot of Just Diesel’s website",
      "author": null,
      "licence": null,
      "…": "4 more keys"
    },
    "… 98 more"
  ],
  "meta": {
    "source": "Each image’s own source and licence (see credit, licence and sourcePage on each item)",
    "sourceUrl": "https://princegeorgepulse.ca/about/",
    "updatedAt": "2026-10-02T17:55:46.074Z",
    "ageSec": 1183958,
    "license": "Per image: the licence named on the item (Creative Commons, public domain, official portraits, screenshots of a business’s own site)",
    "attribution": "Each image’s own source and licence (see credit, licence and sourcePage on each item), via PG Pulse (princegeorgepulse.ca)",
    "total": 926,
    "count": 100,
    "limit": 100,
    "offset": 0
  },
  "links": {
    "self": "/api/v1/media",
    "next": "/api/v1/media?offset=100",
    "docs": "/developers/reference/datasets/#get-media"
  }
}
```

## GET /api/v1/media/{id} {#get-media-id}

One hosted image.

- Cache: 1 h
- Source: [Each image’s own source and licence (see credit, licence and sourcePage on each item)](https://princegeorgepulse.ca/about/)
- Licence: Per image: the licence named on the item (Creative Commons, public domain, official portraits, screenshots of a business’s own site)

| Parameter | In | Type | Description |
| --- | --- | --- | --- |
| `id` | path | string | Media id. Required. Example: `1`. |

Also accepts `fields` (sparse fieldset) and `format` (`json`, `md`).

**Example request**

```bash
curl "https://princegeorgepulse.ca/api/v1/media/1"
```

**Example response** (trimmed)

```json
{
  "data": {
    "id": 1,
    "kind": "photos",
    "url": "https://princegeorgepulse-media.s3.ca-central-1.amazonaws.com/prince-george/photos/university-hill-view-c5d5ac-1200.webp",
    "original": "https://princegeorgepulse-media.s3.ca-central-1.amazonaws.com/prince-george/photos/university-hill-view-c5d5ac.webp",
    "width": 1200,
    "height": 925,
    "variants": [
      {
        "width": 320,
        "height": 247,
        "url": "https://princegeorgepulse-media.s3.ca-central-1.amazonaws.com/prince-george/photos/university-hill-view-c5d5ac-320.webp"
      },
      {
        "width": 640,
        "height": 493,
        "url": "https://princegeorgepulse-media.s3.ca-central-1.amazonaws.com/prince-george/photos/university-hill-view-c5d5ac-640.webp"
      },
      "… 1 more"
    ],
    "alt": "Prince George seen from University Hill looking east over the city toward the hills",
    "caption": null,
    "credit": "Photo: Iranianson, CC BY-SA 3.0 via Wikimedia Commons",
    "author": "Iranianson",
    "licence": "CC BY-SA 3.0",
    "…": "4 more keys"
  },
  "meta": {
    "source": "Each image’s own source and licence (see credit, licence and sourcePage on each item)",
    "sourceUrl": "https://princegeorgepulse.ca/about/",
    "updatedAt": "2026-10-02T17:53:23.478Z",
    "ageSec": 1184100,
    "license": "Per image: the licence named on the item (Creative Commons, public domain, official portraits, screenshots of a business’s own site)",
    "attribution": "Each image’s own source and licence (see credit, licence and sourcePage on each item), via PG Pulse (princegeorgepulse.ca)"
  },
  "links": {
    "self": "/api/v1/media/1",
    "next": null,
    "docs": "/developers/reference/datasets/#get-media-id"
  }
}
```
