For developers

Trackingen API docs

Read your fleet's positions, vehicle data, drives, trouble codes and reports, and set up its vehicles, drivers, geofences and alert rules, from your own scripts and products. Plain JSON over HTTPS, with a key you make yourself.

On this page

Start here

  1. 1

    Make a key

    In the panel, open Admin, then API keys, and make a key. Pick what it may read, what it may change and when it stops working. Its secret shows once, so keep it somewhere safe.

    Open API keys
  2. 2

    Send it with every request

    Put the key in the Authorization header as a bearer token. Keep it out of web pages and apps that others can open.

    HTTP
    Authorization: Bearer $TRACKINGEN_API_KEY
  3. 3

    Ask your first question

    List your vehicles. Each comes with its id, which the routes about one vehicle take.

    Request · curl
    curl "https://trackingen.com/api/v1/vehicles" \
      -H "Authorization: Bearer $TRACKINGEN_API_KEY"

A key works while your organization has the API package. Ask for it on the Package page.

The whole reference is also an OpenAPI 3.1 document, for your tools to read and to build a client from.Open openapi.json

Answers, pages and refusals

Every answer is a JSON object with the result in data.

200
{ "data": … }

A list comes in pages and ends (keyset pagination): each page has page.next, a cursor you send back unchanged (an opaque cursor) and never build or read, and you ask again with after set to it for the next page. On the last page page.next is null, and the list is done. limit says how many come at most on a page.

200
{
  "data": [ … ],
  "page": { "next": "MDE5OWIwMDAtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAy" }
}

A copy never ends: it gives what was received after its cursor, in the order it was received and once it is a minute old, so a late report is never skipped. page.next is always where to go on from, so send it as after next time, even when the page was empty. page.more says whether to ask again at once: true while more is waiting, false once you are up to date, then ask again a minute or longer later. Without after a copy starts 14 days back. Starting it with from at a moment within the last 14 days counts against nothing; further back, within your kept data, it counts against 5 starts a day for each key or person, both copies together. An item may come more than once (at-least-once delivery), with more in it, so keep each by its deviceId and recordedAt.

200
{
  "data": [ … ],
  "page": { "next": "q8Xr2vKmT0EXAMPLE.Hn4wLp9EXAMPLE", "more": true }
}

A refusal has its HTTP status and an error with a code that stays the same, a message for people and, for some codes, details.

404
{
  "error": {
    "code": "NOT_FOUND",
    "message": "No such vehicle"
  }
}
  • Every moment is in UTC and written in ISO 8601, such as 2026-11-04T08:00:00.000Z.
  • Every route has its limit (rate limiting): a route counts your requests in a window, and a copy counts the items it goes through instead. Past the limit a route answers 429 with Retry-After, the seconds to wait.
  • A route that changes something takes its body as JSON, sent with Content-Type: application/json. A route that makes something answers 201 with what it made, and takes an Idempotency-Key header of 8 to 64 letters, digits, dashes or underscores: when an answer is lost, send the same request with the same key, and for a day you get the first answer back, marked Idempotent-Replayed: true, instead of a second record. The same key with a different body answers IDEMPOTENCY_KEY_REUSED. A change sets the fields it names to what you send, so sending it again changes nothing more, and a removal answers 204, then 404 once the record is gone. Every change counts against its own limit for each key or person.
  • Version 1 keeps its word: an answer may gain fields and a list of values may grow, but nothing is renamed or removed. Skip what you do not know, a field as much as a feed entry of a kind you have not seen.

Routes

Vehicles and positions

Your vehicles, where each one is now, its track over a period, a copy of every position as it arrives, and the trackers it has had.

GET/api/v1/vehicles

Your vehicles

Your vehicles, each with the tracker installed in it, whether that tracker has the vehicle kit, and the hardware your package still needs

Permissions
vehicle:readSee vehicles
Package
Every package
Rate limit
120 requests a minute
Parameters
  • limitqueryinteger

    How many come at most on one page

    1 to 100default 50

  • afterquerystring

    The page.next of the page before, to ask for the next page; send it as it came (an opaque cursor)

Request · curl
curl "https://trackingen.com/api/v1/vehicles" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000001",
      "plate": "34 API 001",
      "label": "Delivery van",
      "vin": "VF1EXAMPLE0000001",
      "status": "active",
      "deviceId": "0199b000-0000-7000-8000-000000000401",
      "kit": true,
      "missingCapabilities": []
    },
    {
      "id": "0199b000-0000-7000-8000-000000000002",
      "plate": "34 API 002",
      "label": null,
      "vin": null,
      "status": "active",
      "deviceId": null,
      "kit": false,
      "missingCapabilities": []
    }
  ],
  "page": {
    "next": null
  }
}
Error codes

PATCH/api/v1/vehicles/{vehicleId}

Label a vehicle

Gives a vehicle a label of your own, or takes it away; the plate, VIN and tracker stay as the platform keeps them. Answers the vehicle as your vehicle list gives it, and the feed tells the change as vehicle-changed.

Permissions
vehicle:labelChange a vehicle's label
vehicle:readSee vehicles
Package
Every package
Rate limit
60 requests a minute
Parameters
  • vehicleIdpathuuidrequired

    The vehicle's id, from your vehicle list

  • labelbodystringrequired

    A name your organization gives the vehicle, plain text; null to take it away

Request · curl
curl -X PATCH "https://trackingen.com/api/v1/vehicles/0199b000-0000-7000-8000-000000000001" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"label":"Cold chain van"}'
Answer · 200
{
  "data": {
    "id": "0199b000-0000-7000-8000-000000000001",
    "plate": "34 API 001",
    "label": "Cold chain van",
    "vin": "VF1EXAMPLE0000001",
    "status": "active",
    "deviceId": "0199b000-0000-7000-8000-000000000401",
    "kit": true,
    "missingCapabilities": []
  }
}
Error codes

GET/api/v1/vehicles/{vehicleId}/installations

A vehicle's trackers over time

Every time a tracker was installed in the vehicle, oldest first, with when it was taken out again; the one still in has no removedAt

Permissions
vehicle:readSee vehicles
Package
Every package
Rate limit
120 requests a minute
Parameters
  • vehicleIdpathuuidrequired

    The vehicle's id, from your vehicle list

  • limitqueryinteger

    How many come at most on one page

    1 to 100default 50

  • afterquerystring

    The page.next of the page before, to ask for the next page; send it as it came (an opaque cursor)

Request · curl
curl "https://trackingen.com/api/v1/vehicles/0199b000-0000-7000-8000-000000000001/installations" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000b01",
      "deviceId": "0199b000-0000-7000-8000-000000000402",
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "installedAt": "2026-09-01T08:00:00.000Z",
      "removedAt": "2026-10-12T09:10:00.000Z"
    },
    {
      "id": "0199b000-0000-7000-8000-000000000b02",
      "deviceId": "0199b000-0000-7000-8000-000000000401",
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "installedAt": "2026-10-12T09:30:00.000Z",
      "removedAt": null
    }
  ],
  "page": {
    "next": null
  }
}
Error codes

GET/api/v1/fleet/positions

Newest positions

The newest position of each vehicle, null until it reports

Permissions
position:readSee positions
Package
Every package
Rate limit
120 requests a minute
Request · curl
curl "https://trackingen.com/api/v1/fleet/positions" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "plate": "34 API 001",
      "label": "Delivery van",
      "position": {
        "recordedAt": "2026-11-04T08:41:12.000Z",
        "latitude": 41.068,
        "longitude": 29.011,
        "accuracyM": 4,
        "speedKmh": 52,
        "headingDeg": 87,
        "moving": true,
        "silentAt": "2026-11-04T08:56:12.000Z",
        "parkedSince": null
      }
    },
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000003",
      "plate": "34 API 003",
      "label": "Service car",
      "position": {
        "recordedAt": "2026-11-04T08:40:30.000Z",
        "latitude": 41.042,
        "longitude": 28.987,
        "accuracyM": 6,
        "speedKmh": 0,
        "headingDeg": null,
        "moving": false,
        "silentAt": "2026-11-04T08:55:30.000Z",
        "parkedSince": "2026-11-04T08:12:40.000Z"
      }
    },
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000002",
      "plate": "34 API 002",
      "label": null,
      "position": null
    }
  ]
}
Error codes

GET/api/v1/vehicles/{vehicleId}/track

A vehicle's track

A vehicle's positions from one moment to another, seven days at most

Permissions
position:readSee positions
Package
Every package
Rate limit
60 requests a minute
Parameters
  • vehicleIdpathuuidrequired

    The vehicle's id, from your vehicle list

  • fromquerydate-timerequired

    The first moment of the period

  • toquerydate-timerequired

    The last moment of the period

Request · curl
curl "https://trackingen.com/api/v1/vehicles/0199b000-0000-7000-8000-000000000001/track?from=2026-11-04T08:00:00.000Z&to=2026-11-04T09:00:00.000Z" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "recordedAt": "2026-11-04T08:41:12.000Z",
      "latitude": 41.068,
      "longitude": 29.011,
      "accuracyM": 4,
      "speedKmh": 52,
      "headingDeg": 87,
      "moving": true
    }
  ]
}
Error codes

GET/api/v1/positions

Copy positions

Every vehicle's positions in the order they were received, from where your last page ended, once they are a minute old

Permissions
position:readSee positions
Package
Every package
Rate limit
120,000 items a minute
Parameters
  • afterquerystring

    The page.next of the page before, to go on where it ended

  • fromquerydate-time

    Start a new copy here instead. Within the last 14 days this counts against nothing; further back, within your kept data, it counts against 5 starts a day for each key or person

  • limitqueryinteger

    How many come at most on one page

    1 to 1000default 1000

Request · curl
curl "https://trackingen.com/api/v1/positions" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "deviceId": "0199b000-0000-7000-8000-000000000401",
      "serial": "EXAMPLE-0001",
      "recordedAt": "2026-11-04T08:41:12.000Z",
      "receivedAt": "2026-11-04T08:41:44.000Z",
      "latitude": 41.068,
      "longitude": 29.011,
      "accuracyM": 4,
      "speedKmh": 52,
      "headingDeg": 87,
      "moving": true
    },
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000002",
      "deviceId": "0199b000-0000-7000-8000-000000000402",
      "serial": "EXAMPLE-0002",
      "recordedAt": "2026-11-04T08:12:30.000Z",
      "receivedAt": "2026-11-04T08:41:45.000Z",
      "latitude": 41.0712,
      "longitude": 29.0146,
      "accuracyM": 6,
      "speedKmh": 0,
      "headingDeg": null,
      "moving": false
    }
  ],
  "page": {
    "next": "q8Xr2vKmT0EXAMPLE.Hn4wLp9EXAMPLE",
    "more": false
  }
}
Error codes

Trackers

The trackers the platform assigned to you, the vehicle each one is in, how each one is doing and what is wrong with it now.

GET/api/v1/devices

Your trackers

The trackers the platform assigned to you, with their serial number and the vehicle each one is in now

Permissions
device:readSee devices
Package
Every package
Rate limit
120 requests a minute
Parameters
  • limitqueryinteger

    How many come at most on one page

    1 to 100default 50

  • afterquerystring

    The page.next of the page before, to ask for the next page; send it as it came (an opaque cursor)

Request · curl
curl "https://trackingen.com/api/v1/devices" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000401",
      "serial": "356938035643809",
      "label": "Van tracker",
      "status": "active",
      "vehicleId": "0199b000-0000-7000-8000-000000000001"
    },
    {
      "id": "0199b000-0000-7000-8000-000000000402",
      "serial": "356938035643817",
      "label": null,
      "status": "active",
      "vehicleId": null
    }
  ],
  "page": {
    "next": null
  }
}
Error codes

GET/api/v1/devices/{deviceId}/health

How a tracker is doing

What the tracker last told about itself: its mobile signal, the vehicle's supply, its satellite position and how long it has been running. Every field is null until it first tells

Permissions
device:readSee devices
Package
Every package
Rate limit
120 requests a minute
Parameters
  • deviceIdpathuuidrequired

    The tracker's id, from your trackers

Request · curl
curl "https://trackingen.com/api/v1/devices/0199b000-0000-7000-8000-000000000401/health" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": {
    "signalDbm": -71,
    "supplyMillivolts": 12600,
    "gnss": "fixed",
    "lastFixAt": "2026-11-04T08:39:40.000Z",
    "uptimeSeconds": 5400,
    "healthReportedAt": "2026-11-04T08:40:00.000Z",
    "lastReportAt": "2026-11-04T08:41:00.000Z"
  }
}
Error codes

GET/api/v1/devices/{deviceId}/health-alerts

A tracker's open health alerts

What is wrong with the tracker now, such as having gone silent, each with since when; empty when nothing is

Permissions
device:readSee devices
Package
Every package
Rate limit
120 requests a minute
Parameters
  • deviceIdpathuuidrequired

    The tracker's id, from your trackers

Request · curl
curl "https://trackingen.com/api/v1/devices/0199b000-0000-7000-8000-000000000401/health-alerts" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000a01",
      "condition": "silent",
      "since": "2026-11-03T18:20:00.000Z",
      "startedAt": "2026-11-04T18:20:00.000Z"
    }
  ]
}
Error codes

Drivers

The people who drive your vehicles, with their phone and licence, for routes. They come with the route planning package.

GET/api/v1/drivers

Your drivers

Your drivers, active and inactive, with their phone and licence

Permissions
driver:readSee drivers
Package
Route planning
Rate limit
120 requests a minute
Parameters
  • limitqueryinteger

    How many come at most on one page

    1 to 100default 50

  • afterquerystring

    The page.next of the page before, to ask for the next page; send it as it came (an opaque cursor)

Request · curl
curl "https://trackingen.com/api/v1/drivers" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000601",
      "name": "Ayşe Yılmaz",
      "phone": "+905321234567",
      "licenseNumber": "B1234567",
      "status": "active",
      "userId": null
    },
    {
      "id": "0199b000-0000-7000-8000-000000000602",
      "name": "Mehmet Demir",
      "phone": null,
      "licenseNumber": null,
      "status": "inactive",
      "userId": "0199b000-0000-7000-8000-000000000901"
    }
  ],
  "page": {
    "next": null
  }
}
Error codes

POST/api/v1/drivers

Add a driver

Adds a driver, active from the start, whom your routes can be given to

Permissions
driver:createAdd drivers
Package
Route planning
Rate limit
60 requests a minute
Parameters
  • Idempotency-Keyheaderstring

    Your own key for this request, 8 to 64 letters, digits, dashes or underscores. Send the same key when you send the request again after a lost answer, and the first answer comes back instead of a second record

  • namebodystringrequired

    The driver's full name, plain text

  • phonebodystring

    A phone number of 7 to 15 digits, with + and the country code in front or without; spaces, brackets, dots and dashes are dropped. null for none

  • licenseNumberbodystring

    The driving licence number, kept in capitals; null for none

  • userIdbodyuuid

    The id of the person's account the driver signs in with to see their routes. Only a signed-in person links or unlinks an account: a key leaves it out, or sends it unchanged, and otherwise gets PERSON_REQUIRED

Request · curl
curl -X POST "https://trackingen.com/api/v1/drivers" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"name":"Ayşe Yılmaz","phone":"+905321234567","licenseNumber":"B1234567"}'
Answer · 201
{
  "data": {
    "id": "0199b000-0000-7000-8000-000000000601",
    "name": "Ayşe Yılmaz",
    "phone": "+905321234567",
    "licenseNumber": "B1234567",
    "status": "active",
    "userId": null
  }
}
Error codes

PATCH/api/v1/drivers/{driverId}

Change a driver

Changes the fields you send and keeps the rest. An inactive driver gets no new routes, and their account no longer sees their routes.

Permissions
driver:updateEdit drivers
driver:readSee drivers
Package
Route planning
Rate limit
60 requests a minute
Parameters
  • driverIdpathuuidrequired

    The driver's id, from your drivers

  • namebodystring

    The driver's full name, plain text

  • phonebodystring

    A phone number of 7 to 15 digits, with + and the country code in front or without; spaces, brackets, dots and dashes are dropped. null for none

  • licenseNumberbodystring

    The driving licence number, kept in capitals; null for none

  • statusbodystring

    active or inactive. Only a signed-in person changes it for a driver linked to an account, since that decides what the account sees: a key gets PERSON_REQUIRED

    activeinactive

  • userIdbodyuuid

    The id of the person's account the driver signs in with to see their routes. Only a signed-in person links or unlinks an account: a key leaves it out, or sends it unchanged, and otherwise gets PERSON_REQUIRED

Request · curl
curl -X PATCH "https://trackingen.com/api/v1/drivers/0199b000-0000-7000-8000-000000000601" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone":"+905339876543","status":"active"}'
Answer · 200
{
  "data": {
    "id": "0199b000-0000-7000-8000-000000000601",
    "name": "Ayşe Yılmaz",
    "phone": "+905339876543",
    "licenseNumber": "B1234567",
    "status": "active",
    "userId": null
  }
}
Error codes

Vehicle data

What your vehicles read, newest and over time, the signals each one gives, and its replaced ECUs.

GET/api/v1/vehicles/{vehicleId}/readings

Newest readings

A vehicle's newest value of each signal its tracker reads

Permissions
vehicle:readSee vehicles
position:readSee positions
Package
Vehicle data
Rate limit
120 requests a minute
Parameters
  • vehicleIdpathuuidrequired

    The vehicle's id, from your vehicle list

  • kindsqueryarray

    The kinds of signal to answer, comma separated. Measures, counters and states always come; add text for values in words.

    measurecounterstatetext

  • signalsqueryarray

    Only these signals, comma separated, 32 at most, each one the vehicle's signals list names. They come whatever their kind.

Request · curl
curl "https://trackingen.com/api/v1/vehicles/0199b000-0000-7000-8000-000000000001/readings" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": {
    "recordedAt": "2026-11-04T08:41:12.000Z",
    "readings": {
      "speed": 52,
      "engine-speed": 1726,
      "coolant-temperature": 88,
      "fuel-level": 63.5
    }
  }
}
Error codes

GET/api/v1/vehicles/{vehicleId}/readings/series

Readings over time

A vehicle's readings from one moment to another in at most 240 buckets, each signal by its kind

Permissions
vehicle:readSee vehicles
position:readSee positions
Package
Vehicle data
Rate limit
120 requests a minute
Parameters
  • vehicleIdpathuuidrequired

    The vehicle's id, from your vehicle list

  • fromquerydate-timerequired

    The first moment of the period

  • toquerydate-timerequired

    The last moment of the period

  • kindsqueryarray

    The kinds of signal to answer, comma separated. Measures, counters and states always come; add text for values in words.

    measurecounterstatetext

  • signalsqueryarray

    Only these signals, comma separated, 32 at most, each one the vehicle's signals list names. They come whatever their kind.

  • bucketSecondsqueryinteger

    How long a bucket is, in seconds: at least as long as the period divided into 240, at most the whole period. Without it the shortest is taken.

    60 to 2678400

Request · curl
curl "https://trackingen.com/api/v1/vehicles/0199b000-0000-7000-8000-000000000001/readings/series?from=2026-11-04T08:00:00.000Z&to=2026-11-04T09:00:00.000Z" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": {
    "from": "2026-11-04T08:00:00.000Z",
    "to": "2026-11-04T09:00:00.000Z",
    "bucketSeconds": 900,
    "quiet": [],
    "series": [
      {
        "signal": "speed",
        "kind": "measure",
        "unit": "km/h",
        "paceSeconds": 20,
        "rare": false,
        "points": [
          {
            "at": "2026-11-04T08:00:00.000Z",
            "low": 0,
            "high": 74,
            "mean": 41.2,
            "last": 52
          }
        ]
      },
      {
        "signal": "odometer",
        "kind": "counter",
        "unit": "km",
        "paceSeconds": 60,
        "rare": false,
        "points": [
          {
            "at": "2026-11-04T08:00:00.000Z",
            "low": 84211.4,
            "high": 84219.8,
            "last": 84219.8
          }
        ]
      },
      {
        "signal": "driver-working-state",
        "kind": "state",
        "paceSeconds": null,
        "rare": true,
        "points": [
          {
            "at": "2026-11-04T08:00:00.000Z",
            "state": "drive"
          }
        ]
      }
    ]
  }
}
Error codes

GET/api/v1/vehicles/{vehicleId}/signals

A vehicle's signals

Each signal a vehicle's tracker reads: its name, its labels in each language, its kind, and the unit and decimals of a number or the states of a state

Permissions
vehicle:readSee vehicles
position:readSee positions
Package
Vehicle data
Rate limit
120 requests a minute
Parameters
  • vehicleIdpathuuidrequired

    The vehicle's id, from your vehicle list

Request · curl
curl "https://trackingen.com/api/v1/vehicles/0199b000-0000-7000-8000-000000000001/signals" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": {
    "signals": [
      {
        "name": "speed",
        "labels": {
          "tr": "Hız",
          "en": "Speed",
          "de": "Geschwindigkeit"
        },
        "base": true,
        "kind": "measure",
        "unit": "km/h",
        "decimals": 0
      },
      {
        "name": "fuel-level",
        "labels": {
          "tr": "Yakıt seviyesi",
          "en": "Fuel level",
          "de": "Tankfüllstand"
        },
        "base": true,
        "kind": "measure",
        "unit": "%",
        "decimals": 1
      },
      {
        "name": "odometer",
        "labels": {
          "tr": "Kilometre",
          "en": "Odometer",
          "de": "Kilometerstand"
        },
        "base": true,
        "kind": "counter",
        "unit": "km",
        "decimals": 1
      },
      {
        "name": "driver-working-state",
        "labels": {
          "tr": "Sürücü çalışma durumu",
          "en": "Driver working state",
          "de": "Arbeitszustand des Fahrers"
        },
        "base": false,
        "kind": "state",
        "states": [
          {
            "name": "rest",
            "labels": {
              "tr": "Dinlenme",
              "en": "Rest",
              "de": "Ruhezeit"
            }
          },
          {
            "name": "available",
            "labels": {
              "tr": "Hazır bekleme",
              "en": "Available",
              "de": "Bereitschaft"
            }
          },
          {
            "name": "work",
            "labels": {
              "tr": "Diğer iş",
              "en": "Other work",
              "de": "Andere Arbeit"
            }
          },
          {
            "name": "drive",
            "labels": {
              "tr": "Sürüş",
              "en": "Driving",
              "de": "Lenkzeit"
            }
          }
        ]
      }
    ]
  }
}
Error codes

GET/api/v1/fleet/readings

The fleet's newest readings

The newest value of the signals you name for every vehicle that reads them, one request for the whole fleet

Permissions
vehicle:readSee vehicles
position:readSee positions
Package
Vehicle data
Rate limit
120 requests a minute
Parameters
  • signalsqueryarrayrequired

    The signals to answer, comma separated, 32 at most, each one that means the same on every vehicle

Request · curl
curl "https://trackingen.com/api/v1/fleet/readings?signals=fuel-level" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "recordedAt": "2026-11-04T08:41:12.000Z",
      "readings": {
        "fuel-level": 61.5
      }
    },
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000002",
      "recordedAt": "2026-11-04T08:40:58.000Z",
      "readings": {
        "fuel-level": 24
      }
    }
  ]
}
Error codes

GET/api/v1/readings

Copy readings

Every vehicle's readings in the order they were received, from where your last page ended, once they are a minute old. Each row a page goes through counts toward the limit, also one left out for holding none of your signals.

Permissions
vehicle:readSee vehicles
position:readSee positions
Package
Vehicle data
Rate limit
120,000 items a minute
Parameters
  • afterquerystring

    The page.next of the page before, to go on where it ended

  • fromquerydate-time

    Start a new copy here instead. Within the last 14 days this counts against nothing; further back, within your kept data, it counts against 5 starts a day for each key or person

  • limitqueryinteger

    How many come at most on one page

    1 to 1000default 1000

  • signalsqueryarray

    Only these signals, comma separated, 32 at most, by the names a vehicle's signals list gives

Request · curl
curl "https://trackingen.com/api/v1/readings" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "deviceId": "0199b000-0000-7000-8000-000000000401",
      "serial": "EXAMPLE-0001",
      "recordedAt": "2026-11-04T08:41:12.000Z",
      "receivedAt": "2026-11-04T08:41:44.000Z",
      "readings": {
        "speed": 52,
        "engine-speed": 1840,
        "fuel-level": 61.5
      }
    },
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000002",
      "deviceId": "0199b000-0000-7000-8000-000000000402",
      "serial": "EXAMPLE-0002",
      "recordedAt": "2026-11-04T08:40:58.000Z",
      "receivedAt": "2026-11-04T08:41:46.000Z",
      "readings": {
        "coolant-temperature": 88,
        "odometer": 84219.8
      }
    }
  ],
  "page": {
    "next": "q8Xr2vKmT0EXAMPLE.Hn4wLp9EXAMPLE",
    "more": false
  }
}
Error codes

GET/api/v1/ecu-replacements

Replaced ECUs

Every ECU whose serial number changed at the same address of the same vehicle, newest first, with the serial number before and after as the ECU gave them, in hexadecimal

Permissions
vehicle:readSee vehicles
position:readSee positions
Package
Vehicle data
Rate limit
120 requests a minute
Parameters
  • limitqueryinteger

    How many come at most on one page

    1 to 100default 50

  • afterquerystring

    The page.next of the page before, to ask for the next page; send it as it came (an opaque cursor)

  • vehicleIdqueryuuid

    Only this vehicle's replaced ECUs, by its id

Request · curl
curl "https://trackingen.com/api/v1/ecu-replacements" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000701",
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "plate": "34 API 001",
      "ecu": {
        "tr": "Motor kontrol ünitesi",
        "en": "Engine control unit",
        "de": "Motorsteuergerät"
      },
      "address": 2016,
      "serialBefore": "3132333435363738",
      "serialAfter": "3132333435363739",
      "foundAt": "2026-11-04T08:12:30.000Z"
    }
  ],
  "page": {
    "next": null
  }
}
Error codes

Fuel

Each vehicle's fuel and AdBlue tanks, and the drops and refuels the platform detects in them. They come with the fuel watch package.

GET/api/v1/vehicles/{vehicleId}/fuel-tanks

A vehicle's fuel tanks

The vehicle's fuel and AdBlue tanks, each with its size where the platform knows it and whether the vehicle gives its level

Permissions
fuel:readSee fuel drops and refuels
Package
Fuel watch
Rate limit
120 requests a minute
Parameters
  • vehicleIdpathuuidrequired

    The vehicle's id, from your vehicle list

Request · curl
curl "https://trackingen.com/api/v1/vehicles/0199b000-0000-7000-8000-000000000001/fuel-tanks" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "tank": "fuel",
      "litres": 80,
      "given": true
    },
    {
      "tank": "def",
      "litres": null,
      "given": false
    }
  ]
}
Error codes

GET/api/v1/fuel-events

Fuel drops and refuels

Each drop and refuel the platform detected in a tank, newest first, with the level before and after and how many litres that is

Permissions
fuel:readSee fuel drops and refuels
Package
Fuel watch
Rate limit
120 requests a minute
Parameters
  • limitqueryinteger

    How many come at most on one page

    1 to 100default 50

  • afterquerystring

    The page.next of the page before, to ask for the next page; send it as it came (an opaque cursor)

  • vehicleIdqueryuuid

    Only this vehicle's drops and refuels, by its id

  • kindquerystring

    Only drops, drop, or only refuels, refuel

    droprefuel

  • tankquerystring

    Only this tank's: fuel, or def for AdBlue

    fueldef

Request · curl
curl "https://trackingen.com/api/v1/fuel-events" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000901",
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "plate": "34 API 001",
      "tank": "fuel",
      "kind": "drop",
      "during": "parked",
      "levelBefore": 62,
      "levelAfter": 48,
      "litres": 11.2,
      "beforeAt": "2026-11-04T01:10:00.000Z",
      "afterAt": "2026-11-04T01:40:00.000Z",
      "detectedAt": "2026-11-04T01:52:00.000Z"
    },
    {
      "id": "0199b000-0000-7000-8000-000000000902",
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "plate": "34 API 001",
      "tank": "fuel",
      "kind": "refuel",
      "during": "standing",
      "levelBefore": 48,
      "levelAfter": 95,
      "litres": 37.6,
      "beforeAt": "2026-11-04T07:05:00.000Z",
      "afterAt": "2026-11-04T07:14:00.000Z",
      "detectedAt": "2026-11-04T07:20:00.000Z"
    }
  ],
  "page": {
    "next": null
  }
}
Error codes

GET/api/v1/fuel-events/{eventId}

One fuel drop or refuel

A drop or refuel as the list gives it, with where the vehicle stood when the level before was read, which a key without position:read does not see

Permissions
fuel:readSee fuel drops and refuels
Package
Fuel watch
Rate limit
120 requests a minute
Parameters
  • eventIdpathuuidrequired

    The drop's or refuel's id, from the list

Request · curl
curl "https://trackingen.com/api/v1/fuel-events/0199b000-0000-7000-8000-000000000901" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": {
    "id": "0199b000-0000-7000-8000-000000000901",
    "vehicleId": "0199b000-0000-7000-8000-000000000001",
    "plate": "34 API 001",
    "tank": "fuel",
    "kind": "drop",
    "during": "parked",
    "levelBefore": 62,
    "levelAfter": 48,
    "litres": 11.2,
    "beforeAt": "2026-11-04T01:10:00.000Z",
    "afterAt": "2026-11-04T01:40:00.000Z",
    "detectedAt": "2026-11-04T01:52:00.000Z",
    "place": {
      "latitude": 41.068,
      "longitude": 29.011
    }
  }
}
Error codes

Drives and reports

Each vehicle's drives with their figures and score, its harsh moves, and your fleet's reports over a period.

GET/api/v1/vehicles/{vehicleId}/drives

A vehicle's drives

A vehicle's drives that started from one moment to another, 32 days at most, with their figures once they are worked out

Permissions
vehicle:readSee vehicles
position:readSee positions
Package
Every package
Rate limit
120 requests a minute
Parameters
  • vehicleIdpathuuidrequired

    The vehicle's id, from your vehicle list

  • fromquerydate-timerequired

    The first moment of the period

  • toquerydate-timerequired

    The last moment of the period

Request · curl
curl "https://trackingen.com/api/v1/vehicles/0199b000-0000-7000-8000-000000000001/drives?from=2026-11-04T08:00:00.000Z&to=2026-11-04T09:00:00.000Z" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000101",
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "startedAt": "2026-11-04T07:58:40.000Z",
      "endedAt": "2026-11-04T08:41:12.000Z",
      "startedBy": "crank",
      "figures": {
        "drivingSeconds": 2350,
        "distance": {
          "km": 31.4,
          "by": "odometer"
        },
        "topSpeedKmh": 96,
        "fuel": {
          "litres": 2.6,
          "by": "counter"
        },
        "idleSeconds": 190,
        "highLoadSeconds": 240,
        "topCoolantC": 91,
        "topOilC": 104,
        "harshAccelerations": 1,
        "harshBrakings": 0
      },
      "score": {
        "value": 81,
        "band": "good",
        "parts": [
          {
            "figure": "harshBrakings",
            "value": 0,
            "points": 0
          },
          {
            "figure": "harshAccelerations",
            "value": 3.18,
            "points": 8
          },
          {
            "figure": "idleShare",
            "value": 0.074,
            "points": 5
          },
          {
            "figure": "highLoadShare",
            "value": 0.094,
            "points": 6
          }
        ]
      }
    }
  ]
}
Error codes

GET/api/v1/reports/fuel-distance

Fuel and distance report

Each vehicle's drives, distance and fuel from one moment to another, a year at most, and their total

Permissions
vehicle:readSee vehicles
Package
Every package
Rate limit
30 requests a minute
Parameters
  • fromquerydate-timerequired

    The first moment of the period

  • toquerydate-timerequired

    The last moment of the period

Request · curl
curl "https://trackingen.com/api/v1/reports/fuel-distance?from=2026-11-04T08:00:00.000Z&to=2026-11-04T09:00:00.000Z" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": {
    "includes": {
      "fuel": true,
      "fuelEvents": true
    },
    "vehicles": [
      {
        "vehicleId": "0199b000-0000-7000-8000-000000000001",
        "plate": "34 API 001",
        "label": "Delivery van",
        "drives": 42,
        "completed": 41,
        "drivingSeconds": 61200,
        "distanceKm": 1284.6,
        "trackKm": 12.3,
        "fuelLitres": 108.2,
        "litresPer100Km": 8.42,
        "fuelEvents": {
          "refuels": 2,
          "refuelLitres": 96.5,
          "drops": 0,
          "dropLitres": null
        }
      }
    ],
    "total": {
      "drives": 42,
      "completed": 41,
      "drivingSeconds": 61200,
      "distanceKm": 1284.6,
      "trackKm": 12.3,
      "fuelLitres": 108.2,
      "litresPer100Km": null,
      "fuelEvents": {
        "refuels": 2,
        "refuelLitres": 96.5,
        "drops": 0,
        "dropLitres": null
      }
    }
  }
}
Error codes

GET/api/v1/reports/driving

Driving style report

How each vehicle was driven from one moment to another, a year at most: idling, high load, harsh moves and top speed

Permissions
vehicle:readSee vehicles
position:readSee positions
Package
Vehicle data
Rate limit
30 requests a minute
Parameters
  • fromquerydate-timerequired

    The first moment of the period

  • toquerydate-timerequired

    The last moment of the period

Request · curl
curl "https://trackingen.com/api/v1/reports/driving?from=2026-11-04T08:00:00.000Z&to=2026-11-04T09:00:00.000Z" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": {
    "vehicles": [
      {
        "vehicleId": "0199b000-0000-7000-8000-000000000001",
        "plate": "34 API 001",
        "label": "Delivery van",
        "drives": 42,
        "completed": 41,
        "drivingSeconds": 61200,
        "distanceKm": 1284.6,
        "idleSeconds": 5400,
        "idleShare": 0.088,
        "highLoadSeconds": 3100,
        "highLoadShare": 0.051,
        "harshAccelerations": {
          "count": 3,
          "per100Km": 0.23
        },
        "harshBrakings": {
          "count": 5,
          "per100Km": 0.39
        },
        "topSpeedKmh": 118,
        "score": {
          "value": 89,
          "band": "very-good",
          "parts": [
            {
              "figure": "harshBrakings",
              "value": 0.39,
              "points": 1
            },
            {
              "figure": "harshAccelerations",
              "value": 0.23,
              "points": 1
            },
            {
              "figure": "idleShare",
              "value": 0.088,
              "points": 6
            },
            {
              "figure": "highLoadShare",
              "value": 0.051,
              "points": 3
            }
          ]
        }
      }
    ],
    "total": {
      "drives": 42,
      "completed": 41,
      "drivingSeconds": 61200,
      "distanceKm": 1284.6,
      "idleSeconds": 5400,
      "idleShare": 0.088,
      "highLoadSeconds": 3100,
      "highLoadShare": 0.051,
      "harshAccelerations": {
        "count": 3,
        "per100Km": null
      },
      "harshBrakings": {
        "count": 5,
        "per100Km": null
      },
      "topSpeedKmh": 118,
      "score": {
        "value": 89,
        "band": "very-good",
        "parts": []
      }
    }
  }
}
Error codes

GET/api/v1/reports/power-take-off

Power take-off report

How long each vehicle's power take-off ran from one moment to another, a year at most

Permissions
vehicle:readSee vehicles
Package
Power take-off
Rate limit
30 requests a minute
Parameters
  • fromquerydate-timerequired

    The first moment of the period

  • toquerydate-timerequired

    The last moment of the period

Request · curl
curl "https://trackingen.com/api/v1/reports/power-take-off?from=2026-11-04T08:00:00.000Z&to=2026-11-04T09:00:00.000Z" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": {
    "vehicles": [
      {
        "vehicleId": "0199b000-0000-7000-8000-000000000001",
        "plate": "34 API 001",
        "label": "Delivery van",
        "drives": 42,
        "completed": 41,
        "drivingSeconds": 61200,
        "distanceKm": 1284.6,
        "powerTakeOffSeconds": 9000,
        "powerTakeOffShare": 0.147
      }
    ],
    "total": {
      "drives": 42,
      "completed": 41,
      "drivingSeconds": 61200,
      "distanceKm": 1284.6,
      "powerTakeOffSeconds": 9000,
      "powerTakeOffShare": 0.147
    }
  }
}
Error codes

GET/api/v1/vehicles/{vehicleId}/harsh-moves

A vehicle's harsh moves

A vehicle's harsh accelerations and brakings from one moment to another, 32 days at most, oldest first: when each was strongest, how strong in m/s², the speed it began and ended at, and where it happened when that is known. Only moves at least as strong as the thresholds that count a drive's harsh moves come.

Permissions
vehicle:readSee vehicles
position:readSee positions
Package
Vehicle data
Rate limit
120 requests a minute
Parameters
  • vehicleIdpathuuidrequired

    The vehicle's id, from your vehicle list

  • fromquerydate-timerequired

    The first moment of the period

  • toquerydate-timerequired

    The last moment of the period

Request · curl
curl "https://trackingen.com/api/v1/vehicles/0199b000-0000-7000-8000-000000000001/harsh-moves?from=2026-11-04T08:00:00.000Z&to=2026-11-04T09:00:00.000Z" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "kind": "acceleration",
      "peakAt": "2026-11-04T08:03:12.000Z",
      "peakMs2": 3.4,
      "fromKmh": 0,
      "toKmh": 41,
      "place": {
        "latitude": 41.0151,
        "longitude": 28.9793
      }
    },
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "kind": "braking",
      "peakAt": "2026-11-04T08:12:31.000Z",
      "peakMs2": 4.6,
      "fromKmh": 87,
      "toKmh": 52,
      "place": null
    }
  ]
}
Error codes

Trouble codes

The trouble codes your vehicles report, with their meaning, and how many are still open on each vehicle.

GET/api/v1/fleet/open-faults

Open faults per vehicle

How many faults are still open on each vehicle, one request for the whole fleet; a vehicle with none is left out

Permissions
fault:readSee vehicle faults
Package
Vehicle faults
Rate limit
120 requests a minute
Request · curl
curl "https://trackingen.com/api/v1/fleet/open-faults" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "open": 2
    },
    {
      "vehicleId": "0199b000-0000-7000-8000-000000000002",
      "open": 1
    }
  ]
}
Error codes

GET/api/v1/vehicle-faults

Trouble codes

Your trouble codes, newest first, each with its meaning and the part of the vehicle that reported it

Permissions
fault:readSee vehicle faults
Package
Vehicle faults
Rate limit
120 requests a minute
Parameters
  • limitqueryinteger

    How many come at most on one page

    1 to 100default 50

  • afterquerystring

    The page.next of the page before, to ask for the next page; send it as it came (an opaque cursor)

  • vehicleIdqueryuuid

    Only this vehicle's trouble codes, by its id

Request · curl
curl "https://trackingen.com/api/v1/vehicle-faults" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000601",
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "plate": "34 API 001",
      "code": "P0301",
      "system": "powertrain",
      "meaning": {
        "tr": "Silindir 1 ateşleme hatası algılandı",
        "en": "Cylinder 1 misfire detected",
        "de": "Zylinder 1 Fehlzündung erkannt"
      },
      "ecu": {
        "tr": "Motor kontrol ünitesi",
        "en": "Engine control unit",
        "de": "Motorsteuergerät"
      },
      "clearable": false,
      "status": "stored",
      "appearedAt": "2026-11-04T08:12:30.000Z",
      "clearedAt": null,
      "clearingRefusal": null,
      "clearingWarning": null
    }
  ],
  "page": {
    "next": null
  }
}
Error codes

Geofences

The places you draw on the map, whose entries and exits are told in the feed, how many you may keep, and each vehicle's stays in them.

GET/api/v1/geofences

Your geofences

Your geofences, each with its shape, what it tells and how many vehicles are inside

Permissions
geofence:readSee geofences; their stays and notices also need See positions
Package
Geofences
Rate limit
120 requests a minute
Parameters
  • limitqueryinteger

    How many come at most on one page

    1 to 100default 50

  • afterquerystring

    The page.next of the page before, to ask for the next page; send it as it came (an opaque cursor)

Request · curl
curl "https://trackingen.com/api/v1/geofences" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000701",
      "name": "Depot",
      "shape": {
        "kind": "circle",
        "center": {
          "latitude": 41.0681,
          "longitude": 29.0109
        },
        "radiusMeters": 250
      },
      "tellEntries": true,
      "tellExits": true,
      "inside": 2,
      "createdAt": "2026-11-02T07:30:00.000Z",
      "shapedAt": "2026-11-02T07:30:00.000Z"
    },
    {
      "id": "0199b000-0000-7000-8000-000000000702",
      "name": "Harbour gate",
      "shape": {
        "kind": "polygon",
        "corners": [
          {
            "latitude": 40.9921,
            "longitude": 29.0241
          },
          {
            "latitude": 40.9934,
            "longitude": 29.0263
          },
          {
            "latitude": 40.9917,
            "longitude": 29.0279
          }
        ]
      },
      "tellEntries": true,
      "tellExits": false,
      "inside": 0,
      "createdAt": "2026-11-03T09:12:00.000Z",
      "shapedAt": "2026-11-04T06:45:00.000Z"
    }
  ],
  "page": {
    "next": null
  }
}
Error codes

POST/api/v1/geofences

Draw a geofence

Draws a geofence; vehicles coming in and going out are judged from then on. Drawing, changing and removing geofences also count together against 60 a minute for your whole organization.

Permissions
geofence:configureDraw and change geofences
Package
Geofences
Rate limit
60 requests a minute
Parameters
  • Idempotency-Keyheaderstring

    Your own key for this request, 8 to 64 letters, digits, dashes or underscores. Send the same key when you send the request again after a lost answer, and the first answer comes back instead of a second record

  • namebodystringrequired

    A name for the geofence, plain text, unique among your geofences whatever the case

  • shapebodyobjectrequired

    A circle, {kind: circle, center, radiusMeters}, or a polygon, {kind: polygon, corners}, each place {latitude, longitude} in degrees. The geofence limits route says how many corners and how large a radius you may draw

  • tellEntriesbodyboolean

    Whether a vehicle coming in is told, to your people as a notification and in the feed as geofence-entered; true when left out of a new geofence

  • tellExitsbodyboolean

    Whether a vehicle going out is told, as a notification and in the feed as geofence-left; true when left out of a new geofence

Request · curl
curl -X POST "https://trackingen.com/api/v1/geofences" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"name":"Depot","shape":{"kind":"circle","center":{"latitude":41.0681,"longitude":29.0109},"radiusMeters":250},"tellExits":true}'
Answer · 201
{
  "data": {
    "id": "0199b000-0000-7000-8000-000000000701",
    "name": "Depot",
    "shape": {
      "kind": "circle",
      "center": {
        "latitude": 41.0681,
        "longitude": 29.0109
      },
      "radiusMeters": 250
    },
    "tellEntries": true,
    "tellExits": true,
    "inside": 0,
    "createdAt": "2026-11-02T07:30:00.000Z",
    "shapedAt": "2026-11-02T07:30:00.000Z"
  }
}
Error codes

GET/api/v1/geofences/{geofenceId}

A geofence

One geofence, as your geofences list gives it

Permissions
geofence:readSee geofences; their stays and notices also need See positions
Package
Geofences
Rate limit
120 requests a minute
Parameters
  • geofenceIdpathuuidrequired

    The geofence's id, from your geofences

Request · curl
curl "https://trackingen.com/api/v1/geofences/0199b000-0000-7000-8000-000000000701" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": {
    "id": "0199b000-0000-7000-8000-000000000701",
    "name": "Depot",
    "shape": {
      "kind": "circle",
      "center": {
        "latitude": 41.0681,
        "longitude": 29.0109
      },
      "radiusMeters": 250
    },
    "tellEntries": true,
    "tellExits": true,
    "inside": 2,
    "createdAt": "2026-11-02T07:30:00.000Z",
    "shapedAt": "2026-11-02T07:30:00.000Z"
  }
}
Error codes

PATCH/api/v1/geofences/{geofenceId}

Change a geofence

Changes the fields you send and keeps the rest. A new shape is judged from the moment it is drawn. Drawing, changing and removing geofences also count together against 60 a minute for your whole organization.

Permissions
geofence:configureDraw and change geofences
geofence:readSee geofences; their stays and notices also need See positions
Package
Geofences
Rate limit
60 requests a minute
Parameters
  • geofenceIdpathuuidrequired

    The geofence's id, from your geofences

  • namebodystring

    A name for the geofence, plain text, unique among your geofences whatever the case

  • shapebodyobject

    A circle, {kind: circle, center, radiusMeters}, or a polygon, {kind: polygon, corners}, each place {latitude, longitude} in degrees. The geofence limits route says how many corners and how large a radius you may draw

  • tellEntriesbodyboolean

    Whether a vehicle coming in is told, to your people as a notification and in the feed as geofence-entered; true when left out of a new geofence

  • tellExitsbodyboolean

    Whether a vehicle going out is told, as a notification and in the feed as geofence-left; true when left out of a new geofence

Request · curl
curl -X PATCH "https://trackingen.com/api/v1/geofences/0199b000-0000-7000-8000-000000000701" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tellExits":false}'
Answer · 200
{
  "data": {
    "id": "0199b000-0000-7000-8000-000000000701",
    "name": "Depot",
    "shape": {
      "kind": "circle",
      "center": {
        "latitude": 41.0681,
        "longitude": 29.0109
      },
      "radiusMeters": 250
    },
    "tellEntries": true,
    "tellExits": false,
    "inside": 2,
    "createdAt": "2026-11-02T07:30:00.000Z",
    "shapedAt": "2026-11-02T07:30:00.000Z"
  }
}
Error codes

DELETE/api/v1/geofences/{geofenceId}

Remove a geofence

Removes a geofence: vehicles inside it are no longer judged, their stays end without being told, and the stays it had keep their history. Drawing, changing and removing geofences also count together against 60 a minute for your whole organization.

Permissions
geofence:configureDraw and change geofences
Package
Geofences
Rate limit
60 requests a minute
Parameters
  • geofenceIdpathuuidrequired

    The geofence's id, from your geofences

Request · curl
curl -X DELETE "https://trackingen.com/api/v1/geofences/0199b000-0000-7000-8000-000000000701" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"

204Done; the answer has no body.

Error codes

GET/api/v1/geofence-limits

Geofence limits

How many geofences you may keep and keep now, the most corners of a polygon and the smallest and largest radius of a circle

Permissions
geofence:readSee geofences; their stays and notices also need See positions
Package
Geofences
Rate limit
120 requests a minute
Request · curl
curl "https://trackingen.com/api/v1/geofence-limits" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": {
    "geofencesMax": 100,
    "geofencesUsed": 2,
    "cornersMax": 50,
    "radiusMinMeters": 50,
    "radiusMaxMeters": 30000
  }
}
Error codes

GET/api/v1/geofence-stays

Stays in geofences

Each time a vehicle was inside a geofence, from when it came in to when it went out, the newest first; a stay still going has no end

Permissions
geofence:readSee geofences; their stays and notices also need See positions
position:readSee positions
Package
Geofences
Rate limit
120 requests a minute
Parameters
  • limitqueryinteger

    How many come at most on one page

    1 to 100default 50

  • afterquerystring

    The page.next of the page before, to ask for the next page; send it as it came (an opaque cursor)

  • vehicleIdqueryuuid

    Only this vehicle's stays, by its id

  • geofenceIdqueryuuid

    Only the stays in this geofence, by its id

  • insidequerystring

    true for only the stays still going

    truefalse

Request · curl
curl "https://trackingen.com/api/v1/geofence-stays" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000302",
      "geofenceId": "0199b000-0000-7000-8000-000000000701",
      "geofence": "Depot",
      "vehicleId": "0199b000-0000-7000-8000-000000000002",
      "plate": "34 API 002",
      "start": "entered",
      "startedAt": "2026-11-04T06:02:10.000Z",
      "end": "left",
      "endedAt": "2026-11-04T08:43:58.000Z"
    },
    {
      "id": "0199b000-0000-7000-8000-000000000303",
      "geofenceId": "0199b000-0000-7000-8000-000000000701",
      "geofence": "Depot",
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "plate": "34 API 001",
      "start": "already-inside",
      "startedAt": "2026-11-02T07:30:00.000Z",
      "end": null,
      "endedAt": null
    }
  ],
  "page": {
    "next": null
  }
}
Error codes

Alerts

The rules that raise an alert when a vehicle's reading passes a threshold, the signals a rule may watch, and the alerts raised.

GET/api/v1/alert-rules

Your alert rules

Your alert rules, on and off, and every signal a rule may watch with the thresholds it takes and whether your package lets a rule watch it now

Permissions
alert:readSee alerts
Package
Every package
Rate limit
120 requests a minute
Request · curl
curl "https://trackingen.com/api/v1/alert-rules" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": {
    "rules": [
      {
        "id": "0199b000-0000-7000-8000-000000000201",
        "name": "Engine running hot",
        "signal": "coolant-temperature",
        "comparison": "above",
        "threshold": 105,
        "unit": "°C",
        "holdSeconds": 60,
        "on": true
      },
      {
        "id": "0199b000-0000-7000-8000-000000000202",
        "name": "Battery running low",
        "signal": "battery-low",
        "comparison": "below",
        "threshold": null,
        "unit": "V",
        "holdSeconds": 300,
        "on": false
      }
    ],
    "signals": [
      {
        "signal": "coolant-temperature",
        "unit": "°C",
        "threshold": {
          "by": "customer",
          "min": 40,
          "max": 130,
          "step": 1
        },
        "usable": true
      },
      {
        "signal": "battery-low",
        "unit": "V",
        "threshold": {
          "by": "platform",
          "comparison": "below"
        },
        "usable": true
      }
    ]
  }
}
Error codes

POST/api/v1/alert-rules

Add an alert rule

Adds a rule, on from the start: a vehicle whose signal stays past the threshold for the hold time raises an alert, told to your people and in the feed as vehicle-alert. Adding and changing alert rules also count together against 100 a day for your whole organization.

Permissions
alert:configureSet alert rules
Package
Every package
Rate limit
60 requests a minute
Parameters
  • Idempotency-Keyheaderstring

    Your own key for this request, 8 to 64 letters, digits, dashes or underscores. Send the same key when you send the request again after a lost answer, and the first answer comes back instead of a second record

  • namebodystringrequired

    A name for the rule, plain text, shown with each alert

  • signalbodystringrequired

    The signal the rule watches: one of the signals the alert rules list names, or battery-low

  • comparisonbodystringrequired

    above or below: on which side of the threshold an alert is

    abovebelow

  • thresholdbodystringrequired

    The value the signal must pass, within its range and in its steps as the alert rules list gives them; null for battery-low, whose threshold the platform sets

  • holdSecondsbodyintegerrequired

    How long, in whole seconds, the signal stays past the threshold before the alert is raised; 0 raises it at once

    0 to 3600

Request · curl
curl -X POST "https://trackingen.com/api/v1/alert-rules" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"name":"Engine running hot","signal":"coolant-temperature","comparison":"above","threshold":105,"holdSeconds":60}'
Answer · 201
{
  "data": {
    "id": "0199b000-0000-7000-8000-000000000201",
    "name": "Engine running hot",
    "signal": "coolant-temperature",
    "comparison": "above",
    "threshold": 105,
    "unit": "°C",
    "holdSeconds": 60,
    "on": true
  }
}
Error codes

PATCH/api/v1/alert-rules/{ruleId}

Change an alert rule

Changes the fields you send and keeps the rest, and turns the rule on or off. Adding and changing alert rules also count together against 100 a day for your whole organization.

Permissions
alert:configureSet alert rules
alert:readSee alerts
Package
Every package
Rate limit
60 requests a minute
Parameters
  • ruleIdpathuuidrequired

    The rule's id, from your alert rules

  • namebodystring

    A name for the rule, plain text, shown with each alert

  • signalbodystring

    The signal the rule watches: one of the signals the alert rules list names, or battery-low

  • comparisonbodystring

    above or below: on which side of the threshold an alert is

    abovebelow

  • thresholdbodystring

    The value the signal must pass, within its range and in its steps as the alert rules list gives them; null for battery-low, whose threshold the platform sets

  • holdSecondsbodyinteger

    How long, in whole seconds, the signal stays past the threshold before the alert is raised; 0 raises it at once

    0 to 3600

  • onbodyboolean

    Whether the rule raises alerts; past the rules that may be on at once, turning one on answers ALERT_RULE_LIMIT

Request · curl
curl -X PATCH "https://trackingen.com/api/v1/alert-rules/0199b000-0000-7000-8000-000000000201" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"threshold":110,"on":true}'
Answer · 200
{
  "data": {
    "id": "0199b000-0000-7000-8000-000000000201",
    "name": "Engine running hot",
    "signal": "coolant-temperature",
    "comparison": "above",
    "threshold": 110,
    "unit": "°C",
    "holdSeconds": 60,
    "on": true
  }
}
Error codes

DELETE/api/v1/alert-rules/{ruleId}

Remove an alert rule

Removes a rule; the alerts it raised stay in the alert history

Permissions
alert:configureSet alert rules
Package
Every package
Rate limit
60 requests a minute
Parameters
  • ruleIdpathuuidrequired

    The rule's id, from your alert rules

Request · curl
curl -X DELETE "https://trackingen.com/api/v1/alert-rules/0199b000-0000-7000-8000-000000000201" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"

204Done; the answer has no body.

Error codes

GET/api/v1/alert-episodes

Alerts raised

Each time a vehicle's reading passed an alert rule's threshold, newest first, with how far it went and for how long, and where it began to a key with position:read

Permissions
alert:readSee alerts
Package
Every package
Rate limit
120 requests a minute
Parameters
  • limitqueryinteger

    How many come at most on one page

    1 to 100default 50

  • afterquerystring

    The page.next of the page before, to ask for the next page; send it as it came (an opaque cursor)

  • vehicleIdqueryuuid

    Only this vehicle's alerts, by its id

Request · curl
curl "https://trackingen.com/api/v1/alert-episodes" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000301",
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "plate": "34 API 001",
      "name": "Engine running hot",
      "signal": "coolant-temperature",
      "comparison": "above",
      "threshold": 105,
      "unit": "°C",
      "peak": 112.5,
      "startedAt": "2026-11-04T08:41:12.000Z",
      "durationSeconds": 95,
      "place": {
        "latitude": 41.068,
        "longitude": 29.011
      }
    }
  ],
  "page": {
    "next": null
  }
}
Error codes

The feed

What happened in your fleet and what changed in your vehicles, devices and package, in one order.

GET/api/v1/feed

The feed

What happened in your fleet, in the order it was written, from where your last page ended, once it is a minute old and for 14 days. Each entry is of a kind and carries what it is about, the way that thing's own list gives it, with a cursor to go on from right after it. Each kind needs its own permission, and without position:read an entry's place is left out. Without the vehicle data package a drive comes with its time driving and distance only, as the vehicle's drives list gives it. More kinds may come in time, so skip an entry of a kind you do not know and go on after its cursor.

Permissions
alert:readSee alerts
device:readSee devices
fault:readSee vehicle faults
fuel:readSee fuel drops and refuels
geofence:readSee geofences; their stays and notices also need See positions
package:readSee the package and its price
position:readSee positions
vehicle:readSee vehicles
Package
Every package
Rate limit
120,000 items a minute
Kinds

What happened in your fleet

  • vehicle-silentvehicle:read
  • vehicle-heard-againvehicle:read
  • vehicle-faultsfault:readVehicle faults
  • vehicle-alertalert:read
  • geofence-enteredgeofence:readposition:readGeofences
  • geofence-leftgeofence:readposition:readGeofences
  • fuel-dropfuel:readFuel watch
  • refuelfuel:readFuel watch
  • health-alertdevice:readvehicle:read
  • health-alert-endeddevice:readvehicle:read
  • drive-completedvehicle:readposition:read
  • ecu-replacedvehicle:readposition:readVehicle data

What changed in your vehicles, devices and package

  • vehicle-addedvehicle:read
  • vehicle-changedvehicle:read
  • device-assigneddevice:read
  • device-installeddevice:readvehicle:read
  • device-removeddevice:readvehicle:read
  • feature-switchedpackage:read
  • retention-changedpackage:read
  • retention-appliedpackage:read
Parameters
  • afterquerystring

    The page.next of the page before, to go on where it ended

  • fromquerydate-time

    Start here instead, at most 14 days back

  • limitqueryinteger

    How many come at most on one page

    1 to 1000default 1000

  • kindsqueryarray

    Only entries of these kinds, comma separated. Without it every kind you may read comes; a kind you may not read is refused.

    vehicle-silentvehicle-heard-againvehicle-faultsvehicle-alertgeofence-enteredgeofence-leftfuel-droprefuelhealth-alerthealth-alert-endeddrive-completedecu-replacedvehicle-addedvehicle-changeddevice-assigneddevice-installeddevice-removedfeature-switchedretention-changedretention-applied

  • waitSecondsqueryinteger

    When nothing is ready, wait up to this many seconds for the next entry; the platform may wait less. 0 answers at once.

    0 to 30default 0

Request · curl
curl "https://trackingen.com/api/v1/feed" \
  -H "Authorization: Bearer $TRACKINGEN_API_KEY"
Answer · 200
{
  "data": [
    {
      "id": "0199b000-0000-7000-8000-000000000801",
      "kind": "vehicle-alert",
      "cursor": "Wm3kQ9vXEXAMPLE.Pz7cR2EXAMPLE",
      "customerId": "0199b000-0000-7000-8000-000000000501",
      "vehicleId": "0199b000-0000-7000-8000-000000000001",
      "writtenAt": "2026-11-04T08:43:05.000Z",
      "subject": {
        "id": "0199b000-0000-7000-8000-000000000301",
        "vehicleId": "0199b000-0000-7000-8000-000000000001",
        "plate": "34 API 001",
        "name": "Engine running hot",
        "signal": "coolant-temperature",
        "comparison": "above",
        "threshold": 105,
        "unit": "°C",
        "peak": 112.5,
        "startedAt": "2026-11-04T08:41:12.000Z",
        "durationSeconds": 95,
        "place": {
          "latitude": 41.068,
          "longitude": 29.011
        }
      }
    },
    {
      "id": "0199b000-0000-7000-8000-000000000802",
      "kind": "geofence-left",
      "cursor": "Hn4wLp9vEXAMPLE.Qe8tY1EXAMPLE",
      "customerId": "0199b000-0000-7000-8000-000000000501",
      "vehicleId": "0199b000-0000-7000-8000-000000000002",
      "writtenAt": "2026-11-04T08:44:30.000Z",
      "subject": {
        "id": "0199b000-0000-7000-8000-000000000302",
        "geofenceId": "0199b000-0000-7000-8000-000000000701",
        "geofence": "Depot",
        "vehicleId": "0199b000-0000-7000-8000-000000000002",
        "plate": "34 API 002",
        "start": "entered",
        "startedAt": "2026-11-04T06:02:10.000Z",
        "end": "left",
        "endedAt": "2026-11-04T08:43:58.000Z"
      }
    }
  ],
  "page": {
    "next": "q8Xr2vKmT0EXAMPLE.Hn4wLp9EXAMPLE",
    "more": false
  }
}
Error codes

Webhooks

A webhook sends the feed's entries to your own https endpoint as they settle, so your system hears of an alert, a geofence crossed or a drive completed without asking. It is the feed pushed: the same entries, in the same order, with the same cursors.

  • A person registers a webhook in the panel, under Admin, then Webhooks, with their password; an API key never does, and everyone who manages your team hears of a new one. Pick the kinds it is sent, and whether it sees places. A webhook answers to one person, who registered it or last checked it, and never holds more than that person may read: each delivery checks again what that person may read now, that your organization has the API package and that the webhook may read the entry's kind, so a feature switched off stops its kinds. When that person leaves, or may no longer manage API keys, the webhook pauses and the people who manage your API keys are told. It is never checked again, since its endpoint still holds the secret that person saw: remove it and register a new one, which brings a new secret. A check by anyone else, of a webhook paused only for its failures, makes them its person. Without places, an alert's place is null, as the feed gives it without position:read. The signing secret, which begins whsec_, shows once; we keep it sealed.
  • The endpoint is https on port 443 under a public host name. We resolve the name, refuse it if any address it gives is private, loopback, link-local, shared or otherwise not public, in IPv4 or any IPv6 form, then connect to that very address and check its certificate against the name.

Before anything is sent, check the endpoint in the panel. We send it a signed challenge, and it answers 2xx with JSON whose answer is the challenge's HMAC-SHA256 in base64, keyed with the secret as a signature is, which proves it holds the secret. A webhook that has not passed its check is sent nothing; a paused one goes on where it stopped once it passes again.

Challenge
POST /your/path HTTP/1.1
Host: hooks.example.com
Content-Type: application/json
webhook-id: 0199b000-0000-7000-8000-000000000990
webhook-timestamp: 1762245785
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDNEXAMPLE=

{"challenge":"q8XbT0hZx2vYmR4cEXAMPLE"}
Your answer
HTTP/1.1 200 OK
Content-Type: application/json

{"answer":"kOcc0/V1k6uRAwpp/m/bzF5VAhPZm7t/QXJRO0qG5ZY="}

Each delivery is one POST with one feed entry as its JSON body, exactly as GET /api/v1/feed lists it, with its cursor. Entries go in the feed's order, one at a time per webhook, at least a minute after they happened, and an entry is sent again until your endpoint takes it (at-least-once delivery), so keep each by its id. webhook-id is the entry's id. Skip a kind you do not know.

Delivery
POST /your/path HTTP/1.1
Host: hooks.example.com
Content-Type: application/json
webhook-id: 0199b000-0000-7000-8000-000000000801
webhook-timestamp: 1762245785
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDNEXAMPLE=

{
  "id": "0199b000-0000-7000-8000-000000000801",
  "kind": "vehicle-alert",
  "cursor": "Wm3kQ9vXEXAMPLE.Pz7cR2EXAMPLE",
  "customerId": "0199b000-0000-7000-8000-000000000501",
  "vehicleId": "0199b000-0000-7000-8000-000000000001",
  "writtenAt": "2026-11-04T08:43:05.000Z",
  "subject": {
    "id": "0199b000-0000-7000-8000-000000000301",
    "vehicleId": "0199b000-0000-7000-8000-000000000001",
    "plate": "34 API 001",
    "name": "Engine running hot",
    "signal": "coolant-temperature",
    "comparison": "above",
    "threshold": 105,
    "unit": "°C",
    "peak": 112.5,
    "startedAt": "2026-11-04T08:41:12.000Z",
    "durationSeconds": 95,
    "place": {
      "latitude": 41.068,
      "longitude": 29.011
    }
  }
}

Every delivery and challenge is signed with the webhook's own secret, following the Standard Webhooks headers, so their libraries check it too. The signed content is webhook-id, a dot, webhook-timestamp, a dot and the raw body. Its HMAC-SHA256, keyed with the base64-decoded secret after whsec_, is base64 in webhook-signature after v1, and the header may hold several, separated by spaces. Compare in constant time, on the body as it arrived, before parsing it.

webhook-timestamp is when we sent it, in seconds since 1970 UTC. Refuse a delivery whose timestamp is more than 300 seconds from your clock, and keep the webhook-id values you took within that window to refuse a replay.

Checking a delivery · JavaScript
import { createHmac, timingSafeEqual } from "node:crypto";

function keyOf(secret) {
  return Buffer.from(secret.slice("whsec_".length), "base64");
}

export function challengeAnswer(secret, challenge) {
  return createHmac("sha256", keyOf(secret)).update(challenge).digest("base64");
}

export function isFromTrackingen(secret, headers, rawBody) {
  const sentAt = Number(headers["webhook-timestamp"]);
  if (!(Math.abs(Date.now() / 1000 - sentAt) <= 300)) {
    return false;
  }
  const signed = `${headers["webhook-id"]}.${headers["webhook-timestamp"]}.${rawBody}`;
  const expected = Buffer.from(
    createHmac("sha256", keyOf(secret)).update(signed).digest("base64"),
  );
  return headers["webhook-signature"].split(" ").some((each) => {
    const given = Buffer.from(each.slice("v1,".length));
    return (
      each.startsWith("v1,") &&
      given.length === expected.length &&
      timingSafeEqual(given, expected)
    );
  });
}
Checking a delivery · Python
import base64, hashlib, hmac, time

def mac_of(secret: str, content: bytes) -> str:
    key = base64.b64decode(secret.removeprefix("whsec_"))
    return base64.b64encode(hmac.new(key, content, hashlib.sha256).digest()).decode()

def challenge_answer(secret: str, challenge: str) -> str:
    return mac_of(secret, challenge.encode())

def is_from_trackingen(secret: str, headers: dict, raw_body: bytes) -> bool:
    sent_at = int(headers["webhook-timestamp"])
    if abs(time.time() - sent_at) > 300:
        return False
    signed = f'{headers["webhook-id"]}.{headers["webhook-timestamp"]}.'.encode() + raw_body
    expected = mac_of(secret, signed)
    return any(
        hmac.compare_digest(each.removeprefix("v1,"), expected)
        for each in headers["webhook-signature"].split(" ")
        if each.startswith("v1,")
    )
  • Answer 2xx within 10 seconds, and do the work after answering. Any other answer, a redirect, a timeout, a refused connection or a certificate that does not match the endpoint's name counts as a failure. We never follow a redirect, and we do not keep or read your answer's body beyond a few bytes.
  • A failed entry is sent again 30 seconds later, then after twice as long each time, at most every 60 minutes, and nothing after it is sent before it (backoff). After 30 failures in a row, about a day, the webhook pauses and the people who manage your API keys are told. We keep only how each failure went and when, never a body.
  • Nothing is lost while a webhook fails or is paused: read GET /api/v1/feed with after set to the last cursor you took, with the same kinds, and go on from there. The feed keeps 14 days.
  • A webhook gets at most 60 deliveries a minute, and all of an organization's webhooks together 120; what waits is sent next. An organization keeps up to 5 webhooks.

Error codes

A refusal names one of these codes. Build on the code: it stays the same, while the message may be worded better.

  • INVALID_REQUEST400A path, query or body value is missing or malformed. Only a route that takes a body answers 413, for a body too large, or 415, for one of the wrong type
  • UNAUTHENTICATED401No valid bearer token, session or live API key came with the request
  • FEATURE_DISABLED403The customer's package does not include the feature this needs, or an API key's organization does not hold the API package
  • FORBIDDEN403The caller lacks a permission this needs, or the request came from another site
  • KEY_NOT_ALLOWED403An API key reaches only the key routes, and this route and method is not one
  • PASSWORD_CHANGE_REQUIRED403A signed-in person must change their password before anything else. Only a person's session gets this; an API key never does, since a key has no password
  • PERSON_REQUIRED403Only a signed-in person does this, such as an action that asks for a password; an API key never does
  • NOT_FOUND404Nothing in the caller's reach has this id
  • METHOD_NOT_ALLOWED405The path does not take this method; the Allow header names those it takes
  • ALERT_RULE_LIMIT409As many alert rules as may be on at once are on
  • CONFLICT409The request conflicts with the present state
  • GEOFENCE_LIMIT409The customer keeps as many geofences as it may
  • GEOFENCE_NAME_TAKEN409Another geofence has this name
  • IDEMPOTENCY_KEY_REUSED409This idempotency key was used before for a different request
  • CURSOR_EXPIRED410The cursor is too old to go on from; start the copy again, with from to reach further back
  • RATE_LIMITED429Too many requests; the Retry-After header says when to try again
  • INTERNAL_ERROR500Something went wrong on our side