Agent integration
When your agent fetches content from the web and uses it in a response, OpenAttribution tracks that usage so content owners get visibility. This page explains what to report, when, and how.
The short version
Your agent does two things that matter for attribution:
- Retrieves content - fetches a URL to read it
- Cites content - uses that content in a response to the user
Report both. Retrieval alone tells the publisher their content was accessed. Citation tells them it was actually used. The combination is what makes attribution meaningful.
Setup
1. Get an API key
Register your agent to get a platform API key. This key authenticates your telemetry submissions.
2. Discover the telemetry endpoint
Before fetching content from a domain, check for a /.well-known/openattribution file. If it exists, it tells you where to send telemetry for that domain.
curl -s https://example.com/.well-known/openattribution | jq .{
"openattribution": {
"version": "0.1",
"telemetry_endpoint": "https://api.openattribution.org/api/v1/telemetry",
"verification": "oa-verify=..."
}
}The telemetry_endpoint is where you send events. For most publishers this points to OA's server, but some may self-host.
Reporting events
A typical agent interaction produces this sequence:
User asks a question
-> Agent fetches content (content_retrieved)
-> Agent generates response (content_cited)
-> User sees response (content_displayed)
-> User clicks a source link (content_engaged)You can report events incrementally during a session or upload a complete session at the end. Both patterns are supported.
Option A: Incremental reporting
Start a session, report events as they happen, end the session.
curl -X POST https://api.openattribution.org/api/v1/telemetry/session/start \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"initiator_type": "user",
"agent_id": "your-agent-name"
}'{ "session_id": "550e8400-e29b-41d4-a716-446655440000" }curl -X POST https://api.openattribution.org/api/v1/telemetry/events \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"events": [
{
"type": "content_retrieved",
"timestamp": "2026-03-18T10:00:01Z",
"source_role": "agent",
"content_url": "https://example.com/article/best-headphones"
},
{
"type": "content_cited",
"timestamp": "2026-03-18T10:00:05Z",
"source_role": "agent",
"content_url": "https://example.com/article/best-headphones",
"data": {
"citation_type": "paraphrase",
"excerpt_tokens": 85,
"excerpt_chars": 340,
"position": "primary",
"media_type": "text"
}
}
]
}'curl -X POST https://api.openattribution.org/api/v1/telemetry/session/end \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"outcome": { "type": "browse" }
}'Option B: Bulk upload
Upload a complete session after it ends. Simpler if you're batch processing.
curl -X POST https://api.openattribution.org/api/v1/telemetry/session/bulk \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "your-agent-name",
"started_at": "2026-03-18T10:00:00Z",
"ended_at": "2026-03-18T10:05:00Z",
"events": [
{
"type": "content_retrieved",
"timestamp": "2026-03-18T10:00:01Z",
"source_role": "agent",
"content_url": "https://example.com/article/best-headphones"
},
{
"type": "content_cited",
"timestamp": "2026-03-18T10:00:05Z",
"source_role": "agent",
"content_url": "https://example.com/article/best-headphones",
"data": {
"citation_type": "paraphrase",
"excerpt_tokens": 85,
"position": "primary"
}
}
],
"outcome": { "type": "browse" }
}'Event types
These are the events an agent typically reports. All use source_role: "agent".
content_retrieved
Your agent fetched a URL. Report this for every URL you read, whether or not you end up using it. This is the base signal - it tells publishers their content was accessed.
| Field | Required | Description |
|---|---|---|
content_url | Yes | The URL you fetched |
data.media_type | No | text, image, video, or audio. Defaults to text |
content_cited
Your agent used the content in its response. This is the high-value signal - it connects retrieval to actual use.
| Field | Required | Description |
|---|---|---|
content_url | Yes | The URL you cited |
data.citation_type | No | direct_quote, paraphrase, reference, or contradiction |
data.excerpt_tokens | No | Token count of the excerpt used |
data.excerpt_chars | No | Character count of the excerpt used |
data.position | No | primary, supporting, or mentioned |
data.media_type | No | text, image, video, or audio |
data.content_hash | No | SHA-256 of the content you processed (sha256:{hex}). Useful for dispute resolution |
content_displayed
Content was shown to the user - in a card, sidebar, source list, or inline citation. Not all agents have a display surface, so this is optional.
content_engaged
The user interacted with cited content. The data.engagement_type field captures what happened:
| engagement_type | When to send |
|---|---|
link_click | User clicked a link to the source content |
expand | User expanded a citation preview or source card |
copy | User copied the cited text |
share | User shared the response or a specific citation |
Click tokens and landing page attribution
When your agent displays a link to source content and the user clicks it, you can pass session context through to the landing page. This lets the destination site (or their affiliate network) see which content influenced the visit - closing the loop between "agent cited this article" and "user landed here."
How it works
- Before displaying an outbound link, create a click token for the session
- Append the token to the URL as a
ctxquery parameter - When the user clicks, report a
content_engagedevent withlink_click - The landing page owner captures
ctxand looks up the session via the public API
curl -X POST https://api.openattribution.org/api/v1/telemetry/click-tokens \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"content_url": "https://retailer.com/headphones/sony-wh1000xm5"
}'{
"token": "ctx_abc123def456",
"session_id": "550e8400-...",
"content_url": "https://retailer.com/headphones/sony-wh1000xm5",
"expires_at": "2026-06-18T10:00:00Z"
}Append the token to the outbound URL:
https://retailer.com/headphones/sony-wh1000xm5?ctx=ctx_abc123def456The landing page owner (or their network) captures the ctx parameter and looks up the session context:
curl https://api.openattribution.org/api/v1/telemetry/ctx/ctx_abc123def456{
"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"
]
}Report the click
When the user clicks the link, report a content_engaged event so the publisher sees the clickthrough:
{
"type": "content_engaged",
"timestamp": "2026-03-18T10:01:00Z",
"source_role": "agent",
"content_url": "https://retailer.com/headphones/sony-wh1000xm5",
"data": {
"engagement_type": "link_click"
}
}The OA-Telemetry-ID header
When your agent fetches content over HTTP, include an OA-Telemetry-ID header with a UUID:
GET /article/best-headphones HTTP/1.1
Host: www.example.com
OA-Telemetry-ID: 550e8400-e29b-41d4-a716-446655440000Then include the same UUID as the oa_telemetry_id field on your content_retrieved event.
This enables cross-observer correlation. If the publisher's CDN or web server also reports the retrieval, both events share the same ID. A retrieval confirmed by both agent and publisher is a stronger signal than either alone.
{
"type": "content_retrieved",
"timestamp": "2026-03-18T10:00:01Z",
"source_role": "agent",
"oa_telemetry_id": "550e8400-e29b-41d4-a716-446655440000",
"content_url": "https://www.example.com/article/best-headphones"
}Session outcomes
When you end a session, include an outcome. This closes the attribution loop.
| Outcome | When |
|---|---|
browse | User read the response, no further action |
conversion | User completed a purchase or signup |
abandonment | User left mid-conversation |
For conversions, include the value:
{
"outcome": {
"type": "conversion",
"value_amount": 4999,
"currency": "USD"
}
}value_amount is in minor currency units - cents for USD, pence for GBP. So $49.99 = 4999.
What to report when
Start with retrieval and citation. These two events cover the core attribution signal. Add the rest as your integration matures.
| Priority | Events | What it enables |
|---|---|---|
| Start here | content_retrieved + content_cited | Publishers see which content is being used and how |
| Add next | content_displayed + content_engaged | Clickthrough rates, engagement metrics |
| If applicable | Session outcomes + OA-Telemetry-ID header | Full attribution loop, cross-observer corroboration |
Next steps
- Register your agent and get an API key
- API reference for full endpoint documentation
- Telemetry specification for the complete schema