| POST | /v1/agents (also parent_agent_id, kind, policy) | register an agent: { agent_id, name, operator_vendor?, issuer?, scopes? } |
| GET | /v1/agents | your registered agents |
| POST | /v1/footprint | a Scout inventory → vendors resolved against the registry, unmatched hints queued, stored, ledger-entered. |
| GET | /v1/footprint | latest report per device; vendors seen across devices with stance, how they were seen (tool, MCP, key), and whether they are watched |
| GET | /v1/org/landscape | watched ∪ seen vendors and concentration over what is underneath them |
| GET | /v1/checks?limit=100 | your check log |
| GET | /v1/dataflow?days=90 | data classes → counterparties summary (the Article 30 view) |
| GET | /v1/api-keys | list the org's keys: name, prefix, created, last used, revoked |
| POST | /v1/api-keys | mint another key (shown once). A signed-in owner only: an API key or a device token is refused (owner) |
| POST | /v1/api-keys/:id/revoke | revoke a key (owner) |
| GET | /v1/me | signed-in person, their orgs and roles, and for each org free_limit_exceeded_at when it went past Free (null where billing is not open) (session only) |
| POST | /v1/me/orgs | { name } → a new org on Free with the caller as owner (session only) |
| GET | /v1/me/invitations | open, unexpired invitations to the signed-in person that their account may accept: any when its address was proven by an emailed code, Google or a verified Microsoft domain; only its own organization's for an account a customer's SSO created (session only) |
| POST | /v1/me/invitations/:id/accept | join that organization with the invitation's role; 404 when it is not open to this account (session only) |
| POST | /v1/me/invitations/:id/decline | remove the invitation and free its seat; recorded in that organization's audit log (session only) |
| GET | /v1/org/members | members, open invites, seats used / limit. A signed-in person only: an API key or a device token is refused |
| POST | /v1/org/members | { email, role? } → an invitation that waits for them to accept it, emailed to them and good for 14 days, whether or not they have an account (201, outcome: invited, emailed, expires_at); 200 outcome: already_member and no change for someone already in the organization; 402 when every seat is taken, though re-sending an open invite takes no new seat and renews it (owner) |
| PATCH | /v1/org/members/:userId | { role } change a member's role: owner, admin, member (shown as Analyst) or viewer (shown as Read-only); making an owner or changing an owner's role needs an owner (403 otherwise); 409 when that would leave no owner (owner or admin) |
| PATCH | /v1/org/members/:userId/grants | { billing_manager?, evidence_reader? } give or take away a grant; each change is in the audit log (owner) |
| DELETE | /v1/org/members/:userId | remove a member; the last owner stays, and only an owner removes an owner (owner or admin) |
| DELETE | /v1/org/invites/:id | withdraw an invite (owner or admin) |
| | Every invite, join, role change, removal, withdrawn and declined invite is written to GET /v1/org/audit and sealed by the ledger |
| GET | /v1/org/sso | the org's own OpenID Connect issuer (issuer, client id, email domain, verified_at, and tested_at: when an owner signed in through it, after which /login routes the domain; never the secret), the DNS record that proves the domain (domain_record), and the redirect URI to register (owner) |
| PUT | /v1/org/sso | { issuer, client_id, client_secret?, email_domain } set it; Business only; the secret is required the first time and kept when omitted; a new email domain has to be proven again, and after any edit /login waits for an owner's sign-in before routing the domain again; 409 when another org already proved that domain (owner) |
| POST | /v1/org/sso/verify | look up domain_record (a TXT record at _openwake.<domain>) and mark the domain proven: 200, 422 while the record is not published, 409 when another org proved the domain first. Until the domain is proven the provider signs nobody in, and it only ever signs in addresses at that domain (owner) |
| DELETE | /v1/org/sso | remove it (owner) |
| PATCH | /v1/agents/:id | { name?, parent_agent_id?, kind?, policy? } rename, re-parent (submodule), or set the allowed context of an agent this org registered. policy is { data_classes?: [...], counterparties?: [...] }; * allows all, acme/* a subtree; null clears it |
| POST | /v1/agents/:id/events | { kind, counterparty?, data_classes?, outcome?, check_id?, detail?, tool?, action?, acting_for?, delegated_by?, parent_event_id?, task_id?, purpose?, authority? } → the event scored against the agent's policy (within_policy, policy_reasons) and its ledger entry. kind is delegation, tool_call, data_out, data_in, decision or custom; detail is one sealed line, never a payload. 600/min per org. Scout for Agents posts one of these per MCP tool call |
| GET | /v1/agents/:id/events | that agent's events, newest first |
| GET | /v1/org/activity | ?days=90&limit=100 every agent's events for the org |
| GET | /v1/org/activity/flows | ?days=30&node=column:value the activity view: every event as a path source → actor → action → data class → destination → outcome, aggregated into nodes and weighted edges with the flagged share (blocked or outside policy). With node, only the events through that node, returned as events. What the Agents page's Activity tab draws |
| GET | /v1/org/findings | ?status=open (default), acknowledged or all: behavior worth a look, from the org's events and nothing else: first contact, a sensitive class to a vendor that trains, the exfil shape (many reads then a send in one session), a burst against the agent's own rate, a destructive action on a newly registered server. Runs the rules first when they have not run in the last minute. See docs/recorder.md, Findings |
| POST | /v1/org/findings/:id/ack | acknowledge a finding (members; viewers cannot). The record stays; the finding leaves the open list |
| GET | /v1/org/activity/stream | server-sent events: every agent event (activity) and every Scout report (footprint) as it lands, ?since=<event id> to resume; ping every 16 s, bye after 30 min (reconnect). What /dashboard/live shows |
| GET | /v1/org/overview | ?days=30 the org's dashboard: watched vendors, changes by materiality, objection windows closing soonest, alerts sent, agent activity |
| GET | /v1/org/changes | ?days=90&limit=200&handled=0 fact and document changes on the watched vendors, newest first, with the notice window, the handled state and a drafted objection for fact changes |
| POST | /v1/org/changes/:kind/:id/handled | { handled?: true, note? } mark a change handled (or reopen it) for this org |
| GET | /v1/org/vendors | the vendors the org watches with the latest record's headline facts, notice period, and change counts for 30 days |
| DELETE | /v1/org/vendors/:slug | stop watching a vendor across the org's watchlists (owner) |
| GET | /v1/org/graph | ?days=90 the org's agents as a tree, the counterparties they reached (checks + events, data classes, decisions, out-of-policy counts), and what sits downstream of those vendors |