Skip to main content
Arterial publishes a read-only ArcGIS FeatureServer that mirrors the operational data from the dashboard so your existing GIS stack can consume it directly. The same layers are also available as a multi-shapefile zip through the Settings → Workspace → GIS exports panel. This is the integration surface for analysts who want hazards, coverage cells, detections, and the org’s service-area polygon to live alongside their other reference data.

Service URL

https://app.arterial.us/api/arcgis/arterial/FeatureServer
The service is read-only and authenticated by a long-lived token issued from the dashboard. Hand the token over via a ?token= query parameter; ArcGIS clients can paste the URL with the token appended (...?token=artgis_…) into Add Data → From URL. The legacy hazards-only path https://app.arterial.us/api/arcgis/hazards/FeatureServer/0 continues to work unchanged for clients that already integrated against it.

Layers

The service exposes four parent layers plus seven pre-filtered sub-layers for clients that prefer to subscribe to a slice rather than apply a where= clause.
#NameGeometryNotes
0HazardsPointEvery hazard owned by your org.
1Coverage CellsPolygonH3 resolution-9 hexes inside your service area, with read counts.
3DetectionsPointRaw detections (pre-rollup) inside your service area.
4Service AreaPolygonYour org’s boundary as a single polygon.
5Hazards — ActivePointHazards whose work order is unfiled or scheduled.
6Hazards — ResolvedPointHazards whose work order is complete.
7Coverage Cells — Fresh (≤7d)PolygonCells last visited within seven days.
8Coverage Cells — Stale (>30d)PolygonCells whose last visit is older than thirty days.
9Coverage Cells — Gap (never)PolygonCells inside the service area never visited in the lookback window.
10Detections — Rolled UpPointDetections that already belong to a hazard.
11Detections — OrphanPointDetections inside the service area that aren’t yet associated with any hazard.

Service manifest

GET /api/arcgis/arterial/FeatureServer?f=json&token=...
Returns the service descriptor — every client uses this to learn the layer set. Each entry includes its numeric id, parentLayerId (-1 for top-level layers), and the canonical layer URL.

Layer descriptor

GET /api/arcgis/arterial/FeatureServer/{layerId}?f=json&token=...
Returns the field schema, geometry type, and pagination caps for one layer. Field metadata uses the standard esriFieldType* identifiers (esriFieldTypeOID, esriFieldTypeString, esriFieldTypeInteger, esriFieldTypeDouble, esriFieldTypeSmallInteger).

Querying features

GET /api/arcgis/arterial/FeatureServer/{layerId}/query
    ?f=json
    &where=1%3D1
    &outFields=*
    &resultOffset=0
    &resultRecordCount=1000
    &returnGeometry=true
    &token=...
Supported parameters:
  • fjson (default), pjson, or geojson. Use geojson to pull the layer straight into QGIS or a Mapbox style.
  • where — must be 1=1. Custom predicates are not supported on this read-only mirror; subscribe to a sub-layer instead.
  • outFields* for all attributes, or a comma-separated list of field names.
  • objectIds — comma-separated list of OBJECTID values to fetch.
  • resultOffset / resultRecordCount — pagination. The maximum page size is 1000 records.
  • returnGeometry — set false to omit geometry (handy for attribute-only joins).
  • returnCountOnly — returns { count: N } and skips the feature payload.
  • returnIdsOnly — returns the array of OBJECTID values only.

Attribute schemas

Hazards (/0, /5, /6)

FieldTypeNotes
OBJECTIDOID
hazard_uuidStringStable UUID.
typeStringHazard category (pothole, crack, …).
priorityDoublePriority score.
statusStringunfiled / scheduled / complete.
last_detected_atStringISO 8601.
detection_countIntegerDetections rolled into this hazard.
owned_by_orgStringOrg display name.
viewer_redactedSmallInt1 when the viewer org has read-but-redacted access.
latitudeDouble
longitudeDouble
addressaddress_stateStringWhen known.

Coverage cells (/1, /7, /8, /9)

FieldTypeNotes
OBJECTIDOID
h3_cellString15-char hex H3 index at resolution 9.
h3_resSmallIntAlways 9 in this release.
reads_countIntegerTotal reads in the lookback window.
last_read_atStringISO 8601. null for gap cells.
days_since_last_readInteger-1 for gap cells.

Detections (/3, /10, /11)

FieldTypeNotes
OBJECTIDOID
detection_uuidString
typeStringDetection category.
confidenceDoubleModel confidence score.
is_approvedSmallInt1 when an operator approved.
captured_atStringISO 8601.
device_uuidString
hazard_uuidStringParent hazard, or null for orphan detections.
model_versionString
latitudeDouble
longitudeDouble

Service area (/4)

FieldTypeNotes
OBJECTIDOID
org_uuidString
org_nameString
area_km2DoublePolygon area in square kilometres.

Adding the service to ArcGIS Online

  1. In ArcGIS Online, open Map Viewer and choose Add → Add layer from URL.
  2. Paste the service URL with your token appended: https://app.arterial.us/api/arcgis/arterial/FeatureServer?token=artgis_…
  3. ArcGIS reads the manifest and shows the layer list. Add as many as you want — top-level layers, sub-layers, or both.
  4. Save the map. When the underlying data updates, refresh the layer from the layer settings menu.

Adding the service to QGIS

  1. Open Layer → Add Layer → Add ArcGIS REST Server Layer.
  2. Use New Connection, paste the service URL (without /0 — FeatureServer root only), and store the token in the query string.
  3. Choose the layers you need from the connection’s layer list.

Multi-layer shapefile export

The dashboard’s GIS exports panel issues an export job that produces a single .zip file containing one shapefile (.shp, .shx, .dbf, .prj) per requested layer, plus a top-level manifest.json describing the bundle:
{
  "version": 1,
  "generatedAt": "2026-05-10T17:42:00.000Z",
  "layers": [
    {
      "id": 0,
      "key": "hazards.all",
      "name": "Hazards",
      "geometryType": "esriGeometryPoint",
      "featureCount": 1842
    },
    {
      "id": 4,
      "key": "service_area.all",
      "name": "Service Area",
      "geometryType": "esriGeometryPolygon",
      "featureCount": 1
    }
  ]
}
Each layer’s shapefile lives under a folder named after the stable layer key with dots replaced by underscores (hazards_all/, coverage_cells_fresh/, …) so unzip-into-folder workflows produce a clean per-layer directory tree. The legacy single-layer export (when no layers field is supplied) keeps producing arterial-hazards.zip with the same shape it always had — your existing automation does not need to change.

Multi-layer ESRI JSON export

When the export format is esri_json and more than one layer is requested, the response is a versioned envelope:
{
  "version": 1,
  "exportedAt": "2026-05-10T17:42:00.000Z",
  "layers": [
    {
      "id": 0,
      "key": "hazards.all",
      "name": "Hazards",
      "geometryType": "esriGeometryPoint",
      "fields": [{ "name": "OBJECTID", "alias": "Object ID", "type": "esriFieldTypeOID" }, ],
      "result": {
        "exceededTransferLimit": false,
        "totalCount": 1842,
        "features": [{ "attributes": {  }, "geometry": {  } }, ]
      }
    },

  ]
}
Single-layer ESRI JSON exports continue to use the flat { features: [...], fields: [...], … } shape for back-compat.

Limits and quirks

  • Read-only — the service does not support applyEdits.
  • where=1=1 is the only supported predicate. Filter by subscribing to the relevant sub-layer instead.
  • Page size is capped at 1000 records. Iterate resultOffset to stream large layers.
  • Coverage cells query against an H3 resolution-9 grid clipped to your service area. The lookback window for a single query is one year.
  • Orphan detections are scoped to your org by checking each detection’s (latitude, longitude) against your service-area polygon — a detection that drifts outside the polygon will not appear in /11.
Last modified on May 11, 2026