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/incidentsMerged 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/regionsFocus-region list — key, label, center, zoom, bbox
- GET
/api/trendsHistorical aggregates — crime YoY, earthquakes by region, GDACS by year
- GET
/api/crime-year?year=YYYY®ion=<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/newsRegional safety news items
?place=<name> for ad-hoc places outside the focus regions.
- GET
/cities/<slug>/feed.xmlAtom feed of a city's 20 most recent incidents
Advertised via <link rel="alternate"> on every city page.
- GET
/api/reportsCommunity-submitted incident reports
- POST
/api/reportsSubmit 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>/voteVote 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/dashboardsCreate a shareable dashboard — returns {id, token}
The token is the write credential; PUT /api/dashboards updates with {id, token, config}.
- POST
/api/mcpMCP (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
sourcefield. - 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.