Two read-only lists, both on logs:read, both scoped to the key's own
workspace.
GET /v1/logs/agent-calls is every request an AI assistant made here: which
connection, which tool it said it was running, which operation, what it
answered, how long it took, and the approval it carried if it carried one. It
is the answer to "what did my assistant actually do?", and it is written for
every such request whatever the outcome — a refusal is on the record exactly
like a success. Kept for 90 days.
GET /v1/logs/audit is the workspace's activity log: the same list the
dashboard shows under Settings, Activity, for everybody rather than only for
assistants.
Two things about the audit log are worth knowing before you build on it.
An actor is a label, not an account. Each entry says who did it as
{ "kind": "member", "label": "Jo Rivera" }, or api_key with the key's name,
or support when BoltClaw support was inside the workspace, or system. There
is no account id and no email address, here or anywhere else in this API.
resource_id is null when the entry is about the workspace itself or its
organisation — the workspace.* and impersonation.* entries. A log entry
names the thing it acted on, never the workspace or the organisation by id.
Anything credential-shaped in details is [redacted]. An entry's details
are written by a dozen different operations, and a log is not a place to find a
secret. A value that looks like a key, a hash or a signature, and any field
named like one, is replaced before the entry leaves the database.
Operations
GET /v1/logs/agent-calls
List agent calls
Scope logs:read.
Every request an AI assistant made in this workspace, newest first: which connection, which tool it said it was running, which operation, what it answered, how long it took, and the approval it carried if it carried one. Kept for 90 days.
Page with before, an ISO-8601 timestamp from the last row of the previous page.
Parameters
| Name | In | Type | |
|---|---|---|---|
before |
query | date-time |
An ISO-8601 timestamp with an offset. Returns calls older than it. |
limit |
query | integer |
Page size, 1 to 100. Above 100 is clamped; anything else is the default. (default 50; >= 1; <= 100) |
Answers
| Status | Body | |
|---|---|---|
| 200 | AgentCallList |
A page of calls. |
| 400 | ErrorEnvelope |
VALIDATION_ERROR: a body that is not JSON, a field that breaks its rule (named in fields), a bad query value or cursor, or a malformed Idempotency-Key. |
| 401 | ErrorEnvelope |
UNAUTHORIZED: no key, or one that is malformed, unknown or revoked. It never says which. |
| 403 | ErrorEnvelope |
INSUFFICIENT_SCOPE: the key lacks this operation's scope. Or ORGANISATION_SUSPENDED: the key's organisation is suspended. Never about another workspace's object, which is 404. |
| 429 | ErrorEnvelope |
RATE_LIMITED: too many requests. Wait for Retry-After seconds. |
| 500 | ErrorEnvelope |
INTERNAL_ERROR: ours. Safe to retry; send the same Idempotency-Key on a POST. |
GET /v1/logs/audit
List the activity log
Scope logs:read.
What everybody did in this workspace, newest first: the same list the dashboard shows under Settings, Activity. Each entry names the action, what it acted on, when, and who by, as a label rather than an account: a member's display name, the name of an API key, or BoltClaw support.
Values that look like a credential are replaced with [redacted] before the entry leaves
the database, so a log is never a place to find one.
Parameters
| Name | In | Type | |
|---|---|---|---|
cursor |
query | string |
The next_cursor from the previous page. Opaque; an invalid one is 400. (max 512) |
limit |
query | integer |
Page size, 1 to 100. Above 100 is clamped; anything else is the default. (default 50; >= 1; <= 100) |
Answers
| Status | Body | |
|---|---|---|
| 200 | AuditEntryList |
A page of entries. |
| 400 | ErrorEnvelope |
VALIDATION_ERROR: a body that is not JSON, a field that breaks its rule (named in fields), a bad query value or cursor, or a malformed Idempotency-Key. |
| 401 | ErrorEnvelope |
UNAUTHORIZED: no key, or one that is malformed, unknown or revoked. It never says which. |
| 403 | ErrorEnvelope |
INSUFFICIENT_SCOPE: the key lacks this operation's scope. Or ORGANISATION_SUSPENDED: the key's organisation is suspended. Never about another workspace's object, which is 404. |
| 429 | ErrorEnvelope |
RATE_LIMITED: too many requests. Wait for Retry-After seconds. |
| 500 | ErrorEnvelope |
INTERNAL_ERROR: ours. Safe to retry; send the same Idempotency-Key on a POST. |
Shapes
The objects these operations send and answer.
AgentCall
| Field | Type | |
|---|---|---|
id |
uuid |
(required) |
key_id |
uuid | null |
(required) |
client_name |
string | null |
What the assistant called itself when it signed in. (required) |
tool |
string | null |
The tool it said it was running. A label it chose, never acted on. (required) |
operation_id |
string |
(required) |
method |
string |
(required; one of GET, POST, PATCH, DELETE) |
status |
integer |
(required) |
duration_ms |
integer | null |
(required) |
approval_id |
uuid | null |
(required) |
created_at |
date-time |
(required) |
AgentCallList
| Field | Type | |
|---|---|---|
data |
AgentCall[] |
(required) |
next_cursor |
NextCursor |
Pass back as cursor for the next page; null on the last page. (required) |
AuditEntry
| Field | Type | |
|---|---|---|
id |
string |
(required) |
action |
string |
(required) |
resource |
string | null |
(required) |
resource_id |
string | null |
The id of what it acted on. null when that is the workspace itself or its organisation (the workspace.* and impersonation.* entries): a log entry never names either of those by id. (required) |
created_at |
date-time |
(required) |
actor |
object |
Who did it, as a label. Never an account id and never an email address. (required) |
details |
object |
What changed. Anything that looks like a credential is [redacted]. (required) |
AuditEntryList
| Field | Type | |
|---|---|---|
data |
AuditEntry[] |
(required) |
next_cursor |
NextCursor |
Pass back as cursor for the next page; null on the last page. (required) |
NextCursor
Pass back as cursor for the next page; null on the last page.
string | null.