Skip to content

Activity

client.activity reads the dashboard’s Activity table: what people and their API keys did, newest first. A workspace’s activity holds what happened in it. The organization’s holds every workspace’s and its own (members, keys, workspaces, credits). Reading needs a key with data:read and a role there. A key restricted to workspaces cannot read activity.

client.events is something else: one job’s live stream.

from qualia import Qualia
client = Qualia()
# the workspace this client acts in (workspace=, QUALIA_WORKSPACE, else the key's own)
page = client.activity.list()
# the organization's, filtered and paged
page = client.activity.list(
client.account,
filter='verb = KEEP AND actor = API_KEY',
limit=100,
)
for row in page.items:
print(row.create_time, row.verb, row.dataset_label, row.changed_count)
next_page = client.activity.list(client.account, cursor=page.page_info.end_cursor)

parent is accounts/{a} for the organization, accounts/{a}/workspaces/{w} or a workspace id for one workspace, or None for this client’s workspace. filter is AIP-160: comparisons joined by AND over verb, actor (PERSON, API_KEY, SERVICE, MODEL, SYSTEM), workspace, text, create_time, subject and action. view="raw" lists every recorded event instead of intentional actions.

Response: a PaginatedPage of qualia.v1.ActivitySummary.

ActivitySummary (row.to_wire())
{
"event": "accounts/<a>/workspaces/<w>/events/<e>",
"uid": "<e>",
"createTime": "2026-10-30T09:00:00Z",
"verb": "KEEP",
"changedCount": 12,
"actor": { "kind": "API_KEY", "credential": "<key id>" },
"dataset": "accounts/<a>/datasets/<d>",
"datasetLabel": "folding"
}

get returns the event as the record holds it. details returns what it touched (episodes and their state before) and the fields it changed, as you may still see them. Both take the event’s full name, which list rows carry as row.event, or its id, read through the organization.

event = client.activity.get(row.event)
print(event.action, event.summary, event.actor.display_name)
details = client.activity.details(row.event)
for change in details.changes:
print(change.field, change.previous, change.current)

The recorded names of who did up to 100 actions, and each recorded key’s current label and owner.

actors = client.activity.actors([row.event for row in page.items])
names = {a.event: a.display_name for a in actors.actors}

Download the organization’s events record as JSON lines, oldest first.

lines = client.activity.export(
"events.jsonl",
start="2026-10-01T00:00:00Z",
end="2026-11-01T00:00:00Z",
)

It returns the number of events written. The file is personal data: member events carry usernames and emails. It needs a key with audit:read, not restricted to workspaces, whose creator is an Admin or Owner of the organization. The file appears only once the whole record has arrived; a download that breaks raises QualiaError and leaves nothing behind.