Skip to content

Drifty API

The Drifty API lets you read your own records over HTTPS, for example to show today’s focus time on your website or to build a weekly report. It is part of Pro, including a trial.

The API reads what your computers have synced to Drifty Cloud. Turn sync on in Settings → Sync on each computer whose records you want to read; a computer with sync off contributes nothing.

  1. Open Settings → Agents, CLI & API and choose New key.
  2. Name it, choose what it can read, and choose when it expires.
  3. Copy the key. Drifty shows it only once and keeps only a fingerprint of it.
Permission What it can read
Summary Focus, neutral and drift time per day, categories, and time by app and site
Activity Each recorded stretch with its app, site and window or page title

Apps and sites you exclude never appear, including records synced before you excluded them. The page address itself is never sent, though a window or page title can contain whatever the page showed.

Each key in the list shows its last characters, what it can read, when it was created and when it expires, and when it was last used. An account can have 10 keys. Delete a key from its ⋯ menu and anything using it stops working at once. Keys are paused while your account has no Pro access and work again when it returns, unless they have expired.

Keep keys on a server, for example in an environment variable. A key written into a web page’s code can be read by anyone who opens the page, so the API does not answer requests made from a browser page.

Send the key as a bearer token. Every endpoint is a GET under https://drifty.so/api/v1 and answers JSON.

Terminal window
curl -H "Authorization: Bearer $DRIFTY_API_KEY" \
"https://drifty.so/api/v1/summary?tz=Asia/Seoul"

Days run from midnight to midnight in the time zone you pass as tz (an IANA name such as Europe/Berlin; the default is UTC). Dates are written YYYY-MM-DD and must fall in 2000–2099.

Endpoint Permission Returns
/me any key (id, name, scopes, createdAt, expiresAt) and rateLimit
/summary?date=&tz= Summary One day (default today): tracked, focus, neutral, drift and unclassified seconds, focus share, time by category, top apps and sites
/days?from=&to=&tz= Summary Daily totals for up to 31 days (default the last 7)
/activity?date=&tz= Activity items in time order, limit up to 500 (default 100); pass nextCursor back as cursor for the next page. from and to ISO times (up to 31 days apart) can replace date.

A summary looks like this:

{
"timeZone": "Asia/Seoul",
"from": "2026-10-25T15:00:00.000Z",
"to": "2026-10-26T15:00:00.000Z",
"date": "2026-10-26",
"trackedSeconds": 27000,
"focusSeconds": 18000,
"neutralSeconds": 5400,
"driftSeconds": 3600,
"unclassifiedSeconds": 0,
"focusShare": 0.6667,
"categories": [{ "category": "workspace", "seconds": 16200 }],
"apps": [{ "name": "Visual Studio Code", "seconds": 12600 }],
"sites": [{ "domain": "github.com", "seconds": 3000 }],
"devices": 2,
"lastActivityAt": "2026-10-26T09:41:00.000Z"
}

Each activity item has id, deviceId, start, end, durationSeconds, app, bundleId, site, windowTitle, pageTitle, category, productivity and platform. Days in /days carry the same totals as a summary without the category, app and site lists.

Time that two computers recorded at once counts once, as in the app. Categories you added yourself appear as custom. The numbers follow the productivity each computer recorded, so they can differ slightly from the app if you changed how a category counts.

Each key can make 60 requests a minute, and all of an account’s keys together 120. Errors look like { "error": { "code": "…", "message": "…" } }.

Status Code Meaning
400 invalid_request A parameter is missing or out of range
401 missing_api_key, invalid_api_key No key, or a key that is wrong, expired or deleted
402 plan_required The account has no Pro access
403 insufficient_scope The key lacks the permission this endpoint needs
404 not_found No such endpoint
405 method_not_allowed Only GET is answered
409 sync_paused The cloud copy is being deleted or was deleted; turn sync on again
422 range_too_large The range holds too many records; ask for fewer days
429 rate_limited Too many requests; wait for Retry-After seconds
500 server_error Something failed on our side; try again

Records reach the API after your computers sync, so the latest minutes can lag a little.