Example: Google Sheets

A Google Apps Script that keeps a People sheet filled from the API.

Switched on per organisationThis is built and working, and is switched on for each organisation on request. Ask your account manager, or reply to any email from us naming it.

Put the credentials in the script's Project Settings, Script Properties as ATG_CLIENT_ID and ATG_CLIENT_SECRET, add a sheet called People, then paste this into the script editor.

const BASE = "https://api.alltoogether.com";

function atgToken_() {
  const cache = CacheService.getScriptCache();
  const cached = cache.get("atg_token");
  if (cached) return cached;
  const props = PropertiesService.getScriptProperties();
  const basic = Utilities.base64Encode(props.getProperty("ATG_CLIENT_ID") + ":" + props.getProperty("ATG_CLIENT_SECRET"));
  const res = UrlFetchApp.fetch(BASE + "/v1/oauth/token", {
    method: "post",
    headers: { Authorization: "Basic " + basic },
    payload: { grant_type: "client_credentials" },
  });
  const token = JSON.parse(res.getContentText()).access_token;
  cache.put("atg_token", token, 3300); // a little under the hour
  return token;
}

// For the paged endpoints: /v1/employees, /v1/leave-requests, /v1/leave-balances.
function atgGetAll_(path) {
  const rows = [];
  let cursor = null;
  do {
    const url = BASE + path + (path.includes("?") ? "&" : "?") + "limit=500" + (cursor ? "&cursor=" + cursor : "");
    const body = JSON.parse(UrlFetchApp.fetch(url, { headers: { Authorization: "Bearer " + atgToken_() } }).getContentText());
    rows.push(...body.data);
    cursor = body.has_more ? body.next_cursor : null;
  } while (cursor);
  return rows;
}

function refreshPeople() {
  const people = atgGetAll_("/v1/employees");
  const sheet = SpreadsheetApp.getActive().getSheetByName("People");
  sheet.clearContents();
  sheet.appendRow(["Name", "Job title", "Status", "Start date", "Leaving date"]);
  people.forEach((p) => sheet.appendRow([p.preferred_name || p.first_name + " " + p.last_name, p.job_title, p.status, p.start_date, p.leaving_date]));
}

Run refreshPeople once to check it, then set it on a time-driven trigger. Hourly or daily is plenty.