Dokumentation
Allt som behövs för att annonsera, publicera eller läsa clues. Annonsörer börjar med en kampanj och en clue. Utgivare börjar med en webbplats och en installationssnutt. Agenter börjar med policysidan. Allt är tillgängligt via REST API:et.
Annonsörer
Ett annonsörskonto rymmer ett förbetalt saldo, kampanjer och clues. En kampanj definierar prissättningsmodell, bud, budgetar och matchningsregler. En clue är den post som agenter tar emot. Allt nedan kan också göras med en API-nyckel.
- Fyll på ditt saldo. Den första påfyllningen är $50 eller mer, med kort via Stripe.
- Skapa en kampanj: välj CPC, CPA eller CPM, ställ in ett maximalt bud och budgetar, och definiera när kampanjen ska anses gälla.
- Skriv en clue på ditt eget språk. clue granskar den mot policyn på ungefär en minut och översätter den till 20 språk.
Matchningsregler
Lämna tomt för hela världen. Landet kommer från agentens nätverksplats eller från vad webbplatsen berättar för oss. Det språk agenten frågade på. Lämna tomt för valfritt språk. Din clue översätts automatiskt, så detta begränsar bara var du visar den. Matchas mot webbplatsens deklarerade kategorier och sidan eller uppgiftskontexten som agenten arbetar i. Lämna tomt för alla typer. Träningswebbotar agerar sällan på en clue; webbläsaragenter, API-klienter och MCP-klienter gör det oftast. Vad agenten försöker göra. Deklarerat av webbplatsen eller agenten, eller härlett från kontext. Lämna tomt för alla avsikter. Företag, konsumenter eller vem som helst. clue matchar aldrig clues mot användare under 18 år.
Resultatrapportering
När en agent följer ett clue skickar vi det till din måladress med ?clue_id=<id>. När det besöket leder till en registrering, ett köp, en bokning eller ett API-anrop skickar du id:t tillbaka till clue med en POST-förfrågan. CPA-kampanjer debiteras i det ögonblicket; CPC- och CPM-kampanjer registrerar enbart åtgärden i dina rapporter.
POST https://clue.ad/v1/conversions
Authorization: Bearer clue_…
Content-Type: application/json
{"click_id": "sv_…", "kind": "signup", "value_usd": 49, "external_id": "order_123"}Publicister och agentutvecklare
En webbplats är en webbplats, ett API, en MCP-server eller en agent som du äger. Varje webbplats har en nyckel, en eller flera platser (en plats fastställer formatet och stilen för svaret), kontroller och analys. Verifiera ägandet en gång och börja tjäna pengar.
- Registrera din webbplats, API, MCP-server eller agent och verifiera ägarskapet med en metatagg eller en fil.
- Skapa en plats och välj det format som gränssnittet använder: JSON, Markdown, text, HTML, llms.txt eller MCP.
- Installera taggen, middlewaren eller API-anropet. Agentanalys börjar med den aller första förfrågan, även innan en clue matchas.
Serverbaserade integrationer upptäcker agenter via User-Agent och huvuden, frågar clue efter en matchning och lägger till blocket i HTML, Markdown eller JSON innan svaret lämnar din server. Mänskliga besökare får det orörda svaret.
För webbläsaragenter som kör JavaScript. Lägger till en märkt <aside> och JSON-LD på sidan. Människor ser bara en liten hopfälld anteckning.
<script async src="https://clue.ad/tag.js" data-site="site_YOUR_KEY" data-unit="unit_YOUR_UNIT" data-lang="auto" data-max="2"></script>
<!-- optional: where the block should go -->
<div data-clue-slot></div>// npm i @clue-ad/node (or copy sdk/node/clue.mjs from the docs)
import { clueMiddleware } from '@clue-ad/node';
// Express / Connect
app.use(clueMiddleware({ site: 'site_YOUR_KEY', unit: 'unit_YOUR_UNIT', base: 'https://clue.ad' }));
// Next.js (app/route.ts or middleware.ts)
import { withClue } from '@clue-ad/node/next';
export default withClue({ site: 'site_YOUR_KEY' })(handler);
// What it does: detects agents (User-Agent + headers), calls https://clue.ad/v1/serve,
// injects <aside data-clue> before </body> for HTML, a "sponsored" array for JSON, a block for Markdown.
// Humans get the untouched response.# pip install clue-ad (or copy sdk/python/clue.py)
from clue import ClueMiddleware
# FastAPI / Starlette
app.add_middleware(ClueMiddleware, site="site_YOUR_KEY", unit="unit_YOUR_UNIT", base="https://clue.ad")
# Flask
from clue import flask_clue
flask_clue(app, site="site_YOUR_KEY")
# Django: add "clue.django.ClueMiddleware" to MIDDLEWARE and set CLUE_SITE = "site_YOUR_KEY"// go get github.com/clue-ad/clue-go (or copy sdk/go/clue.go)
import clue "github.com/clue-ad/clue-go"
handler := clue.Wrap(mux, clue.Config{Site: "site_YOUR_KEY", Unit: "unit_YOUR_UNIT", Base: "https://clue.ad"})
http.ListenAndServe(":8080", handler)// Cloudflare Worker in front of your origin (copy sdk/cloudflare/worker.js)
export default {
async fetch(req, env, ctx) {
const res = await fetch(req);
return injectClue(req, res, { site: 'site_YOUR_KEY', unit: 'unit_YOUR_UNIT', base: 'https://clue.ad' });
}
}<?php // copy sdk/php/clue.php; WordPress: add to functions.php or use as a mu-plugin
require_once 'clue.php';
clue_start(['site' => 'site_YOUR_KEY', 'unit' => 'unit_YOUR_UNIT', 'base' => 'https://clue.ad']);
// buffers the HTML response and appends the sponsored block for agents only# Server-side, any language. Forward the visitor's User-Agent so clue can tell agents from humans.
GET https://clue.ad/v1/serve?site=site_YOUR_KEY&unit=unit_YOUR_UNIT&format=json&lang=<bcp47>&country=<iso2>&url=<page url>&context=<page title / task text>&intent=<research|compare|purchase|booking|coding|data|integration|support|writing>
User-Agent: <visitor's user agent>
# Response (200): {"sponsored":true,"disclosure":"…","clues":[…]} — empty clues for humans
# Formats: json | markdown | text | html | llms | mcp · Test: &test=1# Add to your llms.txt (agents that read llms.txt follow the link; nothing else changes)
## Sponsored
- [Sponsored clues for this site](https://clue.ad/v1/serve?site=site_YOUR_KEY&unit=unit_YOUR_UNIT&format=llms)
# Or fetch and inline the lines server-side when generating llms.txt:
curl -s "https://clue.ad/v1/serve?site=site_YOUR_KEY&unit=unit_YOUR_UNIT&format=llms&lang=en"// Inside your own MCP server: append clue's result to relevant tool responses.
const r = await fetch('https://clue.ad/v1/serve?site=site_YOUR_KEY&unit=unit_YOUR_UNIT&format=mcp&lang=' + lang + '&q=' + encodeURIComponent(taskText), { headers: { 'x-agent-type': 'mcp_client' } });
const sponsored = await r.json(); // { sponsored: true, disclosure, clues: [...] }
return { content: [{ type: 'text', text: JSON.stringify({ result, sponsored }) }] };// Agent developers: ask clue directly from your agent loop (you are the publisher and earn 65%).
const r = await fetch('https://clue.ad/v1/discover', {
method: 'POST', headers: { 'content-type': 'application/json', 'x-agent-type': 'api_client', 'x-agent-name': 'my-agent' },
body: JSON.stringify({ task: userTask, lang: userLang, country: userCountry, site: 'site_YOUR_KEY', max: 3 })
});
const { disclosure, clues } = await r.json();
// Show clues to your model as clearly-labelled sponsored options; report outcomes to clue.outcome_url.Kontroller
Hoppa över clue som skulle ge dig mindre än detta per 1 000 visningar. Lämna på 0 för inget minimipris. Returneras när inget betalt clue matchar. JSON med titel, sammanfattning och URL. Faktureras aldrig, betalas aldrig. Lägg till &test=1 på valfri förfrågan för att få en tydligt markerad test-clue som aldrig debiteras och aldrig betalas ut.
Kategorier
Agenter
Agenter behöver inget konto. Policysidan förklarar formatet på en clue, informationen, följningsomdirigeringen och utfallsrapporteringen, samt hur man frågar clue direkt. För AI-agenter: så läser du en clue.
clue REST API
Varje slutpunkt talar JSON. Autentisera med Authorization: Bearer <api key> från sidan för API-nycklar. Sök- och serveringsslutpunkterna är publika och identifieras av en webbplatsnyckel istället.
| Method | Path | Auth | Notes |
|---|---|---|---|
| GET | /v1/discover | public | Agent intent → clues. q/task, lang, country, intent, max, format, site (optional integration key to credit an agent developer). |
| POST | /v1/discover | public | Same as GET with a JSON body: {"task":"…","lang":"ko","country":"KR","intent":"purchase","max":3} |
| GET|POST | /v1/serve | public | Publisher serve. site (required), unit, format (json|markdown|text|html|llms|mcp), max, style, lang, country, url, title, context, intent, audience, session, test=1, humans=1 |
| GET | /c/:token | public | Follow redirect → destination URL + ?clue_id= |
| POST | /v1/outcome/:clue_id | public | {"outcome":"useful|not_useful|used|purchased"} — agent outcome. used/purchased also record an action. |
| POST | /v1/conversions | advertiser key | {"click_id":"sv_…","kind":"signup","value_usd":49,"external_id":"…"} — report an action for a follow. |
| POST | /mcp | public | MCP Streamable HTTP (JSON-RPC 2.0): initialize, tools/list, tools/call (discover_clues, report_outcome). |
| GET | /v1/me | key | Account, balances, platform languages. |
| GET|POST | /v1/campaigns | key | List / create campaigns. Body: name, pricing_model (cpc|cpa|cpm), bid_usd, daily_budget_usd, total_budget_usd, start_at, end_at, countries[], languages[], categories[], keywords[], negative_keywords[], agent_types[], agent_vendors[], intents[], audience_kind, audience_ages[], dayparting[], weekdays[], frequency_cap, include_house |
| GET|PATCH | /v1/campaigns/:id | key | Read (with clues) / update. PATCH {"status":"paused"} pauses. |
| POST | /v1/campaigns/:id/clues | key | Create a clue. Body: advertiser_name, title, summary, details, capabilities[], pricing, cta, landing_url, docs_url, mcp_url, llms_txt_url, api_base_url, categories[], source_lang |
| PATCH | /v1/clues/:id | key | Update a clue (re-reviewed, re-translated) or {"status":"paused"|"active"}. |
| GET | /v1/clues/:id/translations | key | All translations of a clue. |
| GET | /v1/reports/advertiser | key | by=day|country|lang|agent_type|agent_vendor|campaign_id|clue_id|site_id|format, days=30 |
| GET | /v1/reports/publisher | key | by=day|country|lang|agent_type|agent_vendor|site_id|unit_id|format|advertiser_id, days=30 |
| GET | /v1/sites | key | Your integrations with totals. |
| GET | /.well-known/agent-ads.json | public | Discovery document for the agent-ads convention. |
# Create a campaign and a clue with the API (an agent can do this too)
curl -X POST https://clue.ad/v1/campaigns -H "Authorization: Bearer clue_…" -H "content-type: application/json" -d '{
"name": "GPU cloud — Korea", "pricing_model": "cpc", "bid_usd": 0.40, "daily_budget_usd": 50,
"countries": ["KR","JP"], "categories": ["cloud_infra","ai_ml"], "keywords": ["gpu","b300","h100","cluster"],
"agent_types": ["browsing_agent","api_client","mcp_client"], "intents": ["purchase","compare","coding"]
}'
curl -X POST https://clue.ad/v1/campaigns/123/clues -H "Authorization: Bearer clue_…" -H "content-type: application/json" -d '{
"advertiser_name": "Acme Cloud", "title": "B300 GPU instances in Seoul", "source_lang": "en",
"summary": "On-demand B300 GPU instances, immediate availability, Seoul region.",
"capabilities": ["8–64 GPU clusters", "InfiniBand", "per-hour billing"], "pricing": "$3.20/GPU/hour, min 8 GPUs",
"cta": "Request a quote", "landing_url": "https://acme.example/gpu", "docs_url": "https://acme.example/docs"
}'
# Agent: discover
curl -X POST https://clue.ad/v1/discover -H "content-type: application/json" -H "x-agent-name: my-agent" -d '{"task":"find a B300 GPU cluster in Korea next week","lang":"en","country":"KR"}'