Skip to main content

Recipes

Ready-made building blocks for the things every integration needs — authenticating once, paginating through a list, and streaming a full history. Copy, paste, and wire in your keys.

A tiny API client

Set the two key headers once, then call any path. It unwraps the response envelope and throws on any non-2xx so your own code only ever seesdata.

JavaScript
const BASE = "https://api.huntereld.com";
const headers = {
  "X-API-Provider-Key": process.env.PROVIDER_KEY,
  "X-API-Company-Key": process.env.COMPANY_KEY,
};

// GET a path and unwrap the envelope. Throws on any non-2xx.
async function api(path) {
  const res = await fetch(BASE + path, { headers });
  const body = await res.json();
  if (!res.ok) throw new Error(res.status + " " + (body.description || res.statusText));
  return body; // { description, data, page, total_pages, ... }
}

Fetch every page

Most list endpoints (drivers, vehicles, statuses) are page-based. Loop from page 1 and stop once you reach total_pages. Reuses the api() helper above.

JavaScript
// Walk every page of a list endpoint and collect all records.
async function fetchAll(path, limit = 100) {
  const all = [];
  for (let page = 1; ; page++) {
    const sep = path.includes("?") ? "&" : "?";
    const body = await api(path + sep + "page=" + page + "&limit=" + limit);
    all.push(...body.data);
    if (page >= body.total_pages) break;
  }
  return all;
}

const drivers = await fetchAll("/v2/drivers");

Stream all location history

Vehicle Location History is token-based, not page-based. Pass thenext_page_token from each response until it stops coming back. Yielding keeps memory flat over a six-month range.

JavaScript
// Page through location history with the next_page_token cursor.
async function* locationHistory(vehicleId, startDate, endDate) {
  let token = null;
  do {
    const params = new URLSearchParams({
      start_date: startDate,
      end_date: endDate,
      limit: "1000",
    });
    if (token) params.set("next_page_token", token);
    const body = await api("/v2/vehicle-location-history/" + vehicleId + "?" + params);
    yield* body.data;
    token = body.next_page_token || null;
  } while (token);
}

for await (const ping of locationHistory(vehicleId, "08-20-2026", "08-22-2026")) {
  // ping.lat, ping.lng, ping.timestamp, ...
}

Staying in sync

The API is polling-based. Refresh the latest-statusendpoints on an interval matched to how often the data actually moves — motion data refreshes roughly every 60 seconds, so polling faster just returns the same values. Back off when you get a 429. SeeErrors for the full list.
esc