octowatch-api
Typed Node.js client for OctoWatch DLP Cloud.
Call the Cloud REST API from your own apps, cron jobs, and ETL pipelines—JWT, periods, and user/group filters included.
Product site: octowatchdlp.com/api/ · interactive catalog: app.octowatchdlp.com/api/ · REST host: https://cloud.octowatchdlp.com
Who this is for
| You want… | Use |
|---|---|
| Data in application code (Node/TypeScript) | octowatch-api (this package) |
| An AI assistant reading OctoWatch in Cursor/Claude | octowatch-mcp on PyPI |
| Click-through reports in a browser | Web Console |
Typical jobs: nightly risk export, idle-time reports, keyword hunts across monitoring channels, timesheet pulls into BI.
Why not raw fetch?
- Auth done for you — login, refresh, 401 retry; optional token save/
accessTokenresume - Product-shaped calls —
period=today|last_7_days|…,group_id/user_id, not hand-built JSON trees - DLP + workforce in one client — risks, idle vs timetable anomalies, activity, monitoring search, timesheets, analytics, directory
- Safe defaults for servers — timeouts, limited retries,
fetchAllonly on real list endpoints (hard cap 2000) - Zero runtime dependencies — Node 18+, ESM, TypeScript types shipped
Install
npm install octowatch-api
Requires Node.js 18+ (built-in fetch). ESM only ("type": "module").
Quick start
import { OctoWatchClient } from "octowatch-api";
const client = new OctoWatchClient({
email: process.env.OCTOWATCH_EMAIL!,
password: process.env.OCTOWATCH_PASSWORD!,
});
await client.login();
const risks = await client.listRisks({ period: "last_7_days", limit: 20 });
console.log(risks.TotalRecords, risks.List?.length);
const idle = await client.getIdleSummary({ period: "yesterday" });
const hits = await client.searchMonitoring({
filter_key: "payroll",
period: "last_7_days",
kinds: ["Sites", "Apps", "Mail"],
});
Try the public demo tenant (shared sandbox — not for production):
export OCTOWATCH_EMAIL=demo@octowatchdlp.com
export OCTOWATCH_PASSWORD=demo
What you can read
| Area | Methods (examples) |
|---|---|
| DLP / policy hits | listRisks, summarizeRisksByUser |
| Idle vs formal alerts | getIdleSummary · listAnomalies (different endpoints—don’t mix them up) |
| Activity & attendance | getActivitySummary, getActivityDetail, getTimesheet, getChrono |
| Monitoring / search | listMonitoring, searchMonitoring (keyword fan-out) |
| Online & structure | listOnline, getDayStructure |
| Analytics / dashboard | getAnalytics, getDashboard |
| Directory & account | listDirectory, getUserInfo, getAccountReadonly, listReports |
| Escape hatch | get / post for any Cloud path |
Full method endpoint map: Methods below.packageCoverage() lists this package’s surface locally.
Not included: writes, screenshot/video binaries, Live VNC, billing.
Advanced usage
Token persistence
const client = new OctoWatchClient({
email: process.env.OCTOWATCH_EMAIL!,
password: process.env.OCTOWATCH_PASSWORD!,
onTokens: async ({ accessToken, refreshToken, publicId, expiresAtMs }) => {
// save for the next process start
},
});
// later
const resumed = new OctoWatchClient({
accessToken: saved.accessToken,
refreshToken: saved.refreshToken,
publicId: saved.publicId,
tokenExpiresAtMs: saved.expiresAtMs,
email: process.env.OCTOWATCH_EMAIL, // needed to re-login after expiry
password: process.env.OCTOWATCH_PASSWORD,
});
Pagination, retries, abort
fetchAll works only on page-shaped lists: listRisks, listAnomalies, getTimesheet, getChrono, listMonitoring. Other period methods reject it.
const all = await client.listRisks({
period: "last_30_days",
limit: 100,
fetchAll: true,
maxRecords: 2000,
});
const ac = new AbortController();
await client.getActivitySummary({ period: "today", signal: ac.signal });
Defaults: maxRetries: 2 on HTTP 429 / 5xx / network errors; client timeout 60s. Limit is clamped to 1…500 per page.
Directory cache
const client = new OctoWatchClient({
email: process.env.OCTOWATCH_EMAIL!,
password: process.env.OCTOWATCH_PASSWORD!,
cacheUsersGroups: true, // 5 minutes; or pass TTL in ms
});
await client.listUsersGroups();
await client.listUsersGroups(); // cache hit
await client.listUsersGroups({ refresh: true });
client.invalidateUsersGroupsCache();
Compact payloads (opt-in)
Methods return full Cloud JSON. For logs or previews, wrap with compactPayload (strips blob-like fields, shortens long text, can cap lists). Off by default.
import { compactPayload } from "octowatch-api";
const raw = await client.listMonitoring({ kind: "Keystrokes", period: "today" });
const slim = compactPayload(raw.data, { textMax: 200, listCap: 50 });
Repo examples
npm run build
node examples/etl-risks.mjs
node examples/idle-vs-anomalies.mjs
node examples/keyword-search.mjs payroll
Methods (v1.0)
| Method | Cloud endpoint |
|---|---|
login / refresh / ensureAuth / whoami |
Access/login-jwt, Access/refresh-token |
listUsersGroups / listDirectory |
Edit/GetUsersGroups2 and related directory Gets |
invalidateUsersGroupsCache |
local cache clear |
getUserInfo |
GetUserData2, tooltip, group path, computer |
listRisks |
Risks/Overall2 |
summarizeRisksByUser |
Analytics/Overall (Risks rollup) |
listAnomalies |
Alerts/Overall2 |
getActivitySummary |
Activity/Overall2 |
getActivityDetail |
Activity/ActivityWindow or CategoryWindow |
getProductivitySummary |
Productivity/Overall3 |
getIdleSummary |
Productivity/GetStats |
getDayStructure |
DayStructureList / GetDayStructure |
getTimesheet |
TimeSheet/Overall2 |
getChrono |
Chrono/Overall2 |
listOnline |
Live/Overall2 |
listMonitoring |
Monitoring/{kind} |
searchMonitoring |
Tools → Search fan-out across Monitoring |
getAnalytics |
Analytics/* views |
getDashboard |
Dashboard/Get* widgets |
listReports |
Account/GetReports + Edit/GetProcessingTasks |
listStreamMeta |
Stream meta Gets (no binary download) |
getAccountReadonly |
Account/Edit Get* whitelist |
packageCoverage |
local static method map |
compactPayload |
local helper (opt-in) |
get / post |
escape hatch for any path |
Period: period=today|yesterday|last_7_days|last_30_days, or date_from / date_to (date-only date_to ends at 23:59:59). Filters: group_id → group node, user_id → user AliasID.
Idle vs anomalies: idle duration → getIdleSummary. Formal timetable alerts → listAnomalies. Empty alerts on 24h schedules are normal.
Keyword search: prefer searchMonitoring({ filter_key }) over looping listMonitoring. Risks and idle use their own methods.
Versioning
- 1.x — public method names and option shapes are stable. Breaking changes require a new major.
- Cloud response row fields still use open index signatures where the wire format varies by build; adding known optional fields is non-breaking.
- See CHANGELOG.md.
Security
- Cloud
login-jwtsends the password in the query string (product contract). Do not log full request URLs. - Prefer environment variables for credentials. The demo account is public.
- Demo login often returns
PublicID=-1; refresh is skipped then and the client re-logins when the access token expires (or on HTTP 401).
Links
| Resource | URL |
|---|---|
| Product | https://octowatchdlp.com/ |
| Product docs | https://octowatchdlp.com/docs/ |
| REST API overview | https://octowatchdlp.com/api/ |
| Web Console | https://app.octowatchdlp.com/ |
| In-app API catalog | https://app.octowatchdlp.com/api/ |
| Cloud Help | https://cloud.octowatchdlp.com/Help |
| Source | https://github.com/extralabs/octowatch-api |
| MCP server (Python) | https://pypi.org/project/octowatch-mcp/ |
License
MIT KOLIBRI LLC / OctoWatch DLP