Skip to content
PG Pulse
PG Pulse

Try searching for

Local knowledge for your AI tools

Connect Cursor, VS Code, Codex or Claude Code. Free MCP access, no key needed.

Connect your AI assistant
View as MarkdownFree, no key needed

About the API

5 endpoints. Base URL https://princegeorgepulse.ca/api/v1. Conventions (envelope, paging, fields, formats, limits) are on the overview. All endpoints.

GET /api/v1/ #

API index: every endpoint with a link.

  • Cache: 1 h
  • Source: PG Pulse
  • 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/"

Example response (trimmed)

json
{
  "data": {
    "name": "PG Pulse API",
    "version": "1.1.0",
    "description": "Free, open JSON API for everything on PG Pulse, the local guide to Prince George, British Columbia. No key, no sign-up.",
    "docs": "/developers/",
    "openapi": "/api/v1/openapi.json",
    "llms": "/llms.txt",
    "rateLimit": "120 requests per 60 seconds per IP",
    "endpoints": [
      {
        "path": "/api/v1/",
        "group": "About the API",
        "summary": "API index: every endpoint with a link",
        "docs": "/developers/reference/about-the-api/#get"
      },
      {
        "path": "/api/v1/meta",
        "group": "About the API",
        "summary": "Site facts, counts and data freshness",
        "docs": "/developers/reference/about-the-api/#get-meta"
      },
      "… 277 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/",
    "next": null,
    "docs": "/developers/reference/about-the-api/#get"
  }
}

GET /api/v1/meta #

Site facts, counts and data freshness.

  • Cache: 5 min
  • Source: PG Pulse
  • 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/meta"

Example response (trimmed)

json
{
  "data": {
    "site": {
      "name": "PG Pulse",
      "longName": "Prince George Pulse",
      "tagline": "The pulse of Prince George, British Columbia",
      "description": "The live local guide to Prince George, BC: news from every local source, live weather, air, rivers and wildfires, a local business directory and things to do.",
      "url": "https://princegeorgepulse.ca",
      "city": "Prince George",
      "region": "British Columbia",
      "country": "Canada",
      "lat": 53.9171,
      "lng": -122.7497,
      "timezone": "America/Vancouver",
      "contact": "hello@princegeorgepulse.ca"
    },
    "modules": [
      "core",
      "media",
      "… 74 more"
    ],
    "counts": {
      "businesses": 2484,
      "categories": 88,
      "neighbourhoods": 31,
      "newsItems": 871,
      "stories": 6,
      "upcomingEvents": 362,
      "djs": 80,
      "mapLayers": 50,
      "endpoints": 279
    },
    "updated": {
      "businesses": "2026-10-15T09:45:16.195Z",
      "news": "2026-10-16T10:45:31.669Z",
      "events": "2026-10-16T10:21:11.428Z"
    },
    "jobs": {
      "ok": true,
      "scheduler": {
        "alive": true,
        "at": "2026-10-16T10:48:14.290Z",
        "running": [
          "rebuild",
          "mailbox"
        ],
        "node": "v22.23.3",
        "timeZone": {
          "timezone": "America/Vancouver",
          "tzdata": "2026e",
          "ok": true,
          "checks": [
            "{…}"
          ]
        }
      },
      "stale": [],
      "failing": [],
      "jobs": {
        "feed": {
          "enabled": true,
          "dataAt": "2026-10-16T10:45:31.669Z",
          "stale": false,
          "lastOk": true,
          "running": false
        },
        "feed-trends": {
          "enabled": true,
          "dataAt": "2026-10-16T10:07:13.891Z",
          "stale": false,
          "lastOk": true,
          "running": false
        },
        "events": {
          "enabled": true,
          "dataAt": "2026-10-16T10:21:11.428Z",
          "stale": false,
          "lastOk": true,
          "running": false
        },
        "careers": {
          "enabled": true,
          "dataAt": "2026-10-16T08:37:16.644Z",
          "stale": false,
          "lastOk": true,
          "running": false
        },
        "live": {
          "enabled": true,
          "dataAt": "2026-10-16T10:43:26.141Z",
          "stale": false,
          "lastOk": true,
          "running": false
        },
        "city": {
          "enabled": true,
          "dataAt": "2026-10-12T09:10:01.912Z",
          "stale": false,
          "lastOk": true,
          "running": false
        },
        "businesses": {
          "enabled": true,
          "dataAt": "2026-10-15T09:45:11.669Z",
          "stale": false,
          "lastOk": true,
          "running": false
        },
        "maps": {
          "enabled": true,
          "dataAt": "2026-10-11T10:30:05.624Z",
          "stale": false,
          "lastOk": true,
          "running": false
        },
        "climate": {
          "enabled": true,
          "dataAt": "2026-10-16T07:31:29.793Z",
          "stale": false,
          "lastOk": true,
          "running": false
        },
        "stats": {
          "enabled": true,
          "dataAt": "2026-10-12T13:20:29.182Z",
          "stale": false,
          "lastOk": true,
          "running": false
        },
        "notable-people": {
          "enabled": true,
          "dataAt": "2026-10-05T12:50:25.112Z",
          "stale": false,
          "lastOk": true,
          "running": false
        },
        "gtfs": {
          "enabled": true,
          "dataAt": "2026-10-12T11:40:09.498Z",
          "stale": false,
          "lastOk": true,
          "running": false
        },
        "…": "46 more keys"
      }
    },
    "api": {
      "version": "1.1.0",
      "base": "/api/v1",
      "docs": "/developers/",
      "openapi": "/api/v1/openapi.json",
      "rateLimit": {
        "limit": 120,
        "windowSec": 60
      },
      "auth": "none",
      "cost": "free"
    }
  },
  "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/meta",
    "next": null,
    "docs": "/developers/reference/about-the-api/#get-meta"
  }
}

GET /api/v1/pages #

Every public page on the site, with its Markdown version.

  • Cache: 1 h
  • Source: PG Pulse
  • Licence: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)
  • Paginated: limit (default 500, max 5000) and offset; also format=csv
ParameterInTypeDescription
prefixquerystringOnly paths starting with this. Example: /dashboard/.
limitqueryintegerItems per page (default 500).
offsetqueryintegerItems to skip.

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

Example request

bash
curl "https://princegeorgepulse.ca/api/v1/pages?prefix=/dashboard/"

Example response (trimmed)

json
{
  "data": [
    {
      "path": "/dashboard/",
      "url": "https://princegeorgepulse.ca/dashboard/",
      "markdown": "https://princegeorgepulse.ca/dashboard.md"
    },
    {
      "path": "/dashboard/air-quality/",
      "url": "https://princegeorgepulse.ca/dashboard/air-quality/",
      "markdown": "https://princegeorgepulse.ca/dashboard/air-quality.md"
    },
    "… 13 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)",
    "total": 15,
    "count": 15,
    "limit": 500,
    "offset": 0
  },
  "links": {
    "self": "/api/v1/pages?prefix=/dashboard/",
    "next": null,
    "docs": "/developers/reference/about-the-api/#get-pages"
  }
}

Search across site pages, public places, awards categories, schools, outdoor places, businesses, categories, neighbourhoods (and subdivision names), answers, guides, stories, events, jobs, artists, map layers, resources, news, sports teams and clubs.

  • Cache: 5 min
  • Source: PG Pulse
  • Licence: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)
ParameterInTypeDescription
qquerystringSearch text. Required. Example: dog park.
perqueryintegerResults per type (default 5, max 25).

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

Example request

bash
curl "https://princegeorgepulse.ca/api/v1/search?q=dog%20park"

Example response (trimmed)

json
{
  "data": {
    "pages": [
      {
        "name": "Dog parks",
        "description": "Off-leash areas on a map",
        "url": "/maps/?layer=dog-parks"
      }
    ],
    "answers": [],
    "categories": [],
    "services": [],
    "awards": [],
    "schools": [],
    "outdoors": [],
    "businesses": [
      {
        "name": "Happy Tails Canine Adventures",
        "category": "Pets & vets",
        "area": "East Central Fort George",
        "url": "/business/happy-tails-canine-adventures/",
        "api": "/api/v1/businesses/happy-tails-canine-adventures"
      }
    ],
    "neighbourhoods": [],
    "guides": [
      {
        "name": "Parks and trails in Prince George, BC",
        "url": "/visit/parks-and-trails/",
        "markdown": "/visit/parks-and-trails.md"
      },
      {
        "name": "Bylaws, animal control and wildlife",
        "url": "/city/bylaws-and-animal-control/",
        "markdown": "/city/bylaws-and-animal-control.md"
      }
    ],
    "stories": [],
    "events": [],
    "…": "6 more keys"
  },
  "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/search?q=dog%20park",
    "next": null,
    "docs": "/developers/reference/about-the-api/#get-search"
  }
}

GET /api/v1/changes #

Stable incremental discovery for businesses, events and jobs.

Use a full ISO since date-time with Z or an offset no older than 90 days, then follow cursor until complete. Keep watermark only after all pages finish. Removals are explicit tombstones. Fetch current entities from their API URL. Edits during paging appear in the next window. A cursor belongs to one city. An expired window returns 410 and requires a new full sync.

  • Cache: 0 s
  • Source: PG Pulse
  • Licence: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)
ParameterInTypeDescription
sincequerystringUTC date-time, e.g. 2026-10-01T00:00:00.000Z (seconds, milliseconds or an offset like -07:00 are normalised)
cursorquerystringOpaque cursor from the previous response; overrides since
limitqueryintegerBetween 1 and 500

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

Example request

bash
curl "https://princegeorgepulse.ca/api/v1/changes?since=2026-10-15T10:48:18.263Z"

Example response (trimmed)

json
{
  "data": {
    "changes": [
      {
        "kind": "job",
        "id": "_0xWH8FUUBOO",
        "action": "remove",
        "updatedAt": "2026-10-15T13:35:04.405Z",
        "url": "/api/v1/jobs/_0xWH8FUUBOO"
      },
      {
        "kind": "job",
        "id": "9WBhuRzAVl3C",
        "action": "remove",
        "updatedAt": "2026-10-15T13:35:04.405Z",
        "url": "/api/v1/jobs/9WBhuRzAVl3C"
      },
      "… 98 more"
    ],
    "cursor": "eyJ2IjoxLCJjaXR5IjoicHJpbmNlLWdlb3JnZSIsInNpbmNlIjoiMjAyNi0xMC0xNVQxMDo0ODoxOC4yNjNaIiwidW50aWwiOiIyMDI2LTEwLTE2VDEwOjQ4OjE4LjI2NFoiLCJhZnRlciI6WyIyMDI2LTEwLTE2VDA3OjM1OjA5LjIxOFoiLCJqb2IiLCIzazVsVkdsSm1MTUEiXX0",
    "watermark": "2026-10-16T10:48:18.264Z",
    "complete": false
  },
  "meta": {
    "source": "PG Pulse",
    "sourceUrl": "https://princegeorgepulse.ca",
    "updatedAt": "2026-10-16T10:48:18.264Z",
    "ageSec": 0,
    "license": "CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)",
    "attribution": "PG Pulse (princegeorgepulse.ca)"
  },
  "links": {
    "self": "/api/v1/changes?since=2026-10-15T10:48:18.263Z",
    "next": null,
    "docs": "/developers/reference/about-the-api/#get-changes"
  }
}

Add PG Pulse to your home screen

Your browser installs apps from its Share menu.

  1. Tap Share in the browser toolbar (at the bottom of the screen on iPhone, at the top on iPad).
  2. Scroll down and tap Add to Home Screen.
  3. Tap Add. PG Pulse opens from its icon like any other app.