|

API reference

The telemetry API has two sides: write endpoints for agents and platforms reporting events, and read endpoints for content owners querying their data.


Authentication

All authenticated endpoints use an API key in the X-API-Key header. There are two key types:

Key typePrefixUse case
Platformoat_pkAgents and platforms writing telemetry events
Publisheroat_pubContent owners querying their own telemetry data
bash
curl -H "X-API-Key: oat_pub_..." https://api.openattribution.org/api/v1/telemetry/publisher/summary

Publisher keys are scoped to specific domains. A key for wirecutter.com can only query data for that domain. No cross-publisher aggregation.


Base URL

EnvironmentURL
Productionhttps://api.openattribution.org/api/v1/telemetry
Local developmenthttp://localhost:8007/api/v1/telemetry

All endpoint paths below are relative to the base URL.


Publisher endpoints

Query telemetry data for your verified domains. Requires a publisher API key.

Summary

text
GET /publisher/summary

Aggregate metrics across your domains - total events, total sessions, breakdown by event type, and per-agent activity.

ParameterTypeDescription
sinceISO 8601Start of period (optional)
untilISO 8601End of period (optional)
domainstringFilter to a specific domain (optional)
response
{
  "publisher_id": "...",
  "publisher_name": "Wirecutter",
  "domains": ["wirecutter.com"],
  "total_events": 14720,
  "total_sessions": 3891,
  "events_by_type": [
    { "event_type": "content_retrieved", "count": 14720 }
  ],
  "agents": [
    { "platform_id": "openai", "agent_id": "chatgpt-browse", "event_count": 6200, "session_count": 1580 },
    { "platform_id": "anthropic", "agent_id": "claude-web", "event_count": 4100, "session_count": 1020 },
    { "platform_id": "perplexity", "agent_id": "perplexity", "event_count": 4420, "session_count": 1291 }
  ],
  "period_start": "2026-03-01T00:00:00Z",
  "period_end": null
}

Events

text
GET /publisher/events

Paginated list of individual events for your domains.

ParameterTypeDescription
sinceISO 8601Start of period (optional)
untilISO 8601End of period (optional)
domainstringFilter to a specific domain (optional)
limitintegerPage size (default: 100)
offsetintegerOffset for pagination (default: 0)
response
{
  "items": [
    {
      "event_id": "550e8400-...",
      "session_id": "7c9e6679-...",
      "event_type": "content_retrieved",
      "content_url": "https://wirecutter.com/reviews/best-headphones",
      "event_timestamp": "2026-03-18T10:00:00Z",
      "event_data": { "user_agent": "ClaudeBot/1.0" },
      "platform_id": "anthropic",
      "agent_id": "claude-web"
    }
  ],
  "total": 14720,
  "limit": 100,
  "offset": 0
}

URLs

text
GET /publisher/urls

Per-URL metrics - which content is being retrieved most, by how many sessions, and when it was last seen.

ParameterTypeDescription
since, until, domain-Same as above
limit, offsetintegerPagination (default: limit 20, offset 0)
response
{
  "items": [
    {
      "content_url": "https://wirecutter.com/reviews/best-headphones",
      "total_events": 842,
      "unique_sessions": 391,
      "event_types": [
        { "event_type": "content_retrieved", "count": 842 }
      ],
      "last_seen": "2026-03-18T14:22:00Z"
    }
  ],
  "total": 156,
  "limit": 20,
  "offset": 0
}

Delegated access

Content owners can grant measurement partners (affiliate networks, dashboard tools, analytics platforms) read access to their telemetry data. Partners query the same publisher endpoints, adding the delegated_from parameter.

Querying as a delegate

Append delegated_from to any publisher GET endpoint with the content owner's organisation ID:

text
GET /publisher/summary?delegated_from={grantor_org_id}&since=2026-03-01

The gateway checks for an active delegation from the content owner to your organisation. If valid, you receive their telemetry data exactly as they would see it. If not, you get a 403.

Managing delegations

Content owners manage delegations via the identity API:

EndpointDescription
GET /identity/delegationsList active delegations. Optional ?role=grantor|grantee
POST /identity/delegationsGrant access to a partner. Body: grantee_org_id, optional scopes
DELETE /identity/delegations/{id}Revoke a delegation. Only the content owner (grantor) can revoke.
Dashboard
Content owners can also manage delegations from the Measurement partners page in the OA dashboard - no API calls needed.

Click tokens

When an agent generates an outbound link, it can create a click token that ties the click back to the full session - which content was retrieved, cited, and by which agent.

Create a click token

text
POST /click-tokens

Requires a platform API key.

request
{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "content_url": "https://retailer.com/headphones/sony-wh1000xm5"
}
response
{
  "token": "ctx_abc123def456",
  "session_id": "550e8400-...",
  "content_url": "https://retailer.com/headphones/sony-wh1000xm5",
  "expires_at": "2026-06-18T10:00:00Z"
}

The agent appends the token to the outbound URL:

text
https://retailer.com/headphones/sony-wh1000xm5?ctx=ctx_abc123def456

Look up a click token

text
GET /ctx/{token}

Public endpoint - no authentication required. Networks and retailers capture the ctx parameter from the landing page URL and look up the session context.

response
{
  "session_id": "550e8400-...",
  "started_at": "2026-03-18T10:00:00Z",
  "click_content_url": "https://retailer.com/headphones/sony-wh1000xm5",
  "content_urls_cited": [
    "https://wirecutter.com/reviews/best-headphones",
    "https://techradar.com/best/wireless-headphones"
  ],
  "content_urls_retrieved": [
    "https://wirecutter.com/reviews/best-headphones",
    "https://techradar.com/best/wireless-headphones",
    "https://rtings.com/headphones/reviews/sony/wh-1000xm5"
  ]
}
Token expiry
Click tokens expire after 90 days.

Domain resolution

text
GET /resolve?domain=wirecutter.com

Check whether a domain maps to a registered content owner. No authentication required. Accepts either a domain or a url parameter (the domain is extracted from the URL).

response
{
  "domain": "wirecutter.com",
  "handled": true,
  "publisher": {
    "id": "...",
    "name": "Wirecutter"
  }
}

If the domain is not registered, handled is false and publisher is null.


Write endpoints

For agents and platforms reporting telemetry. Requires a platform API key.

Start a session

text
POST /session/start
request
{
  "initiator_type": "user",
  "agent_id": "shopping-assistant",
  "external_session_id": "ext-123",
  "prior_session_ids": ["previous-session-uuid"]
}
response
{
  "session_id": "550e8400-e29b-41d4-a716-446655440000"
}
FieldRequiredDescription
initiator_typeNo"user" or "agent" (default: "user")
agent_idNoIdentifier for the responding agent
manifest_refNoAIMS manifest reference for the agent
content_scopeNoOpaque identifier for content access context
external_session_idNoYour own session identifier
prior_session_idsNoPrevious session UUIDs for multi-session attribution

Record events

text
POST /events
request
{
  "session_id": "550e8400-...",
  "events": [
    {
      "id": "event-uuid-1",
      "type": "content_retrieved",
      "timestamp": "2026-03-18T10:00:00Z",
      "source_role": "agent",
      "content_url": "https://wirecutter.com/reviews/best-headphones",
      "oa_telemetry_id": "telemetry-correlation-uuid"
    },
    {
      "id": "event-uuid-2",
      "type": "content_cited",
      "timestamp": "2026-03-18T10:00:05Z",
      "source_role": "agent",
      "content_url": "https://wirecutter.com/reviews/best-headphones"
    }
  ]
}
response
{
  "status": "ok",
  "events_created": 2
}

End a session

text
POST /session/end
request
{
  "session_id": "550e8400-...",
  "outcome": {
    "type": "conversion",
    "value_amount": 34900,
    "currency": "USD"
  }
}

The value_amount is in minor currency units (cents for USD). Outcome types: "conversion", "abandonment", "browse".

Bulk session upload

text
POST /session/bulk

Upload a complete session - start, events, and outcome - in a single request. Useful for batch reporting or replaying historical data.

request
{
  "session_id": "550e8400-...",
  "agent_id": "shopping-assistant",
  "started_at": "2026-03-18T10:00:00Z",
  "ended_at": "2026-03-18T10:05:00Z",
  "events": [
    {
      "id": "event-uuid-1",
      "type": "content_retrieved",
      "timestamp": "2026-03-18T10:00:00Z",
      "source_role": "agent",
      "content_url": "https://wirecutter.com/reviews/best-headphones"
    }
  ],
  "outcome": {
    "type": "conversion",
    "value_amount": 34900,
    "currency": "USD"
  }
}
response
{
  "session_id": "550e8400-...",
  "events_created": 1,
  "outcome_recorded": true
}

Event types

TypeWhenSource role
content_retrievedContent fetched from sourceorigin, edge, index, or agent
content_citedContent referenced in an agent's responseagent
content_displayedContent shown to user in a card or sidebaragent
content_engagedUser interacted with cited contentagent
turn_startedUser initiated a conversation turnagent
turn_completedAgent finished respondingagent
checkout_completedPurchase completed with valueagent

Source roles

The source_role field identifies who is reporting the event. Multiple observers can report the same retrieval from different vantage points.

RoleReporter
originContent owner's web server (e.g. WordPress plugin)
edgeCDN or edge network (Cloudflare, Fastly, etc.)
indexContent marketplace or licensed content repository
agentThe AI agent itself

Health

EndpointAuthPurpose
GET /healthNoneReturns {"status": "ok"}
GET /readyNoneDatabase connectivity check