Guides
Time ranges
Location history and the audit log are event lists. You filter them with a since/until window, and results come back newest first. Screen time and app usage are per-day lists, filtered by UTC dates.
since and until
sinceis the start of the window and is inclusive.untilis the end and is exclusive. Adjacent windows such as[09:00, 10:00)and[10:00, 11:00)never overlap and never leave a gap.- Both are ISO-8601 timestamps with a UTC offset, such as
2026-10-01T00:00:00Zor2026-10-01T05:30:00+05:30. The API rejects dates without a time and times without an offset. - Both must lie between
1970-01-01T00:00:00Zand9999-12-31T23:59:59.999Z. sincemust be earlier thanuntil.- Results are filtered on the time of the event:
recordedAtfor locations andoccurredAtfor audit log entries.
Encode the + in positive offsets
In a query string, + means a space. Send +05:30 as %2B05:30, or use Z (UTC). HTTP libraries encode it for you when you pass parameters separately, for example with params= in Python or URLSearchParams in JavaScript.
curl "https://api-gw.weguard.ai/core/v1/audit-logs?since=2026-10-01T05:30:00%2B05:30&until=2026-10-08T00:00:00Z" \
-H "Authorization: Bearer $WEGUARD_API_KEY"Defaults and limits
If you omit until, it defaults to the current time. If you omit since, it defaults to until minus the endpoint’s default window. A window longer than the maximum span fails with 400 invalid_parameter, so split long periods into several requests. When you leave out until, the maximum span allows 5 minutes of clock tolerance. A since computed as “your now minus the maximum span” is then not rejected if your clock or the request ran slightly behind.
| Endpoint | Default window | Maximum span |
|---|---|---|
GET/ | Last 24 hours | 31 days |
GET/ | Last 7 days | 93 days |
Location history exists only while the device’s policy has location tracking enabled. WeGuard keeps it for about 65 days on Android and 60 days on Apple devices. Windows history doesn’t expire automatically. On Windows, you get only the points recorded since the device’s current enrollment, not points from an earlier enrollment, even one in your own account. On Android, history follows the physical device within your account, so it can include points from an earlier enrollment of the same device, within the retention period.
Newest-first ordering and cursors
Event lists are ordered by event time, newest first. Entries with the same time are ordered by id, descending. Each nextCursor continues further back in time within your window. Paging works as described in Pagination, with one rule to keep in mind: send the same since and until with every page. If you left them out on the first page, leave them out on the later pages too.
You can rely on the defaults while paging. When you omit until, the first page resolves “now” once and every nextCursor carries that value. Later pages then cover the same window instead of one that moves with the clock. For incremental syncs, explicit values are still easier to checkpoint.
Incremental sync
To mirror an event list into your own system, poll in consecutive windows and remember where you stopped:
- Store a high-water mark (the
untilof your last successful run) and use it as the nextsince. - Audit log entries are timestamped when WeGuard records them, so overlapping each window by a few minutes is enough. Location points carry the time the device captured them (
recordedAt) and can arrive hours later, for example after the device was offline. For location history, re-read a longer trailing window that covers the offline gaps you care about, such as the last 24 hours. For both lists, de-duplicate byid. - Save the new high-water mark only after you have processed the whole window.
import os
from datetime import datetime, timedelta, timezone
import requests
BASE_URL = "https://api-gw.weguard.ai/core"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['WEGUARD_API_KEY']}"
def iso(dt):
return dt.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
def fetch_window(since, until):
"""All audit log entries in [since, until), newest first."""
params = {"since": iso(since), "until": iso(until), "limit": 100}
while True:
response = session.get(f"{BASE_URL}/v1/audit-logs", params=params, timeout=30)
response.raise_for_status()
page = response.json()
yield from page["data"]
if not page["hasMore"]:
return
params["cursor"] = page["nextCursor"] # same since/until on every page
# Run every few minutes. Overlap windows slightly and de-duplicate by id.
last_until = load_checkpoint() # your stored high-water mark
until = datetime.now(timezone.utc)
since = last_until - timedelta(minutes=5)
for entry in fetch_window(since, until):
upsert(entry["id"], entry) # idempotent write keyed by id
save_checkpoint(until)const BASE_URL = "https://api-gw.weguard.ai/core";
const headers = { Authorization: `Bearer ${process.env.WEGUARD_API_KEY}` };
/** All audit log entries in [since, until), newest first. */
async function* fetchWindow(since, until) {
const params = new URLSearchParams({
since: since.toISOString(),
until: until.toISOString(),
limit: "100",
});
for (;;) {
const response = await fetch(`${BASE_URL}/v1/audit-logs?${params}`, { headers });
const page = await response.json();
if (!response.ok) throw new Error(`${page.code}: ${page.detail}`);
yield* page.data;
if (!page.hasMore) return;
params.set("cursor", page.nextCursor); // same since/until on every page
}
}
// Run every few minutes. Overlap windows slightly and de-duplicate by id.
const lastUntil = await loadCheckpoint(); // your stored high-water mark
const until = new Date();
const since = new Date(lastUntil.getTime() - 5 * 60_000);
for await (const entry of fetchWindow(since, until)) {
await upsert(entry.id, entry); // idempotent write keyed by id
}
await saveCheckpoint(until);Date ranges on per-day lists
Screen time and app usage return one entry per UTC day. On these per-day lists, since and until are calendar dates, not timestamps:
- Both are dates in the form
YYYY-MM-DD, and both are inclusive. For example,since=2026-10-01&until=2026-10-07covers seven days. - Days are UTC days, from midnight to midnight UTC. WeGuard can’t shift them to your time zone, because the agent splits screen time at midnight UTC on the device.
- If you omit
until, it defaults to today in UTC. If you omitsince, the range covers the endpoint’s default number of days, up to and includinguntil. - A date that is not in the form
YYYY-MM-DDor does not exist, such as2026-02-30, anuntillater than today, asinceafteruntil, and a range longer than the maximum all fail with 400 invalid_parameter. - Entries are ordered by date, newest first. On app usage, which is paginated, the first page fixes today’s date when you omit
until, and everynextCursorcarries it. A crawl that runs past midnight UTC then keeps the same days.
| Endpoint | Default range | Maximum range |
|---|---|---|
GET/ | Last 7 days, today included | 31 days |
GET/ | Last 7 days, today included | 31 days |
Today’s entry is still growing, so it has complete: false. Earlier days can still change too: a device that was offline uploads its data late, and an app session counts on the day it started only once it ends. To keep a copy in sync, re-read a trailing window on every run, such as the last 7 days, and replace the entries you stored for those days. WeGuard keeps about 60 days of usage, so store what you want to keep longer.