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 }
  ]
}
  • share is the category’s fraction of total city visits in the range.
  • trend is weekly; top_movers.up and .down hold five PlaceSummary objects each, ranked by change_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.
  • trend is weekly across all locations.
  • market_share is the brand’s share of its category’s visits in each city.

All brands and figures are fictional and synthetic (Demo data).