Skip to main content
POST
Report agent activity

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Headers

X-Opal-Actor
string

The identity the reporting client claims this activity belongs to - an email or an Anthropic user id. Unverified: a Claude Code hook payload contains no user identity, so this has to be injected by whoever deploys the hook (via the http handler's headers map and allowedEnvVars interpolation), and whoever controls the machine controls the header. Used only when the API key itself does not identify a developer. When the email belongs to a person in the organization, that person is recorded as who the activity was reported for (always as a claim), and the activity is attributed to the one Claude agent they own, if they own exactly one. The API key's own email is never treated this way: a key belongs to whoever created it, which with a shared key is not who is at the keyboard. Omitting it is valid. When an event's opal_reported object carries other emails, Opal also tries them, in the order configured_email, claude_account_email, git_email, after this header and skipping any that repeat it. The first one that resolves to an agent wins.

X-Opal-Host
string

The name of the machine that sent this request, as that machine reports it (hostname -s). Unverified: two machines can share a name, and whoever controls the machine controls the header. Stored with each event, so a reader can tell which machine reported it. When an event's own opal_reported.hostname names a different machine, this header wins and the body's value is kept beside it. Omitting it is valid.

Body

application/json

AgentActivityIngestRequest Object

Description

A batch of agent activity events.

Three body shapes are accepted: this envelope ({"events": [...]}), a bare JSON array of AgentActivityEvent, and a single AgentActivityEvent object. The last exists so a Claude Code hook can POST here directly, since a hook sends one bare payload per event and cannot wrap it.

events
object[]

Response

A per-batch accounting of what was accepted, stored, and attributed. An organization that has agent activity turned off gets a 200 with an empty body for every body shape, so a sender does not keep the events and try again.

AgentActivityIngestResult Object

Description

What one ingest request actually did.

received and stored differ when a delivery was retried and deduplicated. attributed and unattributed sum to received rather than to stored, because attribution happens before deduplication. Unattributed events are kept, not dropped: activity Opal cannot tie to a governed agent is itself a governance finding.

received
integer
required

Events parsed out of the request body.

stored
integer
required

Rows actually written. Lower than received when a retried delivery was deduplicated on tool_use_id.

attributed
integer
required

Events that resolved to an agent in this organization.

unattributed
integer
required

Events that resolved to no agent, and are therefore visible only in the unattributed activity list. A persistently high value means the reporting clients are not sending an identity Opal can resolve.