Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 59 additions & 1 deletion docs/coverage-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The Coverage API provides programmatic access to MeshMapper coverage grid-square

## Authentication

Access requires a **Coverage** API key. Each key is scoped to a specific region or multiregion group and has a daily rate limit of 100 requests.
Access requires a **Coverage** API key. Each key is scoped to a specific region, a multiregion group, or a set of adjacent regions (see [Multi-Region Keys](#multi-region-keys)), and has a daily rate limit of 100 requests.

### Generating a Key

Expand Down Expand Up @@ -247,6 +247,64 @@ A separate short-term, per-IP throttle protects against bursts; exceeding it als

If you have a Coverage API key assigned to your admin account, you can view your current usage and regenerate your key from the **User Settings** tab in your region's Admin Portal. Regenerating a key invalidates the old one immediately.

## Multi-Region Keys

A Coverage key can be scoped to a **set of up to 6 regions** (for example `PDX,SEA,YVR`) instead of a single region. The response merges every member region's coverage into **one grid** — the same payload shape as a single-region response — so it suits integrations that render adjacent regions as one continuous map.

Multi-region keys are not self-service: like [global keys](#global-coverage-feed), they are issued by the MeshMapper team on request (the admin-panel self-service flow only creates single-region keys). Adjacent regions are the intended use — the merged grid serves them as one map.

!!! info "Multi-region keys vs. Multiregion Groups"
A [Multiregion Group](multiregions.md) merges regions *inside* MeshMapper — shared map, leaderboards, collision detection, and admin panel. A multi-region **key** changes nothing about the regions themselves; it only merges their coverage data in this API's response. If a group already exists, a key can simply be scoped to the group's code instead. A multi-region key is for sets of regions that aren't (and shouldn't become) a group.

### Response Format

Identical to a single-region response — one merged `grid_squares` array, same grid-square fields, `?include=repeaters` supported (the `repeaters` array spans all members):

```json
{
"success": true,
"region": "PDX,SEA,YVR",
"region_name": "Portland, US + Seattle, US + Vancouver, CA",
"grid_size": { "lat": 0.0027, "lon": 0.00384 },
"schema_version": 2,
"generated_at": 1710547200,
"data_age_seconds": 312,
"total_squares": 4102,
"point_count": 131877,
"coverage_type_counts": { "BIDIR": 1620, "TX": 214, "RX": 1467, "DISC": 305, "DEAD": 41, "DROP": 455 },
"type_bits": { "BIDIR": 1, "TX": 2, "RX": 4, "DISC": 8, "DEAD": 16, "DROP": 32 },
"bbox": { "minLat": 45.301, "minLon": -123.212, "maxLat": 49.394, "maxLon": -121.751 },
"grid_squares": [ "…same grid square objects as a single-region response, all members merged…" ],
"regions": ["PDX", "SEA", "YVR"],
"regions_skipped": 0
}
```

Note that `regions` and `regions_skipped` arrive **after** the `grid_squares` array — as with the global feed, use a standard JSON parser rather than assuming key order. The fields that differ from a single-region response:

| Field | Type | Description |
| --- | --- | --- |
| `region` | string | The normalized member set as a CSV, uppercased and sorted (e.g. `"PDX,SEA,YVR"`). |
| `region_name` | string | Member region names joined with `+`. |
| `regions` | array | The member region codes, sorted — present only on multi-region responses. |
| `regions_skipped` | integer | Members that are registered but have no coverage data yet — present only on multi-region responses. |

### Differences from Single-Region Keys

| Behaviour | Result |
| --- | --- |
| `fresh=1` | HTTP 400, `fresh_not_supported` — the merged build is cache-driven only. |
| `f_*` filter parameters | HTTP 400, `filters_not_supported`. |
| Any member region unknown or deleted | HTTP 400, `invalid_region` — the API fails closed and never serves a partial set. |
| More than 6 member regions | HTTP 400, `too_many_regions`. |
| Region set too large to build in memory | HTTP 507, `over_memory_budget` — ask for the key to be recreated with fewer regions. |

If a member region is later renamed, merged, or removed from MeshMapper, the key is updated automatically to follow — a removed region simply drops out of the set.

### Caching and Limits

Caching, compression, conditional requests, and the daily quota work exactly as for single-region keys: 15-minute server cache, `ETag` / `If-None-Match` for `304 Not Modified`, gzip, and 100 requests per day (cache hits and 304s count). Response size scales with the number of member regions — poll at 15-minute intervals or longer.

## Global Coverage Feed

A special **global** Coverage key returns data for **every MeshMapper region in one request** — no region list to maintain on your side. Global keys are not self-service: they are issued by the MeshMapper team on request, for integrations that genuinely need fleet-wide data (reach out via the usual channels if that's you).
Expand Down