REST API for the public website features: prefix reservation, network reports, and duplicate-prefix detection. Admin-only routes (reservation lists, force-release) require an API key when configured.
Production base URL: https://meshbuddy.gulfcoastmesh.org — API routes are under /api (e.g. https://meshbuddy.gulfcoastmesh.org/api/status).
Local development: http://127.0.0.1:5000 (api_port in config.ini; website uses api_base_url on port 8080).
Format: JSON request and response bodies. Content-Type: application/json for POST bodies.
CORS: Enabled for browser clients.
OpenAPI: See openapi.yaml for machine-readable schemas.
| Access | Routes | Header |
|---|---|---|
| Public | Discovery, status, prefix check, reserve, release (email), my-reservations, reports, duplicates, open | None |
| Admin | GET /api/reservations, GET /api/used, DELETE /api/release/<prefix> |
X-API-Key: <api_key> when [api] api_key is set in config.ini |
When api_key is blank, admin routes are also open (development only; set a key in production).
Public reserve and release never require an API key, matching the public website form.
Failed requests return JSON:
{ "error": "Human-readable message" }| Status | Meaning |
|---|---|
| 400 | Invalid input |
| 401 | Wrong or missing API key; email mismatch on release |
| 404 | Resource not found |
| 409 | Prefix already reserved |
API discovery: public route list, prefix_length, documentation path.
Response 200
{
"name": "Gulf Coast Mesh Monitor API",
"documentation": "docs/API.md",
"prefix_length": 4,
"authentication": { "public": "...", "admin": "..." },
"public_routes": [ { "method": "GET", "path": "/api/status", "description": "..." } ],
"admin_routes": [ { "method": "GET", "path": "/api/reservations" } ]
}Example
curl -s https://meshbuddy.gulfcoastmesh.org/apiService health and configuration useful for API clients.
Response 200
{
"status": "ok",
"timestamp": "2026-05-27T12:00:00",
"prefix_length": 4,
"mesh_map_url": "https://explorer.louisianamesh.org",
"website_url": "https://meshbuddy.gulfcoastmesh.org",
"reports": { "active_days": 14 }
}Example
curl -s https://meshbuddy.gulfcoastmesh.org/api/statusCheck whether a hex prefix can be reserved before calling POST /api/reserve.
Path
prefix— 4 hex characters (e.g.A1B2). Uppercase in responses.
Response 200
{
"prefix": "A1B2",
"available": true,
"reason": "available",
"message": "prefix is available to reserve"
}reason values
| reason | available |
Meaning |
|---|---|---|
available |
true | Can be reserved |
reserved |
false | In reservedNodes.json |
deployed |
false | Repeater with this prefix is active (offReserved.json) |
unusable |
false | 0000 or FFFF (convention) |
invalid |
false | Wrong length, non-hex, or 2-char (1-byte) prefix when 4-char required |
Example
curl -s https://meshbuddy.gulfcoastmesh.org/api/prefix/ABCD
curl -s https://meshbuddy.gulfcoastmesh.org/api/prefix/0000Reserve a repeater prefix (same data as the website reservation form).
Body (required)
| Field | Type | Description |
|---|---|---|
prefix |
string | 4 hex characters |
name |
string | Repeater name |
lat |
number | Latitude -90..90 |
lon |
number | Longitude -180..180 |
altitude |
number | Altitude (feet) |
email |
string | Contact email |
Body (optional)
| Field | Type | Default |
|---|---|---|
username |
string | api-user |
display_name |
string | username |
user_id |
number | 0 |
source |
string | api |
Response 201
{
"message": "Prefix A1B2 reserved successfully",
"reservation": {
"prefix": "A1B2",
"name": "My Repeater",
"lat": 30.45,
"lon": -91.19,
"altitude": 25.0,
"email": "you@example.com",
"username": "api-user",
"display_name": "api-user",
"user_id": 0,
"added_at": "2026-05-27T12:00:00",
"source": "api"
}
}Example
curl -s -X POST https://meshbuddy.gulfcoastmesh.org/api/reserve \
-H 'Content-Type: application/json' \
-d '{
"prefix": "A1B2",
"name": "Test Repeater",
"lat": 30.4515,
"lon": -91.1871,
"altitude": 50,
"email": "you@example.com"
}'Release a reservation. The email must match the one stored at reserve time.
Body (required)
| Field | Type |
|---|---|
prefix |
string |
email |
string |
Response 200
{
"message": "Prefix A1B2 released",
"prefix": "A1B2"
}Example
curl -s -X POST https://meshbuddy.gulfcoastmesh.org/api/release \
-H 'Content-Type: application/json' \
-d '{"prefix": "A1B2", "email": "you@example.com"}'List all prefix reservations tied to a contact email. Searches both active reservations (reservedNodes.json) and deployed reservations (offReserved.json). Returns an empty list when no matches are found (does not reveal whether the email exists elsewhere).
Body (required)
| Field | Type | Description |
|---|---|---|
email |
string | Contact email used at reserve time |
Response 200
{
"timestamp": "2026-06-16T12:00:00",
"email": "you@example.com",
"count": 2,
"reservations": [
{
"prefix": "A1B2",
"name": "My Repeater",
"lat": 30.45,
"lon": -91.19,
"altitude": 25.0,
"email": "you@example.com",
"username": "api-user",
"display_name": "api-user",
"user_id": 0,
"added_at": "2026-05-27T12:00:00",
"source": "api",
"status": "reserved"
},
{
"prefix": "CAFE",
"name": "Deployed Node",
"lat": 30.12,
"lon": -91.05,
"altitude": 40.0,
"email": "you@example.com",
"username": "api-user",
"display_name": "api-user",
"user_id": 0,
"added_at": "2026-04-10T08:30:00",
"source": "api",
"status": "deployed"
}
]
}status values
| status | Meaning |
|---|---|
reserved |
Active reservation (not yet deployed on the mesh) |
deployed |
Reservation moved to off-reserved after a live repeater matched |
Results are sorted by prefix ascending.
Example
curl -s -X POST https://meshbuddy.gulfcoastmesh.org/api/my-reservations \
-H 'Content-Type: application/json' \
-d '{"email": "you@example.com"}'Network health report (powers the /reports page). Includes summary stats, repeaters without location, and clock sync (minor drift and out-of-sync only in the repeater table).
Performance: First request after cache expiry may take several seconds while clock skew is fetched from the Gulf Coast Mesh Analyzer. Subsequent requests within the CoreScope cache TTL (~5 minutes) are faster.
Response 200 (top-level keys)
| Key | Description |
|---|---|
timestamp |
Report generation time |
config |
active_days, prefix_length |
summary |
total_nodes, repeaters, companions, needs_attention, recently_active |
no_location |
{ count, repeaters[] } — active repeaters missing GPS |
clock_sync |
Clock buckets and issue rows |
clock_sync
{
"source": "corescope",
"fetched": 225,
"missing": 25,
"ok": 110,
"minor": 12,
"out_of_sync": 82,
"unknown": 25,
"repeaters": [
{
"name": "Example",
"prefix": "ABCD",
"public_key": "ABCD...",
"last_seen": "2026-05-27T10:00:00+00:00",
"clock_skew_seconds": 120,
"clock_sync": "minor",
"clock_sync_label": "Minor Drift",
"location": { "text": "30.45, -91.19", "map_url": "..." },
"owner": null,
"advert_count": 42,
"region": "MSY"
}
]
}clock_sync.repeaters only includes minor and out_of_sync repeaters (not clock-OK nodes).
Example
curl -s https://meshbuddy.gulfcoastmesh.org/api/reportsRepeater prefixes used by more than one distinct repeater name (powers /duplicates).
Response 200
{
"timestamp": "2026-05-27T12:00:00",
"count": 3,
"duplicates": [
{
"prefix": "ABCD",
"count": 2,
"nodes": [
{ "name": "Repeater A", "public_key": "ABCD...", "last_seen": "..." },
{ "name": "Repeater B", "public_key": "ABCD...", "last_seen": "..." }
]
}
]
}Example
curl -s https://meshbuddy.gulfcoastmesh.org/api/duplicatesNot used by the public website; helpful for bots and integrators. Returns a sample of open prefixes and total count (not the full list when the space is large).
Response 200
{
"timestamp": "2026-05-27T12:00:00",
"count": 65000,
"open": ["0001", "0002", "..."]
}Example
curl -s https://meshbuddy.gulfcoastmesh.org/api/openRequire X-API-Key when api_key is set in config.ini.
All rows from reservedNodes.json (includes email addresses).
Deployed / off-reserved entries from offReserved.json.
Force-release without email verification (website admin dashboard).
curl -s -X DELETE https://meshbuddy.gulfcoastmesh.org/api/release/A1B2 \
-H 'X-API-Key: YOUR_SECRET'| Website page | API |
|---|---|
| Reserve | POST /api/reserve, GET /api/prefix/{prefix} |
| My prefixes | POST /api/my-reservations |
| Reports | GET /api/reports |
| Duplicates | GET /api/duplicates |
The website at meshbuddy.gulfcoastmesh.org proxies admin calls with a server-side API key; public pages use the endpoints above without a key.