TerraGo API

Devices

Onboard Band/Bag Tags hardware (trackers/scanners). Register devices (admin, public self-registration, and approval), look up a device by serial number, update device details, and read live telemetry — heartbeat-derived status, status history and data-usage.

9 endpoint(s)
GET List Devices {{url}}/devices

Retrieve a paginated list of hardware devices (trackers, scanners, gateways) registered with TerraGo.

Query Parameters

  • per_page (integer, optional, default 10, max 20)
  • status (string, optional): ONLINE, OFFLINE, LOWBATTERY, PENDINGAPPROVAL, OTHER, or N/A.
  • assigned (integer, optional): 1 for devices assigned to a school/staff, 0 for unassigned.
  • supervisor_id (string UUID, optional): Filter by Administrative Staff (school).
  • search (string, optional): Matches name, description, or serial number.

Response

Paginated list of devices (data) with meta; each includes live-derived status, battery, NFC/location flags, signal and data usage.

Auth
Bearer token
Used On
Request Body
{
    "status": "ONLINE", //only use: ONLINE, OFFLINE, LOW_BATTERY, OTHER, N/A
    "search": "",
    "supervisor_id": "68b86410-e6e8-4b5f-9a3d-8265a7773c0e",
    "per_page": 10,
    "page": 1
}
Sample Response (200 OK)
{
    "data": [
        {
            "id": "e91c072b-508c-448d-a368-f22c34434742",
            "name": "name",
            "description": "description",
            "sim_phone_number": "+254725544432",
            "serial_number": "serial_number",
            "waas_zone_uuid": "ada52fc6-d481-48d9-82b3-fddb07d5d44f",
            "waas_zone_name": "Terra HQ",
            "est_data_usage": "2000",
            "type": "Scanner",
            "administrative_staff": {
                "id": "68b86410-e6e8-4b5f-9a3d-8265a7773c0e",
                "first_name": "Jane",
                "last_name": "Otieno"
            },
            "status": "Online",
            "last_activity": "2025-12-27 14:10:56",
            "battery_level": 100,
            "metadata": null
        }
    ],
    "links": {
        "first": "http://localhost:8001/api/devices?page=1",
        "last": "http://localhost:8001/api/devices?page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "links": [
            {
                "url": null,
                "label": "« Previous",
                "page": null,
                "active": false
            },
            {
                "url": "http://localhost:8001/api/devices?page=1",
                "label": "1",
                "page": 1,
                "active": true
            },
            {
                "url": null,
                "label": "Next »",
                "page": null,
                "active": false
            }
        ],
        "path": "http://localhost:8001/api/devices",
        "per_page": 15,
        "to": 1,
        "total": 1
    },
    "status": 200,
    "message": "Devices Retrieved Successfully"
}
GET Get Device by Serial Number {{url}}/devices/get-by-serial/serial_number

Look up a device by its physical serial number rather than its internal UUID — handy when scanning/typing a label off the hardware itself.

Path Parameters

  • id (string, required): The device's serial_number (not its UUID, despite the parameter name).

Response

The single device (data).

Auth
Bearer token
Sample Response (200 OK)
{
    "status": 200,
    "data": {
        "id": "1aa126a1-f056-4b4e-bd59-9b821ff50bb9",
        "name": "name",
        "description": "description",
        "sim_phone_number": null,
        "serial_number": "serial_number",
        "waas_zone_uuid": null,
        "waas_zone_name": null,
        "est_data_usage": null,
        "type": "Scanner",
        "administrative_staff": {
            "id": "46b0a803-39c8-4113-8b29-8ef30438c5bd",
            "first_name": "PM",
            "last_name": "School"
        },
        "status": "Pending Approval",
        "last_activity": "2026-01-27 09:57:54",
        "battery_level": 100,
        "metadata": null
    },
    "message": "Device retrieved successfully"
}
PUT Update Device {{url}}/devices/update/e91c072b-508c-448d-a368-f22c34434742

Update a device's configuration. Changes are pushed to TerraGo's zone/location and tag registry in the same request (transactional — if the registry call fails, nothing is saved locally).

Path Parameters

  • id (string UUID, required): Device UUID.

Request Body

  • name (string, required)
  • description (string, required)
  • serial_number (string, required, must be unique)
  • type (string, required): TRACKER, SCANNER, GATEWAY, OTHER, or N/A.
  • estdatausage (integer, required, min 1): Estimated monthly data usage.
  • imei (string, optional, max 32)
  • simphonenumber (string, optional)
  • waaszoneuuid / waaszonename (string, optional): Reassign to a different vehicle/zone/location.
  • status (string, optional): ONLINE, OFFLINE, LOWBATTERY, PENDINGAPPROVAL, OTHER, or N/A.
  • battery_level (integer, optional, 0–100, default 100)
  • administativestaffid (string UUID, optional): School the device belongs to; resolved from the authenticated user if omitted.

Notes

  • If batterylevel is 25 or below, status is forced to LOWBATTERY regardless of what's passed in.
  • administativestaffid must be resolvable (from the request or from your own account) or this returns a 422.
Auth
Bearer token
Used On
Request Body
{
   "name": "name",
    "description": "description",
    "serial_number": "serial_number",
    "administative_staff_id":"68b86410-e6e8-4b5f-9a3d-8265a7773c0e",
    "sim_phone_number": "+254725544432",
    "waas_zone_uuid":"ada52fc6-d481-48d9-82b3-fddb07d5d44f",
    "waas_zone_name":"Terra HQ",
    "est_data_usage":"2000", //In MBs
    "type": "SCANNER", //only use: SCANNER, GATEWAY, TRACKER, OTHER, N/A
    "battery_level":"100",
    "status": "ONLINE" //only use: ONLINE, OFFLINE, LOW_BATTERY, OTHER, N/A
}
Sample Response (200 OK)
{
    "status": 200,
    "data": {
        "id": "e91c072b-508c-448d-a368-f22c34434742",
        "name": "name",
        "description": "description",
        "sim_phone_number": "+254725544432",
        "serial_number": "serial_number",
        "waas_zone_uuid": "ada52fc6-d481-48d9-82b3-fddb07d5d44f",
        "waas_zone_name": "Terra HQ",
        "est_data_usage": "2000",
        "type": "Scanner",
        "administrative_staff": {
            "id": "68b86410-e6e8-4b5f-9a3d-8265a7773c0e",
            "first_name": "Jane",
            "last_name": "Otieno"
        },
        "status": "Online",
        "last_activity": "2025-12-27 14:56:47",
        "battery_level": "100",
        "metadata": null
    },
    "message": "Device updated successfully"
}
POST Register Device (Admin) {{url}}/devices/add

Register a new device directly (as an admin), immediately creating it in both TerraGo and TerraGo's zone/location and tag registry with ONLINE status. Compare to Request Registration, which is the self-service flow devices use before an admin approves them.

Request Body

Same fields as Update Device: name, description, serialnumber (required, unique), type (required), estdatausage (required), plus optional imei, simphonenumber, waaszoneuuid, waaszonename, status, batterylevel, administativestaffid.

Notes

  • Also seeds an initial device-status-log entry so uptime tracking has a baseline from creation time.

Response

The created device (data).

Auth
Bearer token
Used On
Request Body
{
   "name": "name",
    "description": "description",
    "serial_number": "serial_number",
    "administative_staff_id":"68b86410-e6e8-4b5f-9a3d-8265a7773c0e",
    "sim_phone_number": "+254725544432",
    "waas_zone_uuid":"ada52fc6-d481-48d9-82b3-fddb07d5d44f",
    "waas_zone_name":"Terra HQ",
    "est_data_usage":"2000", //In MBs
    "type": "SCANNER" //only use: SCANNER, GATEWAY, TRACKER, OTHER, N/A
}
Sample Response (200 OK)
{
    "status": 200,
    "data": {
        "id": "e91c072b-508c-448d-a368-f22c34434742",
        "name": "name",
        "description": "description",
        "sim_phone_number": "+254725544432",
        "serial_number": "serial_number",
        "waas_zone_uuid": "ada52fc6-d481-48d9-82b3-fddb07d5d44f",
        "waas_zone_name": "Terra HQ",
        "est_data_usage": "2000",
        "type": "Scanner",
        "administrative_staff": {
            "id": "68b86410-e6e8-4b5f-9a3d-8265a7773c0e",
            "first_name": "Jane",
            "last_name": "Otieno"
        },
        "status": "Online",
        "last_activity": "2025-12-27 14:10:56",
        "battery_level": 100,
        "metadata": null
    },
    "message": "Device registered successfully"
}
POST Self-Register Device (Public) {{url}}/devices/request-registration

Public, unauthenticated endpoint a device (or field technician) calls to request that a device be added to the system. Creates the device with PENDING_APPROVAL status and does not sync to the registry yet — an admin must call Approve Registration to finish onboarding it.

Request Body

  • name (string, required)
  • description (string, required)
  • serial_number (string, required, must be globally unique)

Notes

  • No bearer token required — this is meant to be callable from the device itself before it has any credentials.

Response

Confirmation the registration request was submitted (data) — the device is pending admin approval.

Auth
Bearer token
Request Body
{
    "name": "name",  // Human-readable name / label
    "description": "description",  // Optional free-text description
    "serial_number": "serial_number"  // Device serial number
}
Sample Response (200 OK)
{
    "status": 200,
    "data": {
        "id": "1aa126a1-f056-4b4e-bd59-9b821ff50bb9",
        "name": "name",
        "description": "description",
        "sim_phone_number": null,
        "serial_number": "serial_number",
        "waas_zone_uuid": null,
        "waas_zone_name": null,
        "est_data_usage": null,
        "type": "Scanner",
        "administrative_staff": {
            "id": "46b0a803-39c8-4113-8b29-8ef30438c5bd",
            "first_name": "PM",
            "last_name": "School"
        },
        "status": "Pending Approval",
        "last_activity": "2026-02-27 10:30:12",
        "battery_level": null,
        "metadata": null
    },
    "message": "Device registered successfully"
}
POST Approve Device Registration {{url}}/devices/approve/1aa126a1-f056-4b4e-bd59-9b821ff50bb9

Admin approval step that completes onboarding for a device previously created via Request Registration: fills in the remaining details, syncs it to the registry, and moves it out of PENDING_APPROVAL.

Path Parameters

  • id (string UUID, required): Device UUID (the one created by the self-registration call).

Request Body

Same fields as Update Deviceadministativestaffid is effectively required here since it determines which school the device is registered to in the registry.

Response

The approved/activated device (data).

Auth
Bearer token
Request Body
{
    "name": "name",
    "description": "description",
    "serial_number": "serial_number",
    "administative_staff_id":"46b0a803-39c8-4113-8b29-8ef30438c5bd",
    "sim_phone_number": "+254725544432",
    "waas_zone_uuid":"ada52fc6-d481-48d9-82b3-fddb07d5d44f",
    "waas_zone_name":"Terra HQ",
    "est_data_usage":"2000", //In MBs
    "type": "SCANNER" //only use: SCANNER, GATEWAY, TRACKER, OTHER, N/A
}
Sample Response (200 OK)
{
    "status": 200,
    "data": {
        "id": "38de6cc4-9043-454b-b3f2-ac67b591b09e",
        "name": "name",
        "description": "description",
        "sim_phone_number": "+254725544432",
        "serial_number": "serial_number",
        "waas_zone_uuid": "ada52fc6-d481-48d9-82b3-fddb07d5d44f",
        "waas_zone_name": "Terra HQ",
        "est_data_usage": "2000",
        "type": "Scanner",
        "administrative_staff": {
            "id": "46b0a803-39c8-4113-8b29-8ef30438c5bd",
            "first_name": "PM",
            "last_name": "School"
        },
        "status": "Low Battery",
        "last_activity": "2026-02-27 10:52:15",
        "battery_level": 100,
        "metadata": null
    },
    "message": "Device registered successfully"
}
GET Device Status History {{url}}/devices/4e1cee0f-3c30-4d2b-8b99-36880590613b/status-history?from=2026-06-14&to=2026-07-13

Online/offline history for a device over a window (derived by diffing the append-only status log; per-heartbeat sample rows are excluded). Powers the Device Usage timeline + uptime stats.

Path Parameters

  • id (string UUID, required): the device UUID.

Query Parameters

  • from / to (date, optional, YYYY-MM-DD): the window (defaults to the last ~7 days). from is start-of-day, to end-of-day.

Response

data: from, to, uptimepercent, totaloutages, longestoutageseconds, and timeline[] (each {status, source, recorded_at}).

Requires a bearer token (auth:api).

Auth
Bearer token
Sample Response (200 OK)
{
    "status": 200,
    "data": {
        "from": "2026-06-14",
        "to": "2026-07-13",
        "uptime_percent": 98.7,
        "total_outages": 2,
        "longest_outage_seconds": 5400,
        "timeline": [
            { "status": "Online", "source": "heartbeat", "recorded_at": "2026-06-14" },
            { "status": "Offline", "source": "heartbeat", "recorded_at": "2026-06-20" }
        ]
    },
    "message": "Device status history retrieved"
}
GET Device Data Usage {{url}}/devices/4e1cee0f-3c30-4d2b-8b99-36880590613b/usage?from=2026-06-14&to=2026-07-13

Per-day data usage (and average battery) for a device over a window, for the usage chart. Reads the per-heartbeat sample telemetry rows: each day is the SUM of that day's datausedmb (0 when none).

Path Parameters

  • id (string UUID, required): the device UUID.

Query Parameters

  • from / to (date, optional, YYYY-MM-DD): the window (defaults to the last ~7 days).

Response

data: from, to, totalusedmb, and series[] (each {date, usedmb, avgbattery}).

Requires a bearer token (auth:api).

Auth
Bearer token
Sample Response (200 OK)
{
    "status": 200,
    "data": {
        "from": "2026-06-14",
        "to": "2026-07-13",
        "total_used_mb": 128,
        "series": [
            { "date": "2026-06-14", "used_mb": 12, "avg_battery": 86 },
            { "date": "2026-06-15", "used_mb": 0, "avg_battery": 90 }
        ]
    },
    "message": "Device usage retrieved"
}
GET Device Status Logs (Cursor Paginated) {{url}}/devices/4e1cee0f-3c30-4d2b-8b99-36880590613b/status-logs?from=2026-06-14&to=2026-07-13&per_page=15

The scrollable status-change log for a device (status transitions only — per-heartbeat sample rows are excluded), newest first, cursor-paginated. The aggregate uptime/outage numbers live in Device Status History; this is just the raw log feed.

Path Parameters

  • id (string UUID, required): the device UUID.

Query Parameters

  • from / to (date, optional, YYYY-MM-DD): the window.
  • per_page (integer, optional, default 15, max 50).
  • cursor (opaque, optional): pass meta.nextcursor / meta.prevcursor from a previous response to page.

Response

data.data[] (each {status, batterylevel, source, recordedat}) + data.meta (perpage, nextcursor, prev_cursor).

Requires a bearer token (auth:api).

Auth
Bearer token
Sample Response (200 OK)
{
    "status": 200,
    "data": {
        "data": [
            { "status": "Offline", "battery_level": 18, "source": "heartbeat", "recorded_at": "2026-07-12" },
            { "status": "Online", "battery_level": 74, "source": "heartbeat", "recorded_at": "2026-07-11" }
        ],
        "meta": {
            "per_page": 15,
            "next_cursor": "eyJyZWNvcmRlZF9hdCI6...",
            "prev_cursor": null
        }
    },
    "message": "Device status logs retrieved"
}