Skip to content

List Audit Log

Who or what changed state in the workspace, newest first.

GET/api/v1/audit-log

Requires an API key with the read scope.

The audit log merges three records FoxReach already keeps, read-only:

sourceWhat it records
campaign_statusCampaign state changes (campaign.state_changed) and sends blocked by a gate while a campaign stays active (campaign.send_blocked, one per reason, not one per attempt).
account_connectionEmail account connection changes (account.connection_changed) with the cause, including each failed attempt that counts toward disconnecting.
eventManual inbox thread changes (audit.inbox_thread.categorized, audit.inbox_thread.deleted), agency client changes (audit.agency_client.created, .renamed, .deleted), agency branding changes made with an API key (audit.agency_branding.updated), template sharing (audit.template.published, .unpublished), campaign changes made with an API key (audit.campaign.duplicated, .shared, .unshared, .leads_removed), team changes (audit.workspace_member.invited, .role_changed, .removed, audit.workspace_invite.revoked, .resent), API keys created or revoked (audit.api_key.created, .revoked), inbox notes added or deleted with an API key (audit.inbox_note.created, .deleted) and webhooks paused or resumed (webhook.paused, webhook.resumed).

Only these event types are returned, and only the fields listed below. The actor is shown as stored: system, system:<source>, user:<id> or api_key:<id> (with :agency:<workspace> when the key was acting as a client workspace). Rows for an email account disappear when the account is deleted.

Paginate with the cursor: pass meta.nextCursor from one page as cursor on the next, until it is null. Rows that share a timestamp keep a stable order.

Query Parameters#

pageSizeintegerquery
Rows per page, 1 to 100. Default 50.
cursorstringquery
The meta.nextCursor of the previous page.
sourcestringquery
campaign_status, account_connection or event.
sincestringquery
Only rows at or after this ISO 8601 time.
untilstringquery
Only rows at or before this ISO 8601 time.
actorstringquery
Only rows by exactly this actor string.
campaignIdstringquery
Only that campaign's campaign_status rows.
accountIdstringquery
Only that email account's account_connection rows.

Response#

dataarray
Show Entry
idstring
Row identifier.
atstring
ISO 8601 timestamp in UTC.
sourcestring
campaign_status, account_connection or event.
typestring
What happened, for example campaign.state_changed.
actorstring
Who or what did it, as stored. null on rows written before actors were recorded.
subjectobject
kind (campaign, email_account, reply, workspace, template, webhook, workspace_member, workspace_invite, api_key, inbox_note) and the id it points to.
fromstring
Previous state, category, name or role, or null.
tostring
New state, category, name or role, or null.
reasonstring
The reason code, or the route that made the change.
detailstring
Extra text (a gate message, a provider error cut to 500 characters, or the action), or null.
metaobject
pageSize and nextCursor (null on the last page).

Entries are not edited or deleted by the API. Agency actions that created, renamed or deleted a client are recorded on the agency workspace; template and webhook rows on the workspace they belong to.

Errors#

StatusDescription
401Missing, invalid, revoked or expired API key
403API key does not have the required scope: read
400cursor is not valid
422source is not one of the three values, or pageSize is outside 1 to 100

Rate Limit#

  • 300 requests per minute, shared by every read call in your workspace. Fixed 60-second window.
  • Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (unix epoch seconds) and X-RateLimit-Bucket (read).
  • A 429 response includes a Retry-After header (seconds until the bucket resets).

For client-side patterns, see Rate Limiting.

Was this page helpful?
View as MarkdownLast updated November 4, 2026