Skip to main content

Overview

The buyer activity feed surfaces meaningful mutations across your workspace — CREATE, UPDATE, DELETE, ARCHIVE, and EXECUTE actions on advertisers, campaigns, creatives, media buys, products, and packages — along with the actor that performed them (a human user or a service token / agent) and the time the change was recorded. Use audit logs for:
  • Compliance — produce a tamper-evident trail of who changed what and when across multi-tenant workspaces.
  • Debugging — reconstruct the sequence of events around a campaign that suddenly stopped pacing or a creative that flipped to rejected.
  • Post-incident analysis — answer “what changed in the last hour?” and “did this agent touch anything it wasn’t supposed to?”.
  • Operational visibility — feed the data into a SIEM, a Slack channel, or your own dashboard.
Audit logs are scoped to your customer (the buyer organization). Each row identifies the actor (userId + userEmail for humans, serviceTokenId + serviceTokenName for agents), the resource (resourceType + resourceId + resourceName), the action, and the parameters or field-level changes that drove it.
All endpoints below are mounted under https://api.agentic.scope3.com/api/buyer/. The activity feed is the REST fallback that powers the in-app activity view; agents and external systems can poll it directly.

Prerequisites

  • A Scope3 API key (see Authentication)
  • ADMIN role or above for the buyer customer — audit logs include actor identity and are not exposed to non-admin roles
  • Optional: a campaign or advertiser ID to scope the feed
export SCOPE3_API_KEY=scope3_<your_api_key>
export BASE=https://api.agentic.scope3.com/api/buyer

Step 1: List recent activity

1

Pull the most recent 50 events

curl "$BASE/audit-logs?take=50" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
2

Inspect the response

{
  "data": {
    "logs": [
      {
        "id": 81234,
        "timestamp": "2026-04-26T14:30:12.481Z",
        "createdAt": "2026-04-26T14:30:12.481Z",
        "action": "UPDATE",
        "resourceType": "CAMPAIGN",
        "resourceId": "camp_abc123",
        "resourceName": "Q2 Brand Launch",
        "parentType": "BRAND_AGENT",
        "advertiserId": 42,
        "userId": 901,
        "userEmail": "alex@brand.example",
        "userName": "Alex Operator",
        "serviceTokenId": null,
        "serviceTokenName": null,
        "parameters": { "budget": { "total": 250000 } },
        "changes": { "budget.total": { "from": 200000, "to": 250000 } },
        "description": "Increased total budget from $200,000 to $250,000"
      }
    ],
    "total": 4128
  },
  "meta": {
    "pagination": { "skip": 0, "take": 50, "total": 4128, "returned": 1 }
  }
}
Each row carries:
FieldNotes
id, timestamp, createdAtStable row identifier and event time (ISO 8601, UTC)
actionOne of CREATE, UPDATE, DELETE, ARCHIVE, EXECUTE
resourceTypeCAMPAIGN, CREATIVE, MEDIA_BUY, PRODUCT, PACKAGE
resourceId, resourceNamePublic ID and human label of the resource that changed
parentType, advertiserIdHierarchy context (e.g. the advertiser the campaign belongs to)
userId, userEmail, userNameSet when a human user made the change
serviceTokenId, serviceTokenNameSet when an agent / service token made the change
parametersThe input payload for the operation (e.g. the body of an UPDATE)
changesField-level before/after diff, populated where applicable
descriptionPre-rendered human-readable summary
Exactly one of (userId, userEmail) and (serviceTokenId, serviceTokenName) is set per row. Use that to distinguish human edits from agent activity.

Step 2: Filter

The endpoint supports four filter dimensions. Combine them as needed.
Query paramTypeMeaning
startDate, endDateISO timestampsInclusive time window
advertiserIdintegerRestrict to a single advertiser
campaignIdstring (e.g. camp_abc123)The campaign row plus all of its descendants (media buys, etc.)
resourceTypesrepeated or comma-separated enumSubset of CAMPAIGN, CREATIVE, MEDIA_BUY, PRODUCT, PACKAGE
take, skipintegersPagination — take defaults to 50, max 500
curl "$BASE/audit-logs?startDate=2026-04-26T00:00:00Z&endDate=2026-04-26T23:59:59Z&take=200" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
resourceTypes accepts either a comma-separated value (?resourceTypes=CAMPAIGN,CREATIVE) or repeated query params (?resourceTypes=CAMPAIGN&resourceTypes=CREATIVE). The default is the full set of buyer resource types.
The feed always restricts to meaningful actionsCREATE, UPDATE, DELETE, ARCHIVE, EXECUTE. Read-only operations (GET / list calls) are not surfaced.

Step 3: Common patterns

Who changed this campaign?

Scope to a campaign and inspect the actor on each row. The campaignId filter matches both the campaign itself and its descendants (media buys, etc.) so you see the full activity tree.
curl "$BASE/audit-logs?campaignId=camp_abc123&take=100" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
Then, on the client, group by userEmail || serviceTokenName to see which operator or agent has been touching the campaign.

What did this agent do today?

Filter to a 24-hour window and look at rows where serviceTokenId is non-null. Match serviceTokenName against the agent you care about.
curl "$BASE/audit-logs?startDate=2026-04-26T00:00:00Z&take=500" \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  | jq '.data.logs[] | select(.serviceTokenName == "ops-bot")'

Did this incident leave a trace?

For post-incident analysis, pull the time window around the symptom and filter to the resource types most likely to have driven it.
curl "$BASE/audit-logs?startDate=2026-04-26T13:45:00Z&endDate=2026-04-26T14:15:00Z&resourceTypes=CAMPAIGN,MEDIA_BUY" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
The description field gives a one-line human summary; parameters and changes carry the full diff for deeper inspection.

Best practices

Pagination — the endpoint orders by timestamp DESC. Page with skip + take; for large back-fills, iterate by time window (endDate of one page becomes startDate of the next) instead of paging deep into a single window.
Polling cadence — for live tailing, poll once per minute and use startDate set to the most recent timestamp you’ve already ingested. Do not poll faster than once per 30 seconds.
  • Retention — audit rows are retained for the standard customer retention window. Archive rows you need long-term to your own warehouse.
  • Pagination ceilingtake is capped at 500. For larger exports, iterate by time window.
  • Idempotencyid is stable per row, so client-side dedupe on id is safe across overlapping polls.
  • Don’t rely on actions filtering at the API — the activity feed always restricts to meaningful actions; filter further client-side if you need to (e.g. only DELETE).

Endpoint reference

MethodPathPurpose
GET/audit-logsList buyer activity, with optional filters and pagination
Query parameters: startDate, endDate, advertiserId, campaignId, resourceTypes, take (default 50, max 500), skip (default 0). Response: { data: { logs: BuyerAuditLog[], total: number }, meta: { pagination: { skip, take, total, returned } } }. See the OpenAPI spec for the full BuyerAuditLog shape: API Reference.
  • Notifications — push notifications for the same underlying events
  • Errors — error codes you may see surfaced in parameters
  • Authentication — required role and token setup