Activity & Audit

Preview — pending review

This reference is generated from the platform API contract and is still under review. Operations, fields, and descriptions can change before publication.

List Activity Events over a real time range, with server-computed totals and histogram

GET
/scopes/{scopeId}/activity/activity-events

The append-only audit trail of control-plane actions in the active scope, powering the the Activity page route. Every event is one Operation: every async write opens an operation stamping the acting principal and the request's source IP, so the operation stream IS the audit stream. The actor's display name and email are those of the matching user of the caller's own tenant, so only users in the caller's tenant resolve; an unmatched principal keeps a null name and email rather than inventing one. The time window is a SERVER-SIDE filter, not a client-side narrowing of a fixed-size page. Supply either range (a trailing window ending now) or an explicit from/to pair; supplying both is a 422. With neither, the whole stream visible in the scope is returned. Three numbers accompany the page and are all computed over the FULL filtered range, never over the returned page: meta.total (rows matching every filter), totals (the Success/Failure/ Pending breakdown) and buckets (the volume histogram). totals and buckets deliberately reflect every active filter EXCEPT result — they ARE the result breakdown, so filtering them by result would be circular and would make the tiles and the bars disagree with each other. With no result filter, meta.total equals totals.total; with result=Failure, meta.total equals totals.failure. Validation: scopeId must resolve to a scope the caller can access (unknown or unauthorized → 404 NOT_FOUND, per the 404-not-403 rule); range must be one of 1h|24h|7d|30d|90d and must not be combined with from/to; from must not be after to; result must be one of Success|Failure|Pending; page ≥ 1 and pageSize within 1..200 — any violation → 422 VALIDATION_FAILED. A very wide window is never refused: the histogram step widens so the window always fits within a readable number of buckets. RBAC: READ on the audit permission-matrix key. owner, contributor and reader all hold it; the billing-ops role does not and is refused. Async & state: Synchronous read; no state change. The stream is append-only and is never mutated by this endpoint. Errors: 401 when the session/credential is missing or expired; 404 when scopeId does not resolve or the caller cannot read the audit trail on it; 422 on a malformed filter, range or pagination value; 500 on unexpected backend failure. Idempotency/Concurrency: Safe and cacheable; no idempotency key required. Repeated identical requests return identical pages for the same stream snapshot.

Authorization

bearerToken
headerAuthorizationBearer <token>

An API token (pc_live_…) or a service-account key (sak_live_…), created in Identity & Access Management and sent as Authorization: Bearer <token>. Requests are rate limited per credential and per tenant: every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a refused request gets 429 RATE_LIMITED with Retry-After.

Path Parameters

scopeId*string

Opaque ownership+authorization scope resolving to tenant + subscription + project.

Query Parameters

q?string

Free-text search.

page?integer

1-based page number.

Range1 <= value
Default1
pageSize?integer

Items per page (max 200).

Range1 <= value <= 200
Default50
from?string

Inclusive lower bound on the event timestamp (ISO-8601 instant). Mutually exclusive with range.

Formatdate-time
to?string

Exclusive upper bound on the event timestamp (ISO-8601 instant). Mutually exclusive with range.

Formatdate-time
range?string

Trailing time window ending now, expanded server-side into from/to. Sugar for the console's range presets; mutually exclusive with from/to.

Value in"1h""24h""7d""30d""90d"
action?string

Filter by exact control-plane action id, e.g. compute.instance.create.

actor?string

Filter by exact actor - either the resolved user display name or the raw principal id.

result?string

Filter by event outcome. Narrows data and meta.total; deliberately does NOT narrow totals or buckets.

Value in"Success""Failure""Pending"

Response Body

A page of Activity Events, newest-first, with the full-range totals and histogram.

application/json
  1. response
data*array<>
meta*

Pagination envelope metadata. List responses are always { data, meta } — never a naked array.

totals*

Outcome breakdown over the FULL filtered range, never over the returned page. Reflects every active filter except result - these counters are the result breakdown, so filtering them by result would be circular. success + failure + pending always equals total.

buckets*array<>

The volume histogram over the whole selected range, oldest bucket first.

curl -X GET "https://example.com/scopes/string/activity/activity-events"
{  "data": [    {      "id": "string",      "action": "compute.instance.create",      "state": "PENDING",      "result": "Success",      "resourceKind": "string",      "resourceId": "string",      "resourceName": "string",      "principalId": "string",      "actorName": "string",      "actorEmail": "string",      "sourceIp": "string",      "actorType": "user",      "credentialId": "string",      "error": {        "code": "string",        "message": "string",        "field": "string",        "details": {},        "retryable": false      },      "warning": {        "code": "string",        "message": "string",        "field": "string",        "details": {},        "retryable": false      },      "progressPercent": 0,      "startedAt": "string",      "finishedAt": "string",      "createdAt": "string",      "updatedAt": "string"    }  ],  "meta": {    "page": 1,    "pageSize": 1,    "total": 0,    "hasNext": true  },  "totals": {    "total": 0,    "success": 0,    "failure": 0,    "pending": 0  },  "buckets": [    {      "startsAt": "2019-08-24T14:15:22Z",      "endsAt": "2019-08-24T14:15:22Z",      "success": 0,      "failure": 0,      "pending": 0,      "total": 0    }  ]}