Senturo Reporting API Endpoint Reference
Complete parameter, response, and field details for every Reporting API endpoint
Overview
The Senturo Reporting API gives you read-only access to your device fleet data over HTTPS. You can retrieve device inventory, location history, network connection history, device notes, and geofence evaluation results, then feed that data into your own reporting tools, dashboards, or asset management systems.
This article is the complete technical reference for all eleven endpoints. For each one you will find the request path, every supported query parameter, an example request, an example response, and notes on behaviour that is not obvious from the parameter list alone. A full field reference for each data type appears toward the end of the article.
Every endpoint in the Reporting API is read-only. All operations use GET, and no endpoint creates, modifies, or deletes anything in your Senturo account.
New to the Reporting API? Start with Getting Started with the Senturo Reporting API, which covers requesting a token, authenticating, pagination, and rate limits. This article assumes you already have a working ReportToken.
Before You Begin
All requests share the same base URL:
https://api.senturo.com/api/report/v1
Every request requires your ReportToken in the Authorization header:
Authorization: ReportToken your_token_here
Two details cause more failed requests than anything else:
- The trailing slash is required.
/devices/works;/devicesreturns a404with no redirect. - Always include a UTC offset on date values. A timestamp written without an offset may be interpreted in a different timezone than you expect. Every example in this article uses an explicit offset, and we recommend you do the same.
Prefer to explore interactively? The live API specification at https://api.senturo.com/api/report/swagger/ lists every endpoint and includes a Try it out panel you can use with your own token.
How Responses Are Structured
Endpoints that return lists wrap their results in a consistent object:
json{ "count": 1286, "next": "https://api.senturo.com/api/report/v1/devices/?page=2&page_size=100", "previous": null, "record_exists": true, "results": [ ] }
| Field | Type | Description |
|---|---|---|
count |
integer | Total number of records matching your request, across all pages |
next |
string | Absolute URL of the next page, or null on the last page |
previous |
string | Absolute URL of the previous page, or null on the first page |
record_exists |
boolean | false when no records matched your request |
results |
array | The records for the current page |
Endpoints that return a single record respond with the record object directly, without this wrapper.
Pagination
Use page and page_size to move through large result sets, or follow the next URL, which is a complete absolute address you can request as-is.
page_sizedefaults to 20 and is capped at 100. Requesting a larger value returns 100 records.- An invalid
page_sizesuch as0,-1, or a non-numeric value falls back to the default of 20 rather than returning an error. - Requesting a page beyond the end of the result set returns a
404with the messageInvalid page.
Working With Dates
All date parameters accept ISO 8601 values. Include the UTC offset that applies to the data you want:
2026-09-01T00:00:00-04:00
Values are also accepted without an offset, and as a date alone (2026-09-01), but we recommend always supplying the offset so results are unambiguous.
Default Date Ranges
Two endpoints apply a default date range when you do not supply one. This is the most important behaviour to understand before you build anything against this API, because a request without dates returns a valid response containing only part of your data.
| Endpoint | Default range when no dates are supplied |
|---|---|
| Location history | The most recent 30 days |
| Geofence evaluation | The most recent 7 days |
A device that has not reported a location in the last 30 days returns zero location records unless you supply a date filter, even when months of history exist. Supplying any date filter removes the default and gives you access to the device's full history.
On the geofence endpoint, timestamp_start and timestamp_end are honoured only as a pair. Supplying one without the other has no effect, and the 7-day default applies instead.
Why this matters: A request without dates still returns a
200, and itscountlooks correct, so there is nothing to indicate that older data has been left out. If you are reporting on any period longer than the last month, always supply a date filter.
Device Endpoints
List devices
GET /devices/
Returns every device in your organization, with support for filtering.
| Parameter | Type | Description |
|---|---|---|
serial |
string | Filter by serial number. Partial match, case-insensitive |
name |
string | Filter by device name. Partial match, case-insensitive |
platform |
string | Filter by platform. Partial match, case-insensitive. Values: windows, macos, ios, android, chromeos |
device_status |
string | Filter by status. Exact match, lowercase only. Values: monitored, unverified, missing |
postal_code |
string | Filter by the postal or ZIP code of the device's last known location. Partial match |
zip_code |
string | Alias for postal_code |
created_after |
string | Devices enrolled on or after this date |
created_before |
string | Devices enrolled on or before this date |
last_seen_after |
string | Devices that last checked in on or after this date |
last_seen_before |
string | Devices that last checked in on or before this date |
page |
integer | Page number |
page_size |
integer | Records per page. Default 20, maximum 100 |
Example request
curl -H "Authorization: ReportToken your_token_here" "https://api.senturo.com/api/report/v1/devices/?device_status=missing&page_size=100"
Example response
json{ "count": 2, "next": null, "previous": null, "record_exists": true, "results": [ { "serial": "ABC1234XYZ", "name": "LIBRARY-07", "platform": "windows", "device_status": "missing", "assignee_name": "Jane Doe", "assignee_email": "jdoe@example.com", "created_on": "2026-03-01T10:34:34.164748-04:00", "last_seen": "2026-09-08T15:22:17.844800-04:00", "postal_code": "05401-1234", "geofence_status": [ { "name": "Main Campus", "inside": false } ], "last_location": 1053972397, "location_link": "https://www.google.com/maps/search/?api=1&query=44.47,-73.21", "os_version": "10.0.19045.0" } ] }
Notes
device_statusis the only filter that rejects invalid input. A value outside the three allowed options returns a400listing the valid choices, and the values are case-sensitive.platformmatches partially, sowinreturns Windows devices and a single letter may match several platforms.- This endpoint has no default date range. Without filters it returns your entire fleet.
- Query parameters that are not recognised are ignored rather than rejected, so a misspelled filter name returns unfiltered results with a
200.
Retrieve a device
GET /devices/{serial}/
Returns a single device record. The response is the device object itself, without the pagination wrapper.
| Parameter | Type | Description |
|---|---|---|
serial |
string | Serial number of the device. Required, in the path |
Example request
curl -H "Authorization: ReportToken your_token_here" "https://api.senturo.com/api/report/v1/devices/ABC1234XYZ/"
An unknown serial returns a 404.
Location History Endpoints
List location history
GET /devices/{device_serial}/location-history/
Returns a device's recorded locations, newest first.
| Parameter | Type | Description |
|---|---|---|
device_serial |
string | Serial number of the device. Required, in the path |
received_after |
string | Locations recorded on or after this date |
received_before |
string | Locations recorded on or before this date |
city |
string | Filter by city name |
postal_code |
string | Filter by postal or ZIP code |
country_code |
string | Filter by two-letter country code |
page |
integer | Page number |
page_size |
integer | Records per page. Default 20, maximum 100 |
Example request
curl -H "Authorization: ReportToken your_token_here" "https://api.senturo.com/api/report/v1/devices/ABC1234XYZ/location-history/?received_after=2026-08-01T00:00:00-04:00&received_before=2026-09-01T00:00:00-04:00&page_size=100"
Example response
json{ "count": 2691, "next": "https://api.senturo.com/api/report/v1/devices/ABC1234XYZ/location-history/?page=2&page_size=100", "previous": null, "record_exists": true, "results": [ { "id": 1053286381, "hpe": 0.0, "latitude": "44.4759920", "longitude": "-73.2121200", "accuracy": 14.0, "received_on": "2026-09-08T13:52:00.356000-04:00", "created_on": "2026-09-09T00:54:06.495227+07:00", "updated_on": "2026-09-09T00:54:06.495227+07:00", "country_code": "US", "country_name": "United States", "country_flag_emoji": "", "district": "Chittenden County", "city": "Burlington", "street": "Main Street", "house_number": "", "postal_code": "05401", "formatted_address": "Main Street, Burlington, VT 05401, USA", "automation_histories": [] } ] }
Supply a date filter. Without
received_afterorreceived_before, this endpoint returns only the most recent 30 days. A device that has not reported a location in that time returns zero records even when months of history exist.
Notes
- Results are ordered newest first by
received_on. - Address fields are populated on a best-effort basis and are frequently empty. Use
latitudeandlongitudeas the reliable location values, and treat address data as supplementary. - The
city,postal_code, andcountry_codefilters match only records that carry that address data, so they return fewer results than the full history. - The first request for a device with a large history can take up to a minute while the record count is calculated. Subsequent requests are fast. Set your client timeout to at least 60 seconds.
Retrieve a location record
GET /devices/{device_serial}/location-history/{id}/
Returns a single location record as a bare object.
| Parameter | Type | Description |
|---|---|---|
device_serial |
string | Serial number of the device. Required, in the path |
id |
integer | Location record ID. Required, in the path |
The last_location field on a device record holds the ID of that device's most recent location entry, which you can pass here directly.
Network Information Endpoints
List network information
GET /devices/{device_serial}/network-info/
Returns the device's recorded network connections, newest first.
| Parameter | Type | Description |
|---|---|---|
device_serial |
string | Serial number of the device. Required, in the path |
page |
integer | Page number |
page_size |
integer | Records per page. Default 20, maximum 100 |
Example request
curl -H "Authorization: ReportToken your_token_here" "https://api.senturo.com/api/report/v1/devices/ABC1234XYZ/network-info/?page_size=100"
Example response
json{ "count": 447, "next": null, "previous": null, "record_exists": true, "results": [ { "id": 64911331, "received_on": "2026-09-09T00:17:42.688641+07:00", "active_network": "Wifi198", "external_ip": "203.0.113.42" } ] }
Notes
- This endpoint has no filters beyond pagination, and no default date range. It returns the device's full network history.
external_ipmay be an IPv4 or an IPv6 address.
Retrieve a network record
GET /devices/{device_serial}/network-info/{id}/
Returns a single network record as a bare object.
Notes Endpoints
Notes can be retrieved either for a single device or across the whole fleet. Both routes accept the same filters and return the same record shape.
List notes for a device
GET /devices/{device_serial}/notes/
List notes across the fleet
GET /notes/
| Parameter | Type | Description |
|---|---|---|
device_serial |
string | Filter by device serial number |
note_type |
string | Filter by note type. Exact match, case-insensitive. Values: General, Security, Hardware, Compliance, User Request, Assignment |
created_after |
string | Notes created on or after this date |
created_before |
string | Notes created on or before this date |
updated_since |
string | Notes created or edited since this date |
page |
integer | Page number |
page_size |
integer | Records per page. Default 20, maximum 100 |
Example request
curl -H "Authorization: ReportToken your_token_here" "https://api.senturo.com/api/report/v1/notes/?note_type=Security&page_size=100"
Example response
json{ "count": 18, "next": null, "previous": null, "record_exists": true, "results": [ { "id": 833, "device_serial": "ABC1234XYZ", "device_name": "LIBRARY-07", "note_type": "Security", "author_name": "Jane Doe", "author_email": "jdoe@example.com", "created": "2026-05-22T21:19:51.697432+07:00", "edited": null, "pinned": false, "body": "Device reported missing by front office." } ] }
Using the device-specific route? The
device_serialquery parameter is applied in addition to the serial in the path, so supplying a different serial in each returns no results. Use the path serial on its own.
Notes
note_typematches exactly but ignores case, sosecurityandSecurityare equivalent. A value that matches no type returns an empty result set rather than an error.editedisnullfor notes that have never been edited.author_nameandauthor_emailmay be empty.- Note bodies are plain text.
Retrieve a note
GET /notes/{id}/ GET /devices/{device_serial}/notes/{id}/
Both return the same single note object as a bare response. Requesting a note ID under a device it does not belong to returns a 404.
Geofence Evaluation
Evaluate devices against geofences
GET /geofence/devices/
For each device you supply, this endpoint checks every geofence assigned to that device and reports whether a location was found matching the condition you asked about.
| Parameter | Type | Description |
|---|---|---|
options |
string | Required. inside or outside |
serials |
string | Required. Comma-separated device serial numbers, maximum 100 |
timestamp_start |
string | Start of the evaluation window |
timestamp_end |
string | End of the evaluation window |
page |
integer | Page number |
page_size |
integer | Records per page. Default 20, maximum 100 |
Example request
curl -H "Authorization: ReportToken your_token_here" "https://api.senturo.com/api/report/v1/geofence/devices/?options=outside&serials=ABC1234XYZ,DEF5678UVW×tamp_start=2026-09-01T08:00:00-04:00×tamp_end=2026-09-08T16:00:00-04:00"
Example response
json{ "success": 1, "count": 1, "next": null, "previous": null, "record_exists": true, "results": [ { "serial": "ABC1234XYZ", "name": "LIBRARY-07", "platform": "windows", "has_location_data": true, "has_geofences": true, "geofence_evaluations": [ { "geofence": { "name": "Main Campus" }, "location_found": true, "matched_location": { "id": 1047301674, "received_on": "2026-09-01T15:29:19.966000-04:00" } }, { "geofence": { "name": "District Office" }, "location_found": false, "matched_location": null } ] } ], "errors": [ { "serial": "DEF5678UVW", "reason": "Device has no location data in specified timeframe", "error": true } ] }
How to read the result
For each geofence assigned to the device, the endpoint searches the time window in chronological order and returns the earliest location that satisfies your condition.
location_found: truemeans at least one location in the window matched, andmatched_locationis the first one that did.location_found: falsemeans no location in the window matched, andmatched_locationisnull.
With options=outside, a matched_location tells you when the device was first seen outside that geofence during the window. With options=inside, it tells you when it was first seen inside.
Because every assigned geofence is evaluated regardless of which option you choose, a device typically returns some evaluations that matched and some that did not.
Looking for where a device is right now? Read the
geofence_statusfield on the device record instead. This endpoint answers questions about a period of history;geofence_statusanswers questions about the present.
Notes
successis the number of devices evaluated successfully, not a true or false flag.- Devices that could not be evaluated appear in
errorsrather thanresults, and the request still returns a200. Common reasons areDevice has no location data in specified timeframeandDevice not found in organization. timestamp_startandtimestamp_endmust be supplied together. One without the other is ignored and the 7-day default applies.- Windows of any length and any age are supported, provided both timestamps are present.
- Omitting
optionsorserialsreturns a400. More than 100 serials returnsMaximum 100 device serials allowed per request.
Field Reference
Responses may include additional fields beyond those listed below. Build your integration around the fields documented here.
Device
| Field | Type | Description |
|---|---|---|
serial |
string | Device serial number, unique within your organization |
name |
string | Device name as shown in Senturo |
platform |
string | windows, macos, ios, android, or chromeos |
device_status |
string | monitored, unverified, or missing. A device is unverified until it has been activated |
assignee_name |
string | Name of the assigned user, if one is set |
assignee_email |
string | Email of the assigned user, if one is set |
created_on |
string | When the device was enrolled |
last_seen |
string | When the device last checked in |
postal_code |
string | Postal or ZIP code of the last known location |
geofence_status |
array | One object per assigned geofence, each with name and inside. Empty when no geofences are assigned |
last_location |
integer | ID of the device's most recent location record |
location_link |
string | Google Maps link to the last known location |
os_version |
string | Operating system version as reported by the device. Format varies by platform |
Location record
| Field | Type | Description |
|---|---|---|
id |
integer | Unique identifier for this location record |
latitude |
string | Latitude, returned as a string |
longitude |
string | Longitude, returned as a string |
accuracy |
number | Reported accuracy of the position |
received_on |
string | When the location was recorded by the device |
created_on |
string | When the record was stored |
updated_on |
string | When the record was last modified |
country_code |
string | Two-letter country code. May be empty |
country_name |
string | Country name. May be empty |
country_flag_emoji |
string | Flag emoji for the country. May be empty |
district |
string | District or county. May be empty |
city |
string | City. May be empty |
street |
string | Street name. May be empty |
house_number |
string | House number. May be empty |
postal_code |
string | Postal or ZIP code. May be empty |
formatted_address |
string | Full address as a single line. May be empty |
automation_histories |
array | Identifiers of Security Policy Automations associated with this location. Usually empty |
Network record
| Field | Type | Description |
|---|---|---|
id |
integer | Unique identifier for this network record |
received_on |
string | When the connection was recorded |
active_network |
string | The device's active network connection as reported by the device. The format is not guaranteed and should not be parsed |
external_ip |
string | External IP address, IPv4 or IPv6 |
Note
| Field | Type | Description |
|---|---|---|
id |
integer | Unique identifier for this note |
device_serial |
string | Serial number of the device the note belongs to |
device_name |
string | Name of that device |
note_type |
string | General, Security, Hardware, Compliance, User Request, or Assignment |
author_name |
string | Name of the note's author. May be empty |
author_email |
string | Email of the note's author. May be empty |
created |
string | When the note was created |
edited |
string | When the note was last edited, or null if never edited |
pinned |
boolean | Whether the note is pinned |
body |
string | Note content, plain text |
Response Codes
| Code | Meaning | Example response |
|---|---|---|
200 |
Success | |
400 |
Invalid parameter value | {"device_status":["Select a valid choice. secure is not one of the available choices."]} |
401 |
Authentication failed | {"detail":"Invalid token."} |
404 |
Record not found, or page beyond the end of the results | {"detail":"Invalid page."} |
429 |
Rate limit exceeded | {"detail":"Request was throttled. Expected available in 60 seconds."} |
A 429 response includes a Retry-After header telling you how many seconds to wait. The limit is 120 requests per minute per token, applied across all endpoints.
Troubleshooting
A device returns no location history, but Senturo shows location data for it
The location history endpoint returns only the most recent 30 days unless you supply a date filter. Add received_after with the date you want to start from, and the device's full history becomes available.
A geofence request returns results for a shorter period than requested
Check that both timestamp_start and timestamp_end are present. If only one is supplied it is ignored and the default 7-day window applies.
A filter appears to have no effect
Unrecognised query parameters are ignored rather than rejected, so a misspelled parameter name returns unfiltered results with a 200. Check the spelling against the parameter tables above.
Requests return a 404 that should succeed
Confirm the URL ends with a trailing slash. Paths without one return a 404 and are not redirected.
The first request to an endpoint times out
The first location history request for a device with extensive history can take up to a minute while the total record count is calculated. Later requests are fast. Set your client timeout to at least 60 seconds.
Conclusion
The Reporting API gives you structured, read-only access to your entire device fleet through eleven endpoints covering inventory, location, network, notes, and geofence evaluation. With the parameter tables and field reference above you can build reports tailored to how your organization tracks and manages its devices.
For worked examples that combine these endpoints into complete reports, see Senturo Reporting API: Example Reports and Use Cases. If you run into behaviour not covered here, or need a ReportToken issued or regenerated, contact support at support@senturo.com.
FAQs
Q: Can I use the API to change device settings or trigger actions? A: No. The Reporting API is read-only. Every endpoint uses GET, and no endpoint creates, modifies, or deletes anything. Device actions are performed in the Senturo dashboard.
Q: How do I retrieve every device when my fleet is larger than 100 devices? A: Request /devices/?page_size=100 and follow the next URL in each response until it returns null. The next value is a complete URL you can request directly. A fleet of 1,000 devices takes ten requests, well within the rate limit.
Q: Why does a device show a recent last_seen but return no location records? A: Check-in and location reporting are separate. A device can be connected and reporting its status while location services are unavailable or disabled. Also confirm you are supplying a date filter, since location history defaults to the most recent 30 days.
Q: Which timezone should I use in date filters? A: Always include an explicit UTC offset, such as 2026-09-01T00:00:00-04:00. Values without an offset are accepted but may be interpreted differently than you expect, which will silently shift your results.
Q: What is the difference between geofence_status on a device and the geofence evaluation endpoint? A: geofence_status tells you whether the device is inside or outside each of its geofences right now. The geofence evaluation endpoint searches a period of history and tells you when a device was first inside or outside a geofence during that window.
Q: Are the results ordered? A: Location history is returned newest first. Follow the next URL rather than assuming an order for other endpoints.