Most GPS tracking starts with an obstacle course: create an account, pick a plan, download an SDK, register a device, wait for approval. You wanted to see a dot move on a map.
This is the short version. Two HTTP requests and you have live tracking — one to get a session, one per point. No account, no key ceremony, no client library.
Get a session
A session is an identity to push points into, and a public id to read them back from. Ask for one:
curl -s -X POST https://gpstrack.dev/api/session
{
"sessionId": "s_7f3a91c4",
"token": "tk_9d41b0e6a7c2f5",
"createdAt": 1781740800000,
"expiresAt": 1784332800000,
"retention": "ephemeral: relayed in-memory only, never stored on the server"
}
Two values matter, and the difference between them is the whole security model:
tokenis the write secret. Anything holding it can push points as you. It goes on the device and nowhere else.sessionIdis the public read id. It is what appears in a dashboard URL, and it cannot be used to write.
Push a point
curl "https://gpstrack.dev/api/ingest?token=tk_9d41b0e6a7c2f5&lat=6.9271&lng=79.8612"
{ "ok": true, "seq": 1, "expiresAt": 1784332800000 }
That is the entire ingest API. Open https://gpstrack.dev/app?view=live in a
browser, and the point is on the map.
seq is the sequence number the relay assigned. The dashboard polls for
everything after the last seq it saw, which is why you never get a duplicate
and never need to send a timestamp to keep order straight.
The fields it understands
Only lat and lng are required. Everything else is optional, and anything the
device does not know it should simply omit.
| Parameter | Aliases | Meaning |
|---|---|---|
lat |
latitude |
Degrees, required |
lng |
lon, longitude |
Degrees, required |
ts |
timestamp |
Epoch ms. Defaults to arrival time |
speed |
speedKph |
Km/h |
heading |
— | Degrees, 0 = north |
altitude |
alt |
Metres |
sats |
satellites |
Satellites in the fix |
battery |
batteryLevel |
Percent |
label |
— | A name for this tracker |
The aliases exist because devices disagree. A GPS module that emits latitude
and a phone script that emits lat should not need a translation layer between
them, so the relay accepts both and normalises on the way in.
Anything not in that table becomes a custom channel rather than being
discarded — &rpm=900&fuel=42.5 will show up as its own readout. That has an
article of its own.
POST works too
Query strings are convenient from a shell and awkward from a device that already speaks JSON. Both are the same endpoint:
curl -X POST https://gpstrack.dev/api/ingest \
-H "Content-Type: application/json" \
-H "X-API-Key: tk_9d41b0e6a7c2f5" \
-d '{"lat":6.9271,"lng":79.8612,"speed":42,"heading":118}'
The token can travel three ways: ?token=, an X-API-Key header, or
Authorization: Bearer. Prefer a header over the query string wherever you have
the choice — query strings end up in proxy logs and browser history in a way
headers do not.
A tracker in five lines of shell
Nothing above needs a device. Here is a complete tracker that walks a point east along a line, which is enough to watch the map behave before real hardware exists:
TOKEN=tk_9d41b0e6a7c2f5
LAT=6.9271
LNG=79.8612
while true; do
LNG=$(awk "BEGIN{print $LNG + 0.0004}")
curl -s "https://gpstrack.dev/api/ingest?token=$TOKEN&lat=$LAT&lng=$LNG&speed=36" > /dev/null
sleep 2
done
If you have a real GPS receiver on the machine, the same loop with gpspipe
feeding it is a working tracker — that is the Raspberry Pi
article.
The limits, stated plainly
One point per second per session, with a burst allowance of five. Go over it
and you get a 429 with a Retry-After header rather than a silent drop:
{ "ok": false, "error": "rate limit: 1 point/sec per session (burst 5)" }
Rejecting rather than dropping is deliberate. A device that is over the limit can see why; points that vanish silently are undebuggable from the outside.
A thousand points per session, in memory. This is a relay, not a database. The buffer is a ring: point 1001 pushes point 1 out. At one point every two seconds that is a little over half an hour of history, which is the right size for live tracking and the wrong size for a trip log. Export to CSV or GPX as you go if you need to keep it.
Nothing on disk. The points are relayed through memory and never written to server storage. The session identity — the id and the token — is durable for 30 days from last use, so a device can keep pushing to the same session across reboots.
When this is the wrong tool
If you want a phone to record itself — a run, a ride, a walk — none of the above applies. There is no server round trip to make, and Track Me records to the phone's own storage instead. This article is for the case where the thing being tracked is not the thing displaying the map.
If you want durable history with queries over it, this is a relay and you want a database behind it. Pull points out with the read API and keep them yourself:
curl "https://gpstrack.dev/api/session/s_7f3a91c4/points?since=0"
Where to go next
- Stream GPS from an ESP32 over MQTT — when the device is a microcontroller and HTTP per point is too expensive
- Send custom telemetry alongside GPS — rpm, fuel, temperature, anything
- HTTP or MQTT for GPS tracking? — which one your device actually wants