Developers
MapsBox API v1
Read, create and update the road incidents in your workspace over HTTPS, and parse plain-English reports into structured data.
The base URL is https://mapbox.cc/v1. Requests and responses are JSON, except when you ask for GeoJSON. The API sends Access-Control-Allow-Origin: * and answers OPTIONS preflight requests with 204, so it can be called from a browser. It does not use cookies.
You need a workspace to get a token. Start a free trial
Authentication
Create a token in the console under API tokens (admins and owners can create them). Choose a name and at least one scope. The secret starts with mbx_ and is shown once, so copy it when it appears. Only a hash is stored. Revoke a token from the same screen.
Send the token as a Bearer header. You can also pass it as the access_token query parameter, but a header keeps it out of URLs and logs.
curl https://mapbox.cc/v1/incidents \
-H "Authorization: Bearer mbx_YOUR_TOKEN"
# or
curl "https://mapbox.cc/v1/incidents?access_token=mbx_YOUR_TOKEN"
Scopes
| Scope | Allows |
|---|---|
incidents:read | List and retrieve incidents. |
incidents:write | Create and update incidents. |
POST /v1/reports/parse accepts any valid token.
Incidents
An incident is one road event at one point: a crash, closure, construction zone, hazard or stretch of congestion.
The incident object
| Field | Type | Description |
|---|---|---|
id | string | Identifier, prefixed inc_. |
road | string | Road name, for example I-35. |
direction | string | null | Northbound, Southbound, Eastbound, Westbound or Both directions. |
type | string | crash, closure, construction, hazard or congestion. |
severity | string | major, moderate or minor. |
status | string | active or cleared. |
lanes | string | Lanes affected, for example two right lanes. |
location | string | Nearby cross street or landmark. |
description | string | Free-text notes. |
lng, lat | number | Longitude and latitude in decimal degrees. |
source | string | console, ai, api or sample. |
createdAt, updatedAt | string | ISO 8601 UTC timestamps. |
clearedAt | string | null | When the incident was cleared. null while active. |
{
"id": "inc_…",
"road": "I-35",
"direction": "Southbound",
"type": "crash",
"severity": "moderate",
"status": "active",
"lanes": "two right lanes",
"location": "Riverside Dr",
"description": "",
"lng": -97.73,
"lat": 30.25,
"source": "api",
"createdAt": "2026-11-01T10:15:00Z",
"updatedAt": "2026-11-01T10:15:00Z",
"clearedAt": null
}
List incidents
GET /v1/incidents Scope: incidents:read
| Parameter | Description |
|---|---|
status | active, cleared or all. Defaults to active. |
severity | Comma-separated list, for example major,moderate. |
type | Incident type, for example crash. |
bbox | Bounding box as minLng,minLat,maxLng,maxLat. |
since | ISO 8601 timestamp. Returns incidents with updatedAt at or after it. |
limit | Maximum incidents to return. Default 100, maximum 500. |
format | json (default) or geojson. |
curl "https://mapbox.cc/v1/incidents?severity=major,moderate&bbox=-97.95,30.10,-97.55,30.50" \
-H "Authorization: Bearer mbx_YOUR_TOKEN"
{
"incidents": [ { "id": "inc_…", "road": "I-35", /* … */ } ],
"count": 1
}
Retrieve an incident
GET /v1/incidents/:id Scope: incidents:read
Returns the incident object, or 404 not_found.
Create an incident
POST /v1/incidents Scope: incidents:write
Send a structured incident, or a plain-English report with a location. The response is 201 with the incident. The source is always set to api.
Structured
| Field | Required | Notes |
|---|---|---|
road | Yes | 1 to 80 characters. |
type | Yes | One of the incident types. |
severity | Yes | major, moderate or minor. |
lng, lat | Yes | Valid longitude (-180 to 180) and latitude (-90 to 90). |
direction | No | One of the direction values. |
lanes | No | Up to 80 characters. |
location | No | Up to 120 characters. |
description | No | Up to 1000 characters. |
curl -X POST https://mapbox.cc/v1/incidents \
-H "Authorization: Bearer mbx_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"road": "I-35",
"direction": "Southbound",
"type": "crash",
"severity": "moderate",
"lanes": "two right lanes",
"location": "Riverside Dr",
"lng": -97.73,
"lat": 30.25
}'
From a plain-English report
Send report, lng and lat. The report is parsed like Parse a report. If no road or incident type is detected, the API returns 422 validation_failed.
curl -X POST https://mapbox.cc/v1/incidents \
-H "Authorization: Bearer mbx_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "report": "Crash on I-35 southbound near Riverside Dr, two right lanes blocked", "lng": -97.73, "lat": 30.25 }'
Update an incident
PATCH /v1/incidents/:id Scope: incidents:write
Send any subset of the structured fields, plus status. Setting status to cleared sets clearedAt; setting it back to active clears it.
curl -X PATCH https://mapbox.cc/v1/incidents/inc_… \
-H "Authorization: Bearer mbx_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "status": "cleared" }'
Parse a report
POST /v1/reports/parse Any valid token
Turns a plain-English road report into structured fields without creating an incident. Use it to pre-fill your own forms.
curl -X POST https://mapbox.cc/v1/reports/parse \
-H "Authorization: Bearer mbx_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "text": "Crash on I-35 southbound near Riverside Dr, two right lanes blocked" }'
{
"parsed": {
"road": "I-35",
"direction": "Southbound",
"event": "crash",
"severity": "moderate",
"lanes": "two right lanes",
"location": "Riverside Dr",
"confidence": 0.95
}
}
event can also be cleared for messages such as “I-35 SB cleared”, or null when nothing is detected. confidence is between 0 and 1.
GeoJSON format
Add format=geojson to the list request to receive a FeatureCollection. Each incident is a Point feature at [lng, lat], and its properties are the incident fields without lng and lat.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-97.73, 30.25] },
"properties": {
"id": "inc_…",
"road": "I-35",
"direction": "Southbound",
"type": "crash",
"severity": "moderate",
"status": "active"
/* lanes, location, description, source, createdAt, updatedAt, clearedAt */
}
}
]
}
Errors
Errors use a standard HTTP status and this body:
{ "error": { "code": "invalid_token", "message": "…" } }
| Status | Code | Meaning |
|---|---|---|
| 401 | invalid_token | The token is missing, malformed or revoked. |
| 403 | insufficient_scope | The token does not have the scope this endpoint needs. |
| 403 | trial_expired | The workspace trial has ended. Contact us to move to a paid plan. |
| 404 | not_found | The incident does not exist in your workspace. |
| 422 | validation_failed | The body is invalid, or a report did not contain a detectable road and type. |
| 429 | quota_exceeded | The monthly API quota for your plan is used up. |
Quotas & usage
Every authenticated call counts toward your workspace’s monthly usage, which you can see in the console. Limits depend on the plan.
| Plan | API calls per month |
|---|---|
| Trial | 10,000 |
| Business | 2,000,000 |
| Enterprise | Unlimited |
Responses include X-Quota-Limit and X-Quota-Remaining. Both are omitted when the plan is unlimited. After the quota is used up, requests return 429 quota_exceeded.
Example: show live incidents on a map
This script loads active incidents as GeoJSON into a MapLibre GL JS map and colors them by severity. A token placed in browser code is visible to anyone who opens the page, so use a token that only has incidents:read and revoke it if it leaks.
const map = new maplibregl.Map({
container: 'map',
style: 'https://tiles.openfreemap.org/styles/positron',
center: [-97.7431, 30.2672],
zoom: 10,
});
map.on('load', async () => {
const response = await fetch(
'https://mapbox.cc/v1/incidents?format=geojson&status=active',
{ headers: { Authorization: 'Bearer mbx_YOUR_READ_TOKEN' } },
);
map.addSource('incidents', { type: 'geojson', data: await response.json() });
map.addLayer({
id: 'incidents',
type: 'circle',
source: 'incidents',
paint: {
'circle-radius': 7,
'circle-stroke-width': 2,
'circle-stroke-color': '#ffffff',
'circle-color': ['match', ['get', 'severity'],
'major', '#f04438', 'moderate', '#f79009', '#fac515'],
},
});
});