Market endpoints
City market overview, category rankings and brand performance across cities.
Market endpoints aggregate foot traffic across a city, a category or a brand. They require authentication, count as ordinary API calls (not analyses) and follow the date-range rules. Paths are relative to https://api.mapdove.com/api/v1. For interpretation see Market intelligence.
| Method | Path | Purpose |
|---|---|---|
| GET | /market/:city/overview |
City totals, categories, weekly trend, movers, neighborhoods |
| GET | /rankings |
Places in a category ordered by visits |
| GET | /brands/:slug/performance |
A brand across all cities |
Market overview
GET /market/:city/overview
| Param | Description |
|---|---|
city |
path, city slug |
from, to |
date range |
curl "https://api.mapdove.com/api/v1/market/houston/overview?from=2026-08-01&to=2026-10-31" \
-H "Authorization: Bearer $MAPDOVE_KEY"
const ov = await fetch('https://api.mapdove.com/api/v1/market/houston/overview', {
headers: { Authorization: `Bearer ${key}` },
}).then((r) => r.json());
const growing = ov.by_category.filter((c) => c.change_pct > 0).map((c) => c.slug);
ov = requests.get(f"{BASE}/market/houston/overview", headers=H, timeout=60).json()
for c in sorted(ov["by_category"], key=lambda c: -c["share"])[:3]:
print(c["name"], round(c["share"] * 100, 1), "%", c["change_pct"])
{
"range": { "from": "2026-08-01", "to": "2026-10-31" },
"totals": { "visits": 12804412, "visits_prev": 12610038, "change_pct": 1.5 },
"by_category": [
{ "slug": "mall", "name": "Shopping Centers", "color": "#475569", "visits": 3521900, "change_pct": 2.4, "share": 0.275 },
{ "slug": "grocery", "name": "Grocery", "color": "#16a34a", "visits": 3110240, "change_pct": 0.9, "share": 0.243 }
],
"trend": [
{ "date": "2026-08-03", "visits": 968210 },
{ "date": "2026-08-10", "visits": 975402 }
],
"top_movers": {
"up": [ { "id": 402, "name": "Midtown Burger Joint", "change_pct": 18.2, "…": "…" } ],
"down": [ { "id": 455, "name": "Crispy Coop · Gulfton", "change_pct": -9.7, "…": "…" } ]
},
"by_neighborhood": [
{ "name": "Uptown Galleria", "visits": 1490330, "change_pct": 1.8 },
{ "name": "Downtown", "visits": 1201876, "change_pct": 0.6 }
]
}
shareis the category’s fraction of total city visits in the range.trendis weekly;top_movers.upand.downhold fivePlaceSummaryobjects each, ranked bychange_pct.
Rankings
GET /rankings — all places of a category in a city, ordered by visits, with rank_in_category.
| Param | Description |
|---|---|
city |
required city slug |
category |
required category slug |
from, to |
date range |
limit |
default 50, max 500 |
curl "https://api.mapdove.com/api/v1/rankings?city=dubai&category=mall&limit=3" \
-H "Authorization: Bearer $MAPDOVE_KEY"
top = requests.get(f"{BASE}/rankings", headers=H,
params={"city": "dubai", "category": "mall", "limit": 3}, timeout=30).json()
[
{ "id": 1201, "name": "Downtown Dubai Galleria", "rank_in_category": 1, "visits": 1184210, "change_pct": 6.1, "avg_daily_visits": 12872, "…": "…" },
{ "id": 1219, "name": "Dubai Marina Town Center", "rank_in_category": 2, "visits": 1012944, "change_pct": 4.8, "avg_daily_visits": 11010, "…": "…" },
{ "id": 1224, "name": "Deira Plaza", "rank_in_category": 3, "visits": 820531, "change_pct": 3.9, "avg_daily_visits": 8919, "…": "…" }
]
Each item is a full PlaceSummary.
Brand performance
GET /brands/:slug/performance — one brand across every city where it operates.
| Param | Description |
|---|---|
slug |
path, brand slug (see GET /brands) |
from, to |
date range |
curl "https://api.mapdove.com/api/v1/brands/bean-republic/performance" \
-H "Authorization: Bearer $MAPDOVE_KEY"
const perf = await fetch('https://api.mapdove.com/api/v1/brands/bean-republic/performance', {
headers: { Authorization: `Bearer ${key}` },
}).then((r) => r.json());
const best = [...perf.by_city].sort((a, b) => b.avg_per_location - a.avg_per_location)[0];
perf = requests.get(f"{BASE}/brands/bean-republic/performance", headers=H, timeout=60).json()
print({s["city"]: s["share"] for s in perf["market_share"]})
{
"brand": { "id": 1, "slug": "bean-republic", "name": "Bean Republic", "category": "coffee", "color": "#6f4e37", "price_tier": 2, "locations": 40 },
"by_city": [
{ "city": "austin", "name": "Austin", "locations": 9, "visits": 318402, "avg_per_location": 35378, "change_pct": 3.2 },
{ "city": "miami", "name": "Miami", "locations": 7, "visits": 241866, "avg_per_location": 34552, "change_pct": 5.0 }
],
"trend": [ { "date": "2026-08-03", "visits": 101233 } ],
"locations": [ { "id": 42, "name": "Bean Republic · Downtown", "…": "…" } ],
"market_share": [ { "city": "austin", "share": 0.312 }, { "city": "miami", "share": 0.287 } ]
}
avg_per_location= visits ÷ locations in the range.trendis weekly across all locations.market_shareis the brand’s share of its category’s visits in each city.
All brands and figures are fictional and synthetic (Demo data).