Attest Verify
Calling the agent
Verify speaks AdCP over MCP (Streamable HTTP). Everything below is the standard protocol; the only Verify-specific parts are the token and the ext.attest blocks.
Connect
| Endpoint | https://verify.cleartrust.cc/mcp |
| Auth | Authorization: Bearer atv_… (buyer) · atp_… (seller, per plan) |
| Protocols | governance, signals · specialisms governance-spend-authority, governance-delivery-monitor, signal-owned |
| Try it | npx @adcp/sdk https://verify.cleartrust.cc/mcp get_adcp_capabilities '{}' --auth $TOKEN |
Buyer accounts and tokens are made in the console by ClearTrust. Tokens are shown once and stored as hashes.
1. Sync a plan
Register the campaign plan Verify will judge spend against. Re-syncing the same plan_id updates it and bumps the version.
sync_plans {
"idempotency_key": "plan-sync-2026-10-12-0001",
"plans": [{
"plan_id": "spring_awareness",
"brand": { "domain": "brand.example" },
"objectives": "Spring awareness",
"budget": { "total": 10000, "currency": "USD", "reallocation_threshold": 2000 },
"flight": { "start": "2026-10-01T00:00:00Z", "end": "2026-10-31T23:59:59Z" },
"countries": ["US", "GB"],
"approved_sellers": ["https://sales.news.example/mcp"]
}]
}The answer lists each plan as active with the policies Verify applies. On first sync, ext.attest.seller_tokens[plan_id] carries an atp_ token: hand it to each seller through sync_governance so they can run delivery checks and report outcomes on that plan.
2. Check a spend
Before each purchase. Pass the publisher properties: without them Verify cannot judge seller authorisation or inventory quality and says so with a may finding.
check_governance {
"caller": "https://orchestrator.example/agent",
"plan_id": "spring_awareness",
"tool": "create_media_buy",
"target_agent": "https://sales.news.example/mcp",
"proposed_commitment": { "amount": 500, "currency": "USD" },
"payload": { "properties": ["news.example"], "countries": ["US"] }
}→ { "check_id": "chk_…", "verdict": "approved", "check_type": "intent",
"explanation": "Approved. Every policy passed.",
"findings": [], "expires_at": "…", "next_check": "…",
"governance_context": "…", "ext": { "attest": { "measurement": { … }, "console": "…" } } }Verdicts and modes
| Verdict | Meaning | What to do |
|---|---|---|
| approved | Proceed. Carries expires_at and governance_context. | Attach the context to the buy; act before it expires. |
| denied | A must finding that no person can override (unknown plan, blocked seller, wrong currency). | Fix the ask or the plan. |
| conditions | Held for a person. Condition human_review, a consultation_context and next_check. | Re-call with the same plan, seller and amount after next_check; the decision arrives as approved or denied. Accounts with a webhook are told at once. |
Each buyer account runs in one of three modes: audit (always approved, findings attached), advisory (a must denies, nothing is held), enforce (deny-class musts deny, the rest hold for a person). Escalations expire after 72 hours.
Findings
Severity on the wire is critical / warning / info, mirroring Verify's must / should / may. Policy ids are stable:
| Policy | Category | Fires when |
|---|---|---|
| plan.budget | budget | spend would exceed the plan budget (must) or pass 90% (should) |
| plan.reallocation | budget | one move above the reallocation threshold |
| plan.flight · plan.countries · plan.approved_sellers | plan | outside the flight, countries or seller list |
| authz.seller_not_authorized | authorization | the property's adagents.json does not list the seller |
| authz.not_reciprocated · authz.unverifiable | authorization | the seller's brand.json does not claim the property; or a document could not be read |
| quality.ivt_high · quality.sivt_elevated · quality.insufficient_data | inventory_quality | the property's ClearTrust score is in the risk or watch tier; or there is too little traffic to say |
| seller.blocked · seller.not_allowlisted · amount.max_per_check | account_policy | the buyer account's own rules |
| delivery.ivt_rate · delivery.pacing | measurement | measured invalid traffic above the limit; delivery past budget |
3. Measurement
An approved purchase creates a media buy in Verify and a scan in ClearTrust. The In-Ad tag for that scan goes in the creative. When ClearTrust provisions the scan at once, the tag is in ext.attest.measurement of the check answer; otherwise it appears on the plan's audit log and in the console as soon as it exists.
From then on Verify records, per day: visits, clean, invalid, general vs sophisticated invalid traffic, brand-safety and viewability flags, and ClearTrust's Traffic Quality Index. The GIVT/SIVT split is ClearTrust's threat category mapped to the MRC classes and is labelled as an approximation.
4. Delivery checks and outcomes
Sellers use the plan's atp_ token. Report acceptance and delivery:
report_plan_outcome {
"plan_id": "spring_awareness", "check_id": "chk_…", "idempotency_key": "…",
"outcome": "delivery",
"delivery": { "observation_id": "…", "source": "seller_statement_copy", "observed_at": "…",
"seller_statement_id": "…", "seller_statement_digest": "…",
"reporting_period": { "start": "…", "end": "…" }, "cumulative_spend": 120, "currency": "USD", "impressions": 48000 }
}The answer carries delivery_reconciliation_status: consistent, measurement_variance (reported and measured differ by more than 20%), or unmatched (nothing measured yet). A delivery-phase check_governance (phase: "delivery" with delivery_metrics) returns a hold when measured invalid traffic is above the account's limit.
5. Audit logs
get_plan_audit_logs { "plan_ids": ["spring_awareness"], "include_entries": true }Per plan: budget state (authorised, committed, net cost, remaining), governed actions, counts by verdict, escalations with their resolution, and with include_entries every check and outcome.
Signals
| Signal | Type | Value |
|---|---|---|
| attest_clean_inventory | binary | The property scores in the clean tier on ClearTrust traffic quality over the last 30 days: low invalid-traffic rate, little sophisticated IVT, no IP concentration. |
| attest_ivt_risk | numeric | A 0 to 1 risk score for the property, 1 being the worst, from ClearTrust trap hits weighted toward recent days. Use a threshold such as ivt_risk < 0.3. |
| attest_givt_sivt_profile | categorical | What kind of invalid traffic the property attracts: general (declared bots, data centres) or sophisticated (spoofing, hijacked devices), or both, or too little data. |
Activate to a sales agent: activate_signal with destinations: [{ type: "agent", agent_url }] returns a key/value activation. The sales agent resolves it per domain:
GET https://verify.cleartrust.cc/api/signals/lookup?domain=news.example
Authorization: Bearer <activation value>
→ { "signal": "attest_ivt_risk", "domain": "news.example", "value": 0.07, "tier": "clean", "score": 93, "total": 48210 }Discovery files
brand.json names the three agents on this host and their keys at jwks.json. adagents.json lists the property features Verify holds, so a buyer finding a governance agent for a property through property_features finds this one.
Internal MCP
ClearTrust staff and the other Attest apps use https://verify.cleartrust.cc/admin/mcp, an HQ-style discover/execute surface with a service key or a Central-minted key. It is not an AdCP endpoint. Console.