The protocol does not mandate what a buyer must share with a counterparty. It does give you the primitives to produce two distinct views of the same audit trail:Documentation Index
Fetch the complete documentation index at: https://agenticadvertisingorg-changeset-release-main.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
- An internal view — the buyer’s full record of every check, finding, budget movement, and human review. Used for self-protection, regulator audits, and internal compliance review.
- A shareable view — a scoped subset, addressed to one counterparty (a seller, an agency, a third-party auditor). Reveals only what that party needs to verify their own action.
get_plan_audit_logs. The split is a matter of filtering and field selection, not a separate protocol.
Why split at all
Three reasons buyers maintain distinct views:- Strategy leakage. Total authorized budget, channel allocation, and remaining headroom across all sellers are competitive signals. Note that derived ratios are not safer than raw amounts —
budget.utilization_pctis a one-step inverse problem if a seller knows their own committed share. A single seller does not need to know the buyer’s full plan to verify their own buy. - Cross-counterparty isolation. Seller A has no business seeing the findings, governance contexts, or outcomes for Seller B. A shareable view is always scoped to the requesting party’s
governance_contextvalues. - Internal review fields. Human review reasons, drift metrics, and oversight thresholds are the buyer’s own governance posture. They protect the buyer in a regulator audit; they are not addressed to a counterparty.
Field tagging
The table below classifies every field in theget_plan_audit_logs response by who can safely see it.
| Field | Internal | Shareable with the specific seller | Shareable with regulator/auditor |
|---|---|---|---|
plans[].plan_id, plan_version | yes | yes (when scoped) | yes |
plans[].status | yes | yes (when scoped) | yes |
plans[].budget.authorized | yes | no | yes |
plans[].budget.committed | yes | no | yes |
plans[].budget.remaining | yes | no | yes |
plans[].budget.utilization_pct | yes | no | yes |
plans[].channel_allocation.* | yes | no | yes |
plans[].governed_actions[].governance_context | yes | yes (own context only) | yes |
plans[].governed_actions[].purchase_type | yes | yes (own context only) | yes |
plans[].governed_actions[].status | yes | yes (own context only) | yes |
plans[].governed_actions[].committed | yes | yes (own context only) | yes |
plans[].governed_actions[].check_count | yes | yes (own context only) | yes |
plans[].summary.checks_performed, outcomes_reported | yes | no | yes |
plans[].summary.statuses | yes | no | yes |
plans[].summary.findings_count | yes | no | yes |
plans[].summary.human_reviews[] | yes | no | redact reason; share resolution + timestamp on request |
plans[].summary.drift_metrics.* | yes | no | available if the buyer’s counterparty rules require disclosure |
plans[].entries[].id, type, timestamp | yes | yes (own context only) | yes |
plans[].entries[].caller | yes | yes (own context only) | yes |
plans[].entries[].tool | yes | yes (own context only) | yes |
plans[].entries[].check_type, verdict | yes | yes (own context only) | yes |
plans[].entries[].mode | yes | yes (own context only) | yes — distinguishes a denied from an approved-with-finding under audit |
plans[].entries[].explanation | yes | yes (own context only) | yes |
plans[].entries[].categories_evaluated | yes | yes (own context only) | yes |
plans[].entries[].policies_evaluated | yes | yes (own context only) | yes |
plans[].entries[].findings[] | yes | yes (own context only) | yes |
plans[].entries[].plan_hash | yes | yes (own context only) | yes — auditors verify this |
plans[].entries[].governance_context | yes | yes (own context only) | yes |
plans[].entries[].purchase_type | yes | yes (own context only) | yes |
plans[].entries[].outcome, outcome_status | yes | yes (own context only) | yes |
plans[].entries[].committed_budget | yes | yes (own context only) | yes |
Producing a shareable view
To answer “what should I share with Seller X?”, filter the audit query to the contexts that belong to that seller and drop plan-level aggregates. Request scoped to one seller’s actions:governed_actions and entries to the requested contexts. The buyer is still responsible for stripping budget.*, channel_allocation.*, summary.findings_count, summary.statuses, and summary.drift_metrics before forwarding — those summaries cover the entire plan and reveal totals across other sellers.
Minimum compliance attestation (no entries):
For counterparties who only need proof that a buy was governed — not the full trail — share a four-field attestation derived from the audit response:
plan_hash against the plan revision they signed under, and the policies_evaluated list confirms which registry policies were applied. Nothing else about the buyer’s portfolio is disclosed.
Regulator and auditor views
A regulator typically asks for one of three things:- Did human oversight occur where required? Share
summary.human_reviews[]and therequires_human_reviewflag from the resolved policies. Reasons may be redacted or summarized; resolutions and timestamps should be intact. - Did the buy comply with a specific regulation? Share entries scoped by
policies_evaluatedcontaining the regulation’spolicy_id(e.g.,us_coppa). Includeplan_hashso the regulator can verify against the plan revision. - Are oversight metrics within thresholds? Share
summary.drift_metricsand the policy-derived thresholds. Ahuman_review_ratebelowhuman_review_rate_minis a signal worth explaining.
Worked example: a clean buy
A plan with 150K, then reports the outcome. The full internal audit response:governed_actions[] entry and the entries[] filtered to governance_context = 11ab64d0.... Plan-level budget.authorized, budget.remaining, and the summary aggregate stay buyer-side.
What violations look like
Findings are how the audit trail communicates risk. Two patterns worth knowing:Security-shaped finding: an unauthorized seller
The plan declaresapproved_sellers: ["https://ads.seller-approved.example"]. A different seller calls check_governance and gets denied:
statuses.denied: 1 and findings_count: 1. The unauthorized seller’s governance_context is still recorded — the trail captures the attempt, not just the success.
Coaching-shaped finding: an Annex III prerequisite is missing
A plan withpolicy_categories: ["fair_lending"] (mortgage, consumer credit, etc.) auto-flips human_review_required: true. If the brand profile doesn’t expose a contestation contact, the check fails closed with an actionable explanation:
The operator’s dial: enforce / advisory / audit
mode is set on the plan via sync_plans and is the operator’s primary lever. The same caller, same payload, same finding produces three different outcomes depending on mode.
mode: "enforce" — the buy is blocked at the governance layer:
mode: "advisory" — the buy proceeds; the operator gets a critical finding to act on post-hoc:
mode: "audit" — the buy proceeds silently; the finding is in the log for retrospective analysis:
| Mode | Velocity | Safety | When to use |
|---|---|---|---|
enforce | Slowest — checks block buys | Highest — violations cannot ship | Production for regulated brands; default for new operators |
advisory | Full velocity | Findings surface but don’t block | Rolling out a new policy; observing behavior before tightening |
audit | Full velocity | Findings logged silently | Backstop telemetry; never the only governance posture |
check_governance response but not consistently on get_plan_audit_logs responses (#3156).
What the protocol guarantees
Two invariants you can rely on when designing your shareable view:plan_hashis verifiable. It isbase64url_no_pad(SHA-256(JCS(plan_payload)))over the plan revision the check was evaluated against. Any party with the plan revision can recompute and byte-compare the digest. See Plan binding and audit.- Inline policies cannot relax registry policies. A buyer’s bespoke
policyentries can only add restrictions on top of registry-sourced policies. So when a shareable view showspolicies_evaluated: ["us_coppa"], the counterparty can trust that the registry version ofus_coppawas applied at its declaredenforcementlevel — the buyer did not silently downgrade it. See Policy Registry.
Related
get_plan_audit_logs— request and response schema- Campaign governance specification — plan binding, drift detection, governance context lifecycle
- Policy Registry — policy versioning,
effective_date, registry vs inline policies - Annex III & Art 22 obligations — when human review is required