API Reference
A simple REST API for accessing your devices and their location data. Authenticate with an API key, hit JSON endpoints, build whatever you need.
Introduction
The ShieldGPS Public API lets you programmatically access devices on your account and their GPS location data. It is organised around REST, accepts and returns application/json, uses standard HTTP verbs and response codes, and authenticates with a single API key per request.
All requests must be made over HTTPS. Calls made over plain HTTP will fail. All timestamps are returned in ISO-8601 format in UTC. JSON keys use camelCase.
Fields marked nullable in the reference tables may be returned as null in JSON responses — usually because the underlying value is not yet known (e.g. a device that has never reported a position). Non-nullable fields are always present and never null.
Authentication
The API authenticates requests using API keys. API access must first be enabled for your account. Then open Settings → API Access in your dashboard to enable a key. This section is only shown when account access is available; contact support if you don't see it. Requests with a valid key return 403 api_access_disabled if API access has been disabled for the account.
Each key grants read access to active devices on your account. A premium subscription is required on each device.
Provide your key in the Authorization header on every request, prefixed with Bearer:
Keys begin with sgps_live_ followed by a long random string. The full key is shown only once at creation time, so store it somewhere safe. If you lose a key, choose Regenerate API key. The old key stops working and the new key is shown once.
curl https://shieldgps.com/api/public/v1/devices \
-H "Authorization: Bearer sgps_live_7Hk9...wQ"
Errors
The API uses conventional HTTP status codes to indicate success or failure. 2xx means success, 4xx means a problem with your request, 5xx means something went wrong on our end.
Errors return a JSON body with a stable machine-readable error code and a human-readable message:
| Status | Meaning |
|---|---|
200 | OK |
400 | Malformed request |
401 | Missing or invalid API key |
403 | API key cannot access this resource |
404 | Resource not found |
422 | Request validation failed |
429 | Rate limit exceeded |
5xx | Server-side error |
{
"error": "device_not_found",
"message": "No device with id 6f7c...c4 for this API key."
}
Rate limits
The API allows up to 60 requests per minute per API key. Exceeding this returns 429 Too Many Requests. Every response includes the following headers so you can track your usage:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests allowed per minute. |
| X-RateLimit-Remaining | Requests remaining in the current window. |
| X-RateLimit-Reset | Unix timestamp when the window resets. |
Pagination
List endpoints are cursor-paginated. Pass limit to control page size and next to fetch the following page using the cursor returned in the previous response.
| Param | Type | Description |
|---|---|---|
| limit | integer optional | Items per page. Default 50, maximum varies per endpoint. |
| next | string optional | Opaque cursor returned as nextCursor on the previous response. |
Every paginated response includes a hasMore boolean and a nextCursor string. Iterate until hasMore is false; on the final page, nextCursor is null.
{
"data": [ /* ... */ ],
"hasMore": true,
"nextCursor": "c3RhcnQ6MTcxMjkxNjAwMA=="
}
Identifiers
All resource IDs in the public API are UUIDs (e.g. 6f7c2c84-2b3d-4e5a-9b1f-1a2b3c4d5ec4). They are stable, opaque strings — do not parse or generate them client-side. Where convenient, the device endpoints also accept an alias of the form imei:<imei> in place of a UUID, so you can address a device by its hardware IMEI directly.
The Device object
Represents a physical GPS device on your account.
| Attribute | Type | Description |
|---|---|---|
| id | string | UUID identifier for the device. |
| imei | string | 15-digit hardware IMEI. |
| name | string | Display name set by the owner (e.g. "Van 3"). Falls back to an auto-generated name based on the model if the owner has not set one. |
| model | string | Hardware model code (e.g. OB22, AT1). |
| state | string | One of new, active, suspended, cancel-pending. |
| isOnline | boolean | True if the device has communicated within the last 30 minutes. Always false for devices that have never been seen. |
| lastSeenAt | timestamp nullable | Most recent communication from the device. null if the device has never been seen. |
| lastMotionAt | timestamp nullable | Most recent motion detected by the device. null if no motion has been recorded, or if the model does not support motion detection. |
| battery | integer nullable | Battery level as a percentage 0–100. null if the device has not reported a battery reading yet, or does not support battery reporting. |
| lastLocation | object nullable | Most recent Location object. null if the device has never reported a position. Does not include the reverse-geocoded address. |
{
"id": "6f7c2c84-2b3d-4e5a-9b1f-1a2b3c4d5ec4",
"imei": "860123456789012",
"name": "Van 3",
"model": "OB22",
"state": "active",
"isOnline": true,
"lastSeenAt": "2026-04-12T10:25:05Z",
"lastMotionAt": "2026-04-12T10:20:00Z",
"battery": 85,
"lastLocation": {
"latitude": 37.7749,
"longitude": -122.4194,
"speed": 45.5,
"heading": 90,
"battery": 85,
"positionAt": "2026-04-12T10:25:00Z"
}
}
List devices
Returns a paginated list of eligible active premium devices on your account in a stable device order. Ineligible devices are omitted before pagination. Direct device and location requests for an ineligible device return 404 device_not_found, including requests using an IMEI alias.
Query parameters
| state | string optional | Filter by device state. Accepts new, active, suspended, cancel-pending; only active can return devices. |
| limit | integer optional | Page size. Default 50, maximum 200. |
| next | string optional | Pagination cursor. |
curl https://shieldgps.com/api/public/v1/devices?state=active \
-H "Authorization: Bearer sgps_live_7Hk9...wQ"
{
"data": [
{
"id": "6f7c2c84-2b3d-4e5a-9b1f-1a2b3c4d5ec4",
"imei": "860123456789012",
"name": "Van 3",
"model": "OB22",
"state": "active",
"isOnline": true,
"lastSeenAt": "2026-04-12T10:25:05Z",
"lastMotionAt": "2026-04-12T10:20:00Z",
"battery": 85,
"lastLocation": { "...": "..." }
}
],
"hasMore": false,
"nextCursor": null
}
Retrieve a device
Fetch a single device by its UUID, or by its IMEI using the imei:<imei> alias.
Path parameters
| id | string required | The device UUID, or imei:<imei>. |
Returns a Device object. Returns 404 with device_not_found if no device on your account matches.
curl https://shieldgps.com/api/public/v1/devices/imei:860123456789012 \
-H "Authorization: Bearer sgps_live_7Hk9...wQ"
The Location object
Represents a single GPS fix reported by a device.
| Attribute | Type | Description |
|---|---|---|
| latitude | number | Decimal degrees, WGS84. |
| longitude | number | Decimal degrees, WGS84. |
| speed | number nullable | Speed in kilometres per hour (kph) at the time of the fix. Always returned in kph regardless of the device or account locale. null if the device did not report a speed. |
| heading | integer nullable | Course in degrees from true north, 0–359. null if heading was not reported (typically when stationary). |
| battery | integer nullable | Battery level 0–100 at the time of the fix. null if the device did not report a battery reading with this position. |
| positionAt | timestamp | When the device recorded the fix. |
| address | object latest only nullable | Reverse-geocoded address. Only returned by the Latest location endpoint, and may be null if the geocoder cannot resolve the coordinates. |
The address object contains formatted, street, city, region, postalCode, and country (ISO-3166 alpha-2). Any field may be null if the geocoder cannot resolve it.
{
"latitude": 37.7749,
"longitude": -122.4194,
"speed": 45.5,
"heading": 90,
"battery": 85,
"positionAt": "2026-04-12T10:25:00Z",
"address": {
"formatted": "1 Market St, San Francisco, CA 94105, USA",
"street": "1 Market St",
"city": "San Francisco",
"region": "CA",
"postalCode": "94105",
"country": "US"
}
}
Latest location
Returns the most recent Location reported by a device, including a reverse-geocoded street address. Use this endpoint when you want a single “where is it now?” answer.
Path parameters
| id | string required | The device UUID, or imei:<imei>. |
Returns a single Location object. Returns 404 with no_location_available if the device has never reported a position.
address field is computed on-demand from the latest coordinates and may add a small amount of latency to this endpoint compared to the historical endpoint.curl https://shieldgps.com/api/public/v1/devices/{id}/locations/latest \
-H "Authorization: Bearer sgps_live_7Hk9...wQ"
{
"latitude": 37.7749,
"longitude": -122.4194,
"speed": 45.5,
"heading": 90,
"battery": 85,
"positionAt": "2026-04-12T10:25:00Z",
"address": {
"formatted": "1 Market St, San Francisco, CA 94105, USA",
"street": "1 Market St",
"city": "San Francisco",
"region": "CA",
"postalCode": "94105",
"country": "US"
}
}
Historical locations
Returns every location reported by a device within a given time range, ordered oldest-first. Use this endpoint to build trip replays, draw routes on a map, or export data for analysis.
Path parameters
| id | string required | The device UUID, or imei:<imei>. |
Query parameters
| start | timestamp required | Inclusive start of the range, ISO-8601 UTC. |
| end | timestamp optional | Exclusive end of the range, ISO-8601 UTC. Defaults to the current time. |
| limit | integer optional | Page size. Default 500, maximum 1000. |
| next | string optional | Pagination cursor returned by the previous response. |
Constraints
- Maximum range per request is 31 days. To pull more, page through using
nextor split into multiple calls. - Locations are retained for 90 days. Requesting a
startolder than this returns422 range_outside_retention. - Reverse-geocoded
addressis not included in this response. Use the Latest location endpoint when you need the address.
curl -G https://shieldgps.com/api/public/v1/devices/{id}/locations \
-H "Authorization: Bearer sgps_live_7Hk9...wQ" \
--data-urlencode "start=2026-04-01T00:00:00Z" \
--data-urlencode "end=2026-04-12T00:00:00Z" \
--data-urlencode "limit=500"
{
"data": [
{
"latitude": 37.7749,
"longitude": -122.4194,
"speed": 45.5,
"heading": 90,
"battery": 85,
"positionAt": "2026-04-01T08:14:32Z"
},
{
"latitude": 37.7751,
"longitude": -122.4189,
"speed": 47.1,
"heading": 92,
"battery": 85,
"positionAt": "2026-04-01T08:14:42Z"
}
],
"hasMore": true,
"nextCursor": "cG9zOjE3MTI5MTYwODI="
}
{
"error": "range_outside_retention",
"message": "start must be within the last 90 days."
}