Ground Intelligence

Integrate ground intelligence into 311 systems and Work Order Management systems

Ground Intelligence

Create a Samsara API integration for 311 verification and work-order workflows.

Introduction

Ground Intelligence gives public-sector agencies continuous visibility into roadway and right-of-way conditions using the Samsara vehicle network — without dedicated survey trucks or reactive windshield time. Agencies can automatically detect road surface issues (such as potholes), remotely verify citizen-reported locations with Watchpoints, and sync that evidence into the systems they already use for 311 and work-order management.

Watch a short product overview: Ground Intelligence demo video.

What You Will Learn: This guide covers the Ground Intelligence capabilities that matter for integrations, then walks through two common workflows — creating Watchpoints from 311 requests, and syncing Road Issues into work-order systems (Cityworks, Tyler EAM, OpenGov, and similar) with a Resolved write-back to Samsara when the work order completes. You'll walk away with request/response examples for the Watchpoints create API and the Road Issues list and update APIs.

High-level overview

Ground Intelligence exposes two integration building blocks. In product and API documentation, call them Road Issues and Watchpoints.

Road Issues

Road Issues are AI-detected road surface conditions (for example, potholes and road cracking) aggregated from the Samsara network as vehicles drive your jurisdiction. Each issue includes location, type, severity, review status, observation counts, and a dashboard link so crews can inspect video evidence before they leave the yard.

Learn more in the knowledge base: Road Conditions Visibility.

Primary endpoints for integrations:

EndpointUse
GET /ground-intelligence/issuesList and filter Road Issues to sync into a work-order or asset system
PATCH /ground-intelligence/issues?id={id}Set status to resolved when the linked work order completes in the source system

Watchpoints

Watchpoints let you pin a specific map location and collect privacy-filtered dashcam observations as Samsara-equipped vehicles pass nearby. Use them when you need on-demand visual verification — for example, a citizen 311 report on a low-coverage street — without dispatching a supervisor first.

Learn more in the knowledge base: Watchpoints.

Primary endpoint for integrations:

EndpointUse
POST /ground-intelligence/watchpointsCreate a Watchpoint from an external system (for example, a 311 service request)

Beta note: Watchpoints create (POST) and Road Issues list/update (GET / PATCH) are Ground Intelligence API capabilities under the Ground Intelligence scopes on your API token or OAuth app. Confirm the required scopes in Authentication when you create the token.

Integration use cases

311 integrations

Problem today: In many 311 workflows, a request comes in from the public and there is no way to verify what the location looks like on the ground. Agencies often send supervisors or inspectors to validate the report. Sometimes there is no issue at all; sometimes a different crew or materials are needed than what the ticket implied. That validation step burns time, fuel, and crew capacity before repair work even starts.

With Ground Intelligence: When a 311 request is created (or routed) for a roadway / right-of-way issue, your integration can automatically create a Watchpoint at the reported coordinates. As Samsara network vehicles pass the location, observation video appears in Samsara for remote verification — so you can confirm the condition, prioritize the right crew, and avoid an unnecessary truck roll.

Integration flow

  1. A citizen submits a 311 request (pothole, utility cut concern, damaged signage, etc.).
  2. Your middleware maps the 311 location (and optional description) into a Watchpoint create request.
  3. Call POST /ground-intelligence/watchpoints with observationType, location, and mode.
  4. Store the returned Watchpoint id (and optionally samsaraDashboardUrl) on the 311 ticket.
  5. Staff review collected observations in Samsara, then update the 311 ticket / create a work order with verified context.

Create a Watchpoint

Required body fields:

  • observationType — condition to observe (for example, roadDefect, utilityCut, signage, stormDrain, vegetation, other)
  • location.latitude / location.longitude — WGS-84 coordinates from the 311 request
  • mode — collection frequency: justOnce, daily, weekly, or monthly

Optional fields:

  • name — up to 80 characters (for example, the 311 request ID)
  • note — up to 280 characters (for example, the citizen description)

Example request:

curl --request POST "https://api.samsara.com/ground-intelligence/watchpoints" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer $SAMSARA_API_TOKEN" \
  --data '{
    "name": "311-REQ-184422",
    "note": "Citizen reported pothole in eastbound lane near intersection.",
    "observationType": "roadDefect",
    "location": {
      "latitude": 37.7749,
      "longitude": -122.4194
    },
    "mode": "justOnce"
  }'
import os
import requests

response = requests.post(
    "https://api.samsara.com/ground-intelligence/watchpoints",
    headers={
        "Authorization": f"Bearer {os.environ['SAMSARA_API_TOKEN']}",
        "Content-Type": "application/json",
    },
    json={
        "name": "311-REQ-184422",
        "note": "Citizen reported pothole in eastbound lane near intersection.",
        "observationType": "roadDefect",
        "location": {
            "latitude": 37.7749,
            "longitude": -122.4194,
        },
        "mode": "justOnce",
    },
)
response.raise_for_status()
watchpoint = response.json()["data"]
print(watchpoint["id"], watchpoint["samsaraDashboardUrl"])

Example response:

{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "311-REQ-184422",
    "note": "Citizen reported pothole in eastbound lane near intersection.",
    "observationType": "roadDefect",
    "location": {
      "latitude": 37.7749,
      "longitude": -122.4194
    },
    "mode": "justOnce",
    "status": "active",
    "monitoringStartTime": "2026-07-15T10:00:00Z",
    "monitoringEndTime": "2026-07-22T10:00:00Z",
    "createdAtTime": "2026-07-15T10:00:00Z",
    "updatedAtTime": "2026-07-15T10:00:01Z",
    "observationCount": 0,
    "lastObservationTime": null,
    "samsaraDashboardUrl": "https://cloud.samsara.com/o/123456/fleet/ground-intelligence?tab=monitors&monitorId=550e8400-e29b-41d4-a716-446655440000"
  }
}

Implementation tips

  • Prefer justOnce for one-off 311 verification. Use daily, weekly, or monthly when you need recurring evidence (for example, post-storm monitoring or utility-cut warranty checks).
  • Put the external 311 request ID in name (or note) so operators can correlate systems quickly.
  • Watchpoint observations depend on Samsara network vehicles passing the pin; first footage often arrives within hours to a few days depending on corridor coverage — set that expectation in the 311 workflow, not “real-time camera PTZ.”
  • Persist the Samsara Watchpoint id on the 311 record so later status or follow-up tooling can reference the same location.

Work order integrations

Problem today: Road Issues detected in Samsara still need to become actionable work in the agency system of record — Cityworks, Tyler EAM, OpenGov, and similar. Without an integration, teams export CSVs, re-key locations, and lose the closed-loop connection between detection, repair, and completion.

With Ground Intelligence: Pull Road Issues into your work-order system, create service requests or work orders according to your agency’s review model, then write the Road Issue back to Samsara as Resolved when the work order completes in the source system.

Part 1 — Sync Road Issues into the work-order system

Use GET /ground-intelligence/issues to list Road Issues, then create corresponding records in the external system. Choose one of the following sync patterns (or combine them by queue/status).

Option 1: Review in Samsara, then sync reviewed issues

Operators triage video evidence in the Samsara dashboard, mark qualifying Road Issues as reviewed, and your integration syncs only those reviewed issues into the work-order system as work orders.

curl --request GET "https://api.samsara.com/ground-intelligence/issues" \
  -G \
  --data-urlencode "types=pothole" \
  --data-urlencode "statuses=reviewed" \
  --data-urlencode "queryByTimeField=updatedAtTime" \
  --data-urlencode "startTime=2026-07-01T00:00:00Z" \
  --header "Authorization: Bearer $SAMSARA_API_TOKEN"
import os
import requests

response = requests.get(
    "https://api.samsara.com/ground-intelligence/issues",
    headers={"Authorization": f"Bearer {os.environ['SAMSARA_API_TOKEN']}"},
    params={
        "types": "pothole",
        "statuses": "reviewed",
        "queryByTimeField": "updatedAtTime",
        "startTime": "2026-07-01T00:00:00Z",
    },
)
response.raise_for_status()
issues = response.json()["data"]

This pattern keeps human validation in Samsara and reduces noise in the CMMS.

Option 2: Sync everything as service requests for validation in the work-order system

Pull open Road Issues (for example, needsReview) into the work-order system as service requests / investigations. Users validate severity and jurisdiction in the CMMS, then promote validated items to work orders.

curl --request GET "https://api.samsara.com/ground-intelligence/issues" \
  -G \
  --data-urlencode "types=pothole,roadCracking,patchedPothole" \
  --data-urlencode "statuses=needsReview" \
  --data-urlencode "queryByTimeField=updatedAtTime" \
  --data-urlencode "startTime=2026-07-01T00:00:00Z" \
  --header "Authorization: Bearer $SAMSARA_API_TOKEN"
import os
import requests

response = requests.get(
    "https://api.samsara.com/ground-intelligence/issues",
    headers={"Authorization": f"Bearer {os.environ['SAMSARA_API_TOKEN']}"},
    params={
        "types": "pothole,roadCracking,patchedPothole",
        "statuses": "needsReview",
        "queryByTimeField": "updatedAtTime",
        "startTime": "2026-07-01T00:00:00Z",
    },
)
response.raise_for_status()
issues = response.json()["data"]

This pattern is useful when the work-order system is already the agency’s triage surface.

Option 3: Sync high-severity issues only (more automated)

Filter to high-severity Road Issues and create work orders automatically, relying on Samsara’s severity ranking to prioritize the most impactful defects first.

curl --request GET "https://api.samsara.com/ground-intelligence/issues" \
  -G \
  --data-urlencode "types=pothole" \
  --data-urlencode "severities=high" \
  --data-urlencode "statuses=needsReview,reviewed" \
  --data-urlencode "queryByTimeField=updatedAtTime" \
  --data-urlencode "startTime=2026-07-01T00:00:00Z" \
  --header "Authorization: Bearer $SAMSARA_API_TOKEN"
import os
import requests

response = requests.get(
    "https://api.samsara.com/ground-intelligence/issues",
    headers={"Authorization": f"Bearer {os.environ['SAMSARA_API_TOKEN']}"},
    params={
        "types": "pothole",
        "severities": "high",
        "statuses": "needsReview,reviewed",
        "queryByTimeField": "updatedAtTime",
        "startTime": "2026-07-01T00:00:00Z",
    },
)
response.raise_for_status()
issues = response.json()["data"]

Example list response:

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "type": "pothole",
      "location": {
        "type": "point",
        "point": {
          "latitude": 37.7749,
          "longitude": -122.4194
        }
      },
      "roadSegment": {
        "roadName": "Market Street"
      },
      "status": "needsReview",
      "severity": "high",
      "observationCount": 8,
      "dashboardUrl": "https://cloud.samsara.com/o/123/fleet/ground-intelligence",
      "firstSeenTime": "2026-07-10T13:22:00.000Z",
      "lastSeenTime": "2026-07-12T13:22:00.000Z",
      "createdAtTime": "2026-07-10T13:23:20.000Z",
      "updatedAtTime": "2026-07-12T13:23:20.000Z"
    }
  ],
  "pagination": {
    "endCursor": "eyJ1cGRhdGVkQXRUaW1lIjoiMjAyNi0wNy0xMlQxMzoyMzoyMFoifQ==",
    "hasNextPage": true
  }
}
Mapping guidance for Part 1

When creating the external work order / service request, map at least:

Samsara Road Issue fieldTypical work-order field
idExternal / source system ID (store for write-back)
typeIssue / asset problem type
severityPriority
location.point.latitude / longitudeWork location
roadSegment.roadNameStreet / asset description
dashboardUrlLink back to Samsara evidence
firstSeenTime / lastSeenTimeReported / last observed timestamps

Use cursor pagination (pagination.endCursorafter) until hasNextPage is false. For incremental sync, filter on queryByTimeField=updatedAtTime with a sliding startTime.

Part 2 — Write work-order completion back to Samsara as Resolved

When a work order completes in the source system (Cityworks, Tyler EAM, OpenGov, or similar), write that completion back to Samsara by setting the linked Road Issue status to resolved.

Use PATCH /ground-intelligence/issues?id={id} with the Samsara Road Issue id you stored during Part 1 sync. This closes the loop so Ground Intelligence no longer treats the defect as open work.

Recommended trigger: on work-order completion / closed in the CMMS (not on create or assignment). Look up the stored Samsara Road Issue id for that work order, then PATCH:

curl --request PATCH "https://api.samsara.com/ground-intelligence/issues?id=550e8400-e29b-41d4-a716-446655440000" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer $SAMSARA_API_TOKEN" \
  --data '{
    "status": "resolved"
  }'
import os
import requests

issue_id = "550e8400-e29b-41d4-a716-446655440000"
response = requests.patch(
    "https://api.samsara.com/ground-intelligence/issues",
    headers={
        "Authorization": f"Bearer {os.environ['SAMSARA_API_TOKEN']}",
        "Content-Type": "application/json",
    },
    params={"id": issue_id},
    json={"status": "resolved"},
)
response.raise_for_status()
updated_issue = response.json()["data"]

Example response (Road Issue now Resolved):

{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "type": "pothole",
    "location": {
      "type": "point",
      "point": {
        "latitude": 37.7749,
        "longitude": -122.4194
      }
    },
    "roadSegment": {
      "roadName": "Market Street"
    },
    "status": "resolved",
    "severity": "high",
    "observationCount": 8,
    "dashboardUrl": "https://cloud.samsara.com/o/123/fleet/ground-intelligence",
    "firstSeenTime": "2026-07-10T13:22:00.000Z",
    "lastSeenTime": "2026-07-12T13:22:00.000Z",
    "createdAtTime": "2026-07-10T13:23:20.000Z",
    "updatedAtTime": "2026-07-20T16:05:00.000Z"
  }
}

Status and filter reference (Road Issues)

FieldSupported values
typepothole, roadCracking, patchedPothole
status (list filters)needsReview, reviewed, resolved, dismissed
severitylow, medium, high

For Part 2 write-back, set status to resolved when the source-system work order completes. Location, severity, observation counts, G-force metrics, dashboard URL, and timestamps are read-only on PATCH.

Key Samsara API endpoints for Ground Intelligence integrations

  • Create Watchpoint (POST /ground-intelligence/watchpoints): Create an on-demand verification pin from 311 or other intake systems. Requires observationType, location, and mode.
  • List Road Issues (GET /ground-intelligence/issues): Paginated list with filters for types, statuses, severities, ids, startTime, endTime, and queryByTimeField (updatedAtTime or lastSeenTime).
  • Update Road Issue (PATCH /ground-intelligence/issues?id={id}): Set status to resolved when the linked work order completes in the source system, so Ground Intelligence reflects that the Road Issue is closed.

All requests require a Bearer token (Authorization: Bearer <token>) from an API token or OAuth access token with the appropriate Ground Intelligence scopes. Responses are JSON and include a top-level data object or array; list endpoints also return pagination.

Getting started with authentication

Samsara supports API tokens (direct integrations) and OAuth 2.0 (recommended for Marketplace apps). See:

For Ground Intelligence integrations, create a dedicated token (or OAuth app) with only the Ground Intelligence scopes your workflow needs — for example, write access for Watchpoints create, and read/write access for Road Issues sync and Resolved write-back.


Did this page help you?