Projects, favorites and alerts

Save and share analyses as projects, keep a watchlist of favorite places and set visit alerts through the API.

These endpoints manage your organization’s working state: projects (saved analyses), favorites (a watchlist of places) and alerts (week-over-baseline change notifications). All require authentication; paths are relative to https://api.mapdove.com/api/v1.

Method Path Purpose
GET /projects List projects
POST /projects Create a project
GET /projects/:id Get a project
PATCH /projects/:id Update a project
DELETE /projects/:id Delete a project
GET /favorites List favorite places
PUT /favorites/:place_id Add a favorite
DELETE /favorites/:place_id Remove a favorite
GET /alerts List alerts with evaluation
POST /alerts Create an alert
DELETE /alerts/:id Delete an alert

Projects

A project stores an analysis — its kind, city, parameters and result — plus notes, so the team can reopen and reproduce it. Projects are visible to everyone in the organization.

{
  "id": "6f1c2a8e-3d4b-4f0a-9a51-0b7e2c9d1f33",
  "name": "Austin café #12 — shortlist",
  "kind": "compare",
  "city_slug": "austin",
  "params": { "category": "coffee", "sites": ["…"], "weights": { "daytime": 8, "gap": 7 } },
  "result": { "sites": ["…"] },
  "notes": "Mueller preferred; check landlord TI allowance.",
  "created_at": "2026-11-04T15:22:10Z",
  "updated_at": "2026-11-05T09:01:44Z",
  "created_by_name": "Ada Park"
}

kind is one of site_selection, huff, catchment, compare, trade_area. params and result are free-form JSON — store the request body you sent and the response you received.

List projects

curl https://api.mapdove.com/api/v1/projects \
  -H "Authorization: Bearer $MAPDOVE_KEY"

Returns Project[].

Create a project

POST /projects — body { name, kind, city_slug, params, result?, notes? }. Returns 201 with the project.

curl -X POST https://api.mapdove.com/api/v1/projects \
  -H "Authorization: Bearer $MAPDOVE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Mueller coffee forecast",
    "kind": "huff",
    "city_slug": "austin",
    "params": { "category": "coffee", "lng": -97.7046, "lat": 30.2981, "sqft": 2200, "brand_strength": 1.1 },
    "result": { "predicted_daily_visits": 397, "total_cannibalized_daily": 212 },
    "notes": "Base case."
  }'
// Run a model, then save it as a project
const params = { city: 'austin', category: 'coffee', lng: -97.7046, lat: 30.2981 };
const headers = { Authorization: `Bearer ${key}`, 'Content-Type': 'application/json' };
const result = await fetch(`${BASE}/sdss/huff`, { method: 'POST', headers, body: JSON.stringify(params) }).then((r) => r.json());
const project = await fetch(`${BASE}/projects`, {
  method: 'POST',
  headers,
  body: JSON.stringify({ name: 'Mueller coffee forecast', kind: 'huff', city_slug: 'austin', params, result }),
}).then((r) => r.json());
params = {"city": "austin", "category": "coffee", "lng": -97.7046, "lat": 30.2981}
result = requests.post(f"{BASE}/sdss/huff", headers=H, json=params, timeout=120).json()
project = requests.post(f"{BASE}/projects", headers=H, timeout=30, json={
    "name": "Mueller coffee forecast", "kind": "huff", "city_slug": "austin",
    "params": params, "result": result,
}).json()
print(project["id"])

Saving a project does not count as an analysis; only the model run does.

Get, update, delete

# Get
curl https://api.mapdove.com/api/v1/projects/6f1c2a8e-3d4b-4f0a-9a51-0b7e2c9d1f33 \
  -H "Authorization: Bearer $MAPDOVE_KEY"

# Update notes (any of name, params, result, notes)
curl -X PATCH https://api.mapdove.com/api/v1/projects/6f1c2a8e-3d4b-4f0a-9a51-0b7e2c9d1f33 \
  -H "Authorization: Bearer $MAPDOVE_KEY" -H "Content-Type: application/json" \
  -d '{ "notes": "Approved for LOI." }'

# Delete → 204
curl -X DELETE https://api.mapdove.com/api/v1/projects/6f1c2a8e-3d4b-4f0a-9a51-0b7e2c9d1f33 \
  -H "Authorization: Bearer $MAPDOVE_KEY"

PATCH returns the updated project and bumps updated_at.

Favorites

Favorites are a watchlist of places. GET /favorites returns them as PlaceSummary[] computed over the last 30 days of data.

# Add place 42 → 204
curl -X PUT https://api.mapdove.com/api/v1/favorites/42 \
  -H "Authorization: Bearer $MAPDOVE_KEY"

# List
curl https://api.mapdove.com/api/v1/favorites \
  -H "Authorization: Bearer $MAPDOVE_KEY"

# Remove → 204
curl -X DELETE https://api.mapdove.com/api/v1/favorites/42 \
  -H "Authorization: Bearer $MAPDOVE_KEY"
[
  { "id": 42, "name": "Bean Republic · Downtown", "visits": 11520, "visits_prev": 11208, "change_pct": 2.8, "avg_daily_visits": 384, "…": "…" }
]

PUT is idempotent — adding an existing favorite is not an error.

Alerts

An alert watches one metric of one place and reports whether the latest week moved more than a threshold. Alerts are evaluated whenever you list them:

change_pct = 100 · (current_week − baseline_week) / baseline_week
  • current_week — the latest 7 days of data (sum of visits or visitors; average dwell).
  • baseline_week — the weekly average of the 4 weeks before that.

An alert is triggered when it is active and the change passes the threshold in the chosen direction.

Field Values
place_id integer
metric visits (default), visitors or dwell
direction up (change ≥ threshold), down (change ≤ −threshold) or either (absolute change ≥ threshold)
threshold_pct percentage, e.g. 10

Alert counts are limited by plan: Free 0, Pro 10, Business 100, Enterprise unlimited. Creating one beyond the limit returns 402 plan_limit.

Create an alert

curl -X POST https://api.mapdove.com/api/v1/alerts \
  -H "Authorization: Bearer $MAPDOVE_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "place_id": 42, "metric": "visits", "direction": "down", "threshold_pct": 10 }'
alert = requests.post(f"{BASE}/alerts", headers=H, timeout=30, json={
    "place_id": 42, "metric": "visits", "direction": "down", "threshold_pct": 10,
}).json()

Response 201:

{
  "id": "0d9b5f3e-1c7a-4e2b-8f6d-5a4c3b2a1e0f",
  "place_id": 42, "place_name": "Bean Republic · Downtown",
  "metric": "visits", "direction": "down", "threshold_pct": 10,
  "active": true, "created_at": "2026-11-06T10:12:03Z",
  "triggered": false, "last_change_pct": -3.4
}

List and delete

curl https://api.mapdove.com/api/v1/alerts -H "Authorization: Bearer $MAPDOVE_KEY"
curl -X DELETE https://api.mapdove.com/api/v1/alerts/0d9b5f3e-1c7a-4e2b-8f6d-5a4c3b2a1e0f \
  -H "Authorization: Bearer $MAPDOVE_KEY"

To build notifications, poll GET /alerts on a schedule (once a day is plenty — the data is daily) and act on items whose triggered is true.