Developer API

CityAlert normalizes live public-safety incidents — police open-data feeds, earthquake agencies, wildfire services, weather warnings, disaster alerts, geocoded media reports and community submissions — into one GeoJSON stream. The same endpoints that power the map are public and free to use with attribution.

Machine-readable spec: /api/openapi.json (OpenAPI 3.1). For AI agents, see llms.txt and the MCP server below.

Public endpoints

  • GET/api/incidents

    Merged live incident stream as a GeoJSON FeatureCollection

    Filter with ?region=, ?category=, ?source=, ?bbox=minLon,minLat,maxLon,maxLat, ?days=, ?limit= (max 10000), ?id=. Use ?format=json for a plain array. ?refresh=1 forces an upstream re-fetch.

  • GET/api/regions

    Focus-region list — key, label, center, zoom, bbox

  • GET/api/trends

    Historical aggregates — crime YoY, earthquakes by region, GDACS by year

  • GET/api/crime-year?year=YYYY&region=<key>

    Full-year incident GeoJSON + neighbourhood ranking

    Vancouver VPD history goes back to 2003; other regions via police portals or the media log.

  • GET/api/news

    Regional safety news items

    ?place=<name> for ad-hoc places outside the focus regions.

  • GET/cities/<slug>/feed.xml

    Atom feed of a city's 20 most recent incidents

    Advertised via <link rel="alternate"> on every city page.

  • GET/api/reports

    Community-submitted incident reports

  • POST/api/reports

    Submit a community report

    Body: {title, lat, lon, category?, severity?, description?}. Rate-limited to 5/hour per IP; reports are community-verified before going active.

  • POST/api/reports/<id>/vote

    Vote on a report — confirm, resolve or flag

    Body: {kind: "confirm"|"resolve"|"flag"}. 30 votes/hour per IP.

  • GET/api/dashboards?id=<id>

    Fetch a shared dashboard config

  • POST/api/dashboards

    Create a shareable dashboard — returns {id, token}

    The token is the write credential; PUT /api/dashboards updates with {id, token, config}.

  • POST/api/mcp

    MCP (Model Context Protocol) server for AI assistants

    JSON-RPC 2.0 — initialize, tools/list, tools/call over the same incident data.

Incident object

Every incident — in GeoJSON properties or JSON array items — carries:

id          stable source-prefixed identifier
source      feed key (e.g. "usgs", "vpd", "zwaailicht")
category    crime | fire | disaster | weather | unrest | health | infra | report
type        source-specific type (e.g. "earthquake", "Break and Enter")
title       headline
description optional detail (plain text, max ~160 chars)
lat, lon    WGS84 coordinates
time        reported time, ISO 8601
severity    low | medium | high | critical
url         upstream source link
region      focus-region key when inside one
nhood       neighbourhood label when the feed provides one
status      community-report state: pending | active | resolved | hidden

MCP server

POST /api/mcp speaks the Model Context Protocol — point any MCP client (Claude, ChatGPT, open-source agents) at it to query incidents, regions and trends as tools instead of raw HTTP.

Per-city Atom feeds

Each of the 74 city pages publishes an Atom feed of its 20 most recent incidents at /cities/<slug>/feed.xml. City pages themselves are ISR-rendered every ~10 minutes with live incident lists — safe to crawl and cite.

Usage, rate limits & attribution

  • Read endpoints are public; community write endpoints are IP rate-limited.
  • Attribution: cite CityAlert and the underlying source listed in each incident's source field.
  • Media-sourced incidents are approximate block-level locations — preserve that caveat when republishing.
  • This is an aggregation/awareness tool. For emergencies defer to official authorities.
  • Data is provided under CC BY 4.0 for our normalization layer; underlying feeds carry their own licenses — see Sources & licenses.