SimpleGPS API
Read the vehicles on your account and the hours they ran. Built for pulling numbers into your own system instead of typing them into a spreadsheet.
Getting a key
Issue one yourself in Settings → API keys. It is shown once, at creation - we store only a fingerprint, so if it is lost you issue another rather than asking us to read it back. Revoke a key from the same screen and it stops working immediately.
API access is part of the Fleet plan. A key on an account without it answers 403.
Calling it
curl -H "Authorization: Bearer sgps_..." \
https://simple-gps.com/api/v1/devices
Every response is JSON.
Trying it without writing any code
Two ways, both a couple of minutes. Have your key ready - issue it in Settings, API keys.
Hoppscotch, in the browser
Free, nothing to install and no account needed. Open hoppscotch.io and:
- Put
https://simple-gps.com/api/v1/devicesin the address field, replacing the example that is there. - Open the Authorization tab, set the type to Bearer, and paste your key into Token.
- Press Send. You should get the list of your vehicles back.
- Take any
idfrom that response and try the other three - the Authorization tab keeps your key, so you only change the address.
Postman, with the collection
If you would rather have all four requests ready: Download the Postman collection and import it. Paste your key into the api_key variable, then run Devices first - it saves the first vehicle id into a variable so the rest work without you copying anything.
Hoppscotch can import the same file (Import → Postman), but it does not carry the variables across, so you would set those by hand. For a first look the four clicks above are quicker.
moving_seconds and idle_seconds together. They should equal engine_seconds exactly - it is the sum of the two, not a third measurement. Adding all three counts every hour twice, and it is the mistake most likely to reach a report before anyone notices.
Rate limits
| Endpoint | Limit |
|---|---|
/devices | 120 requests per minute |
| Everything else | 30 requests per minute |
Counted per key, so your limit is yours alone. The second tier is lower because those calls read through position history for the window you ask for - listing vehicles is a single indexed lookup and costs almost nothing.
Over the limit answers 429 with a Retry-After header in seconds. Please obey it rather than retrying straight away. A fleet pulling hourly, or once a night, will never come near these numbers - if your integration needs more, tell us what it does and we will raise them.
Knowing where you are
You do not have to count. Every response carries two headers:
X-RateLimit-Limit | How many requests this endpoint allows per minute. It differs by endpoint, so read it rather than assuming. |
X-RateLimit-Remaining | How many you have left in the current minute. |
Retry-After | Seconds to wait. Sent only on a 429. |
X-RateLimit-Reset | Seconds until the counter goes back to full. Sent only on a 429. |
If you are polling on a schedule you will never see these move. They are there for the case where something loops by mistake - read X-RateLimit-Remaining and you will know before you are refused rather than after.
engine_seconds is the sum of the other two, not a third measurement - do not add all three together.
Endpoints
GET /api/v1/devices
Every vehicle on the account. This is your mapping table: our id never changes, so map it once against your own asset id.
{
"data": [
{
"id": 41,
"name": "Forklift 3",
"imei": "860813070448084",
"registration": null,
"model": "Teltonika FTM305",
"status": "active",
"timezone": "America/Chicago",
"last_reported_at": "2026-08-26T14:03:11+00:00"
}
]
}
GET /api/v1/devices/{id}/hours
Totals for a window. Defaults to the last seven days.
| Parameter | Meaning |
|---|---|
from | Date (YYYY-MM-DD). Whole days in the vehicle's zone. Optional. |
to | Same. Optional; defaults to now. |
Windows reaching further back than 365 days are clamped rather than refused, and the window you actually received is echoed back - so a gap is never charted as zeroes.
{
"device_id": 41,
"from": "2026-08-01T05:00:00+00:00",
"to": "2026-08-08T04:59:59+00:00",
"timezone": "America/Chicago",
"engine_seconds": 141120,
"moving_seconds": 98400,
"idle_seconds": 42720
}
GET /api/v1/devices/{id}/hours/daily
The same three numbers per day. This is usually what replaces a spreadsheet.
{
"device_id": 41,
"timezone": "America/Chicago",
"data": [
{ "date": "2026-08-01", "engine_seconds": 21600, "moving_seconds": 15300, "idle_seconds": 6300 }
]
}
GET /api/v1/devices/{id}/meter
The running total since the tracker started reporting - the figure that lines up against the hour meter on the machine's own dash.
When something is wrong
| Status | What it means |
|---|---|
401 | Missing, unknown, revoked or expired key. The message says which. |
403 | The account is not on a plan that includes the API. |
404 | No such vehicle on this account, or no such endpoint. |
429 | Over the rate limit. Wait and retry. |
A vehicle belonging to another account answers 404, not 403 - otherwise the difference between the two would tell you which of our ids exist.
Versioning
The version is in the path. Once a field means something to your nightly job, we will not change what it means - anything new goes somewhere new.
Questions, or an endpoint you need that is not here: [email protected].