Audit trail
Only people who manage the workspace (owners, and the role that can invite people) can read it; anyone else gets 403. Every change to how the workspace is set up, newest first, by whoever made it: a member (member), a hire (hire), Roster itself (system), the assistant (assistant) or an API token (api_token). Hires, their instructions, hours, tools, notebooks, responsibilities and follow-ups; skills; connections; departments, seats and goals; approvals decided; members, roles and invitations; workspace settings; seats. action is stable and dotted (hire.renamed, note.added); filter by one, or by everything about one kind of thing (action=hire). changes holds only the fields that changed, as { from, to }, with credentials shown as [redacted]. summary is the change in one sentence and sentence the same in parts, the actor and the target marked so they can be linked. requestId ties together changes made by one request or one piece of a hire's work. Pass next back as cursor for older changes.
sessionbetter-auth.session_token<token>Set by POST /api/auth/sign-in/email.
ws*stringThe workspace id (from GET /api/me).
actorType?stringWho made the change: a member, a hire, Roster itself, the assistant or an API token.
"member""hire""system""assistant""api_token"actorId?stringThe member's user id or the hire's id.
length <= 200action?stringOne action (hire.renamed) or every action about one kind of thing (hire).
^[a-z_]+(\.[a-z_]+)?$targetType?stringWhat was changed.
"hire""handbook""skill""connection""department""position""goal""approval""workspace""member""invitation""known_contact""billing""api_token"targetId?stringIts id: a hire's id shows everything about that hire.
length <= 200from?|Changes at or after this time: a date (2026-11-09) or a time (ISO 8601).
to?|Changes before this time: a date (2026-11-10) or a time (ISO 8601).
cursor?stringnext from the previous page.
length <= 1000limit?integer1 <= value <= 10050A page of changes, and the cursor for the next one (null at the end).
application/jsoncurl -X GET 'https://app.useroster.work/api/workspaces/string/audit'{ "items": [ { "id": "0b7e…", "action": "hire.renamed", "actor": { "type": "member", "id": "u_123", "name": "Youssef" }, "target": { "type": "hire", "id": "5d0c…", "name": "Ledger Finance" }, "changes": { "displayName": { "from": "Ledger", "to": "Ledger Finance" } }, "detail": {}, "requestId": "8f14…", "createdAt": "2026-11-09T10:12:00.000Z", "summary": "Youssef renamed Ledger to Ledger Finance", "sentence": [ { "text": "Youssef", "role": "actor" }, { "text": " renamed Ledger to " }, { "text": "Ledger Finance", "role": "target" } ] }, { "id": "c2a9…", "action": "note.added", "actor": { "type": "hire", "id": "5d0c…", "name": "Ledger Finance" }, "target": { "type": "hire", "id": "5d0c…", "name": "Ledger Finance" }, "changes": {}, "detail": { "noteId": "41aa…", "note": "Invoices go out on Fridays" }, "requestId": "task 77e1…", "createdAt": "2026-11-09T09:40:00.000Z", "summary": "Ledger Finance added a note to its notebook: “Invoices go out on Fridays”", "sentence": [ { "text": "Ledger Finance", "role": "actor" }, { "text": " added a note to" }, { "text": " its notebook" }, { "text": ": “Invoices go out on Fridays”" } ] } ], "next": "WyJhdWRpd…"}Forget a known contact DELETE
Owners and admins only. A hire's first message to them waits for approval again, unless the connection has been in touch with them already.
People and invitations GET
Everyone in the workspace with their role (owner, admin or member), and invitations still waiting to be accepted. Agents use this rather than better-auth's routes, which need a session.