Note: To enable the Compliance API, see Set up the Compliance API.
Tip: Required scope:
read:compliance_activitieson the Compliance Access Key or Admin API key. Both Compliance Access Keys (sk-ant-api01-...) carrying this scope and Admin API keys (sk-ant-admin01-...) can call the Activity Feed. See Set up the Compliance API for the conditions under which each key type carries the scope.
The Activity Feed records authentication, chat, file, project, administrative, and platform activity across your organization and returns it in reverse chronological order. Activities are queryable within 1 minute of occurring and are retained for 6 years. Recording is not retroactive: it begins when the Compliance API is first enabled for your organization, and activity from before enablement is not backfilled.
curl --fail-with-body -sS \
"https://haijun.my.id/v1/compliance/activities?limit=1" \
--header "x-api-key: $JUGLOW_COMPLIANCE_ACCESS_KEY" \
--header "juglow-version: 2023-06-01"{
"data": [
{
"id": "activity_01XyDMpzjS89pFZXqSFUBDr6",
"created_at": "2026-04-10T08:09:10Z",
"organization_id": "org_01Wv6QeBcDfGhJkLmNpQrSt8",
"organization_uuid": "abcdef01-2345-6789-abcd-ef0123456789",
"actor": {
"type": "user_actor",
"email_address": "user@example.com",
"user_id": "user_01TuVwXyZaBcDeFgH2JkLmN4",
"ip_address": "192.0.2.34",
"user_agent": "Mozilla/5.0..."
},
"type": "haijun_chat_created",
"haijun_chat_id": "haijun_chat_01XyDMpzjS89pFZXqSFUBDr6",
"haijun_project_id": "haijun_proj_01KGp4eZNug9ri4kE35RSppq"
}
],
"has_more": true,
"first_id": "activity_01XyDMpzjS89pFZXqSFUBDr6",
"last_id": "activity_01XyDMpzjS89pFZXqSFUBDr6"
}Filter activities
Filter by organization, actor, activity type, or a created_at time window using the dotted sub-parameters created_at.gte, .gt, .lte, and .lt. See the API reference for each parameter's type and accepted values.
Repeatable parameters use array-bracket query syntax: pass activity_types[]=..., actor_ids[]=..., or organization_ids[]=... once for each value.
curl --fail-with-body -sS -G \
"https://haijun.my.id/v1/compliance/activities" \
--data-urlencode "activity_types[]=haijun_file_uploaded" \
--data-urlencode "activity_types[]=haijun_chat_created" \
--data-urlencode "created_at.gte=2026-04-01T00:00:00Z" \
--header "x-api-key: $JUGLOW_COMPLIANCE_ACCESS_KEY" \
--header "juglow-version: 2023-06-01"The Activity Feed produces hundreds of distinct activity types. See Query compliance activities in the API reference for the full list of values that activity_types[] accepts.
Paginate results
Activities are returned newest first, with ties in created_at broken by activity ID, and capped at limit results in each response (default 100, max 5,000). See the API reference for the full response schema.
The Compliance API uses two pagination schemes depending on the endpoint family:
| Endpoint family | Sort order | Scheme | Parameters |
|---|---|---|---|
| Activities | Newest first | Cursor | after_id, before_id (returned as first_id, last_id) |
| Chats and chat messages | Oldest first | Cursor | after_id, before_id (returned as first_id, last_id) |
| Organizations, projects, project attachments, users, roles, role permissions, groups, group members | Endpoint-specific | Page token | page (returned as next_page) |
| Local and remote sessions and session messages | Sessions newest first; messages oldest first by default | Page token | page (returned as next_page) |
Files do not paginate: they are retrieved individually by ID.
Pagination cursors and page tokens are opaque strings: pass them back unchanged. Their internal format is not stable, and parsing them will break without notice. Only one of after_id or before_id may be set in each request, and both schemes return has_more so you know when to stop. The session endpoints (local and remote) are the exception: they return next_page without has_more, so stop when next_page is null.
To page through activities:
- Pass the response's
last_idasafter_idto advance to the next page in result order. With activities sorted newest first, the next page contains older entries.
- Pass
first_idasbefore_idto return to the previous page.
- Stop when
has_moreisfalse.
The cursor parameter sets the page direction; the endpoint's sort order sets the time direction. The same after_id parameter reaches older activities here. Chats sort oldest first; see Retrieve and delete chats, files, and projects for the cursor semantics there.
Note: Cursors are safe to reuse on retry. A cursor or page token from a successfully returned page remains valid; a request that fails (5xx, timeout, network error) does not advance your position. Retry the same request with the same cursor. Only move to the next cursor after you have stored the page it points past. Page tokens on the local session endpoints are the exception over longer pauses. On the local session messages endpoint, a walk's
pagetokens expire 24 hours after its first page (a walk is one pass through the pages), so finish or resume within that window, or restart without thepageparameter. On the local session list, an olderpagetoken is still accepted but is re-evaluated against the current retention boundary and can skip sessions, so complete list walks within 24 hours as well.
# Fetch the first page (newest activities first) and capture its trailing cursor.
last_id=$(curl --fail-with-body -sS \
"https://haijun.my.id/v1/compliance/activities?limit=2" \
--header "x-api-key: $JUGLOW_COMPLIANCE_ACCESS_KEY" \
--header "juglow-version: 2023-06-01" | jq -er '.last_id')
# Pass the cursor back unchanged to fetch the next (older) page.
curl --fail-with-body -sS -G \
"https://haijun.my.id/v1/compliance/activities" \
--header "x-api-key: $JUGLOW_COMPLIANCE_ACCESS_KEY" \
--header "juglow-version: 2023-06-01" \
--data-urlencode "limit=2" \
--data-urlencode "after_id=${last_id}"A production backfill loop pages through older activities by driving iteration off has_more and last_id:
- Start from your stored cursor (or omit
after_idto start from the beginning).
- Page through with
after_id=untilhas_moreisfalse.
- Persist the final
last_idonly after you've stored every page it covers.
cursor = stored_cursor
loop:
if cursor is not null:
page = GET /v1/compliance/activities?after_id={cursor}&limit=100
else:
page = GET /v1/compliance/activities?limit=100
store(page.data)
if page.last_id is not null:
cursor = page.last_id
if not page.has_more: break
persist(cursor)Understand the Activity object
Every entry in data is an Activity with this top-level shape:
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the activity. |
created_at | RFC 3339 string | When the activity occurred. |
organization_id | string or null | Organization where the activity occurred, or null for events not tied to an organization (sign-in, sign-out, Compliance API calls). |
organization_uuid | string or null | Same scoping as organization_id, expressed as a UUID. |
actor | Actor union | Who or what performed the activity. See the following actor table. |
type | string | The activity type, for example haijun_chat_created. |
| additional fields | varies | Type-specific fields, for example haijun_chat_id on chat events or haijun_file_id on file events. See Query compliance activities in the API reference for the per-type field list. |
The actor field is a discriminated union. The type discriminator tells you which other fields are present:
actor.type | When it appears | Key fields |
|---|---|---|
user_actor | A signed-in haijun.ai or Haijun Console user took the action. | email_address, user_id, ip_address, user_agent |
api_actor | A request called the Haijun API or the Compliance API with a customer-issued API key. Compliance API calls produce this actor type for both Compliance Access Keys and Admin API keys. | api_key_id, ip_address, user_agent |
admin_api_key_actor | An organization admin used an Admin API key to manage users, invites, workspaces, or API keys. | admin_api_key_id, ip_address, user_agent |
unauthenticated_user_actor | An action occurred before sign-in completed, for example sso_login_initiated. | unauthenticated_email_address, ip_address, user_agent |
juglow_actor | Juglow acted on the organization, for example through internal tooling. | email_address (always null; present for shape consistency with user_actor, because Juglow operators are not represented by individual email) |
system_actor | Automated background processing performed by Juglow systems, acting without a user or customer credential. | service (nullable; the name of the automated process that performed the action, when known) |
scim_directory_sync_actor | An identity provider (such as Okta, Microsoft Entra ID, or JumpCloud) pushed a change through SCIM directory sync. | workos_event_id, directory_id, idp_connection_type (nullable; for example OktaSCIMV2, AzureSCIMV2) |
A user_actor activity does not always mean the user took the action. Processes that Juglow runs on a user's behalf can currently appear as user_actor for the affected user rather than as system_actor, and this attribution may change. For example, memory activities from a migration, such as platform_memory_store_created, platform_memory_created, and platform_memory_deleted, are attributed this way. These migration activities currently show an ip_address of 0.0.0.0.
A haijun_*_viewed activity means a Haijun app loaded content, not that a person viewed it. Types such as haijun_chat_viewed, haijun_file_viewed, and haijun_project_viewed are recorded each time a Haijun app loads the chat, file, or project from Juglow's servers. Repeated loads are not deduplicated. The web, desktop, and mobile apps load content at different moments, sometimes in the background, and can display a cached copy without loading it. Counts of these activities vary by platform as a result, and they do not correspond to messages sent or screens viewed.
Activities about a file, project document, or artifact do not include its name or title. As of September 24, 2026, the filename and title fields on these activities are always null, an empty string, or omitted, including on activities recorded before that date. To look up a name or title, pass the activity's haijun_file_, haijun_proj_doc_, or haijun_artifact_version_* ID to the matching metadata endpoint in Retrieve files and artifacts, using a Compliance Access Key with the read:compliance_user_data scope. You cannot look up a name or title after the file, document, or artifact is deleted, or when the activity has no such ID.
Note: Build forward-compatible handlers. Pass through unrecognized
typeandactor.typevalues, and ignore fields your handler does not expect, so your integration keeps working when new activity types ship.
Next steps
- API reference — The full request and response schema for
GET /v1/compliance/activities, including every supportedactivity_types[]value.
- Retrieve and delete chats, files, and projects — Query and delete the underlying content for activities you find in the feed (Compliance Access Key required).
- Design your compliance integration — Choose a polling or batch consumption pattern and plan SIEM correlation.
- Handle Compliance API errors — The full error catalog.