@the_ro_show/agent-ads-sdk 0.6.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +318 -467
- package/dist/index.d.mts +218 -7
- package/dist/index.d.ts +218 -7
- package/dist/index.js +278 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +278 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/SECURITY.md +0 -376
- package/SIMPLE_INTEGRATION_GUIDE.md +0 -319
package/README.md
CHANGED
|
@@ -1,611 +1,462 @@
|
|
|
1
|
-
# AttentionMarket
|
|
1
|
+
# AttentionMarket
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@the_ro_show/agent-ads-sdk)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
|
-
[](https://www.typescriptlang.org/)
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
**The ad exchange for the AI era. Monetize your chatbot, AI assistant, or AI agent with one API call.**
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
- **Simple integration** - One API call to get ads
|
|
8
|
+
Works on every platform — iOS, Android, Web, Voice, Discord, WhatsApp, Node.js, Python, and anything else that can make an HTTP request.
|
|
11
9
|
|
|
12
10
|
---
|
|
13
11
|
|
|
14
|
-
##
|
|
12
|
+
## Two Ways To Earn
|
|
15
13
|
|
|
16
|
-
### 1.
|
|
14
|
+
### 1. Show ads in your chatbot or AI assistant
|
|
15
|
+
Your app has conversations. Users ask questions. You send us the context, we return a relevant ad, you earn $5–$150 when the user clicks.
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- Live key: `am_live_...`
|
|
21
|
-
- Agent ID
|
|
17
|
+
### 2. List your AI agent on the exchange
|
|
18
|
+
You built a specialized AI agent. Other AI agents need what you offer. List it on AttentionMarket and earn every time another agent calls yours.
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
npm install @the_ro_show/agent-ads-sdk
|
|
27
|
-
```
|
|
20
|
+
---
|
|
28
21
|
|
|
29
|
-
|
|
22
|
+
## Quick Start — 30 Seconds
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
import { AttentionMarketClient } from '@the_ro_show/agent-ads-sdk';
|
|
33
|
-
|
|
34
|
-
const client = new AttentionMarketClient({
|
|
35
|
-
apiKey: process.env.ATTENTIONMARKET_API_KEY,
|
|
36
|
-
agentId: 'your_agent_id'
|
|
37
|
-
});
|
|
24
|
+
Get your API keys at [api.attentionmarket.ai](https://api.attentionmarket.ai), then:
|
|
38
25
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
26
|
+
```bash
|
|
27
|
+
curl -X POST https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/decide \
|
|
28
|
+
-H "X-AM-API-Key: am_live_YOUR_KEY" \
|
|
29
|
+
-H "Content-Type: application/json" \
|
|
30
|
+
-d '{"context": "I need car insurance"}'
|
|
31
|
+
```
|
|
43
32
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
33
|
+
**Response:**
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"status": "filled",
|
|
37
|
+
"units": [{
|
|
38
|
+
"suggestion": {
|
|
39
|
+
"title": "Get 20% off car insurance",
|
|
40
|
+
"body": "Compare quotes in minutes",
|
|
41
|
+
"cta": "Get a Quote",
|
|
42
|
+
"tracking_url": "https://..."
|
|
43
|
+
}
|
|
44
|
+
}]
|
|
48
45
|
}
|
|
49
46
|
```
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
## How It Works
|
|
54
|
-
|
|
55
|
-
1. User interacts with your agent: `"I need help with estate planning"`
|
|
56
|
-
2. You pass the message to `decideFromContext()`
|
|
57
|
-
3. We return a matching ad from our network
|
|
58
|
-
4. You display it and track clicks to earn revenue
|
|
59
|
-
|
|
60
|
-
The API handles intent detection and ad matching automatically.
|
|
48
|
+
Show `suggestion.title` and `suggestion.body` to your user. When they click, send them to `tracking_url`. That's it — you get paid automatically.
|
|
61
49
|
|
|
62
50
|
---
|
|
63
51
|
|
|
64
|
-
##
|
|
52
|
+
## 🚨 CRITICAL: Impression Tracking Required (v0.9.0+)
|
|
65
53
|
|
|
66
|
-
|
|
54
|
+
**As of v0.9.0, impression tracking is REQUIRED to earn revenue from clicks.**
|
|
67
55
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
apiKey: process.env.ATTENTIONMARKET_API_KEY,
|
|
73
|
-
agentId: 'your_agent_id'
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
async function handleUserMessage(userMessage: string) {
|
|
77
|
-
const ad = await client.decideFromContext({ userMessage });
|
|
78
|
-
|
|
79
|
-
if (!ad) {
|
|
80
|
-
return null; // No ads available
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Display ad (you can customize this)
|
|
84
|
-
const displayMessage = `\n[Sponsored] ${ad.disclosure.sponsor_name}\n${ad.creative.title}\n${ad.creative.body}\n${ad.creative.cta}\n`;
|
|
85
|
-
console.log(displayMessage);
|
|
86
|
-
|
|
87
|
-
// Track click when user clicks
|
|
88
|
-
await client.trackClick({
|
|
89
|
-
agent_id: 'your_agent_id',
|
|
90
|
-
request_id: ad.request_id,
|
|
91
|
-
decision_id: ad.offer_id,
|
|
92
|
-
unit_id: ad.offer_id,
|
|
93
|
-
tracking_token: ad.tracking_token,
|
|
94
|
-
href: ad.click_url,
|
|
95
|
-
click_context: displayMessage // What was actually shown to user
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
return ad;
|
|
99
|
-
}
|
|
100
|
-
```
|
|
56
|
+
When you show an ad to a user, you must track an impression. Clicks without prior impressions will:
|
|
57
|
+
- ✅ Still redirect the user to the advertiser (good UX)
|
|
58
|
+
- ❌ NOT charge the advertiser
|
|
59
|
+
- ❌ NOT credit your earnings
|
|
101
60
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
## API Reference
|
|
61
|
+
### Why This Matters
|
|
105
62
|
|
|
106
|
-
|
|
63
|
+
This prevents developers from filtering ads client-side and still earning revenue from clicks. It ensures clean data and accurate quality metrics for the advertising exchange.
|
|
107
64
|
|
|
108
|
-
|
|
65
|
+
### Using `decideFromContext()` (Recommended)
|
|
109
66
|
|
|
110
|
-
|
|
67
|
+
**Good news:** If you're using the SDK's `decideFromContext()` method, impressions are tracked **automatically**. No changes needed.
|
|
111
68
|
|
|
112
69
|
```typescript
|
|
70
|
+
// Impressions tracked automatically ✅
|
|
113
71
|
const ad = await client.decideFromContext({
|
|
114
|
-
userMessage: "I need
|
|
115
|
-
|
|
116
|
-
context: { geo: { city: 'NYC', country: 'US' } } // Optional
|
|
72
|
+
userMessage: "I need car insurance",
|
|
73
|
+
placement: 'sponsored_suggestion'
|
|
117
74
|
});
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
Returns ad with:
|
|
121
|
-
- `creative.title` - Ad headline
|
|
122
|
-
- `creative.body` - Ad description
|
|
123
|
-
- `creative.cta` - Call to action
|
|
124
|
-
- `click_url` - URL to open on click
|
|
125
|
-
- `tracking_token` - Required for revenue tracking
|
|
126
|
-
- `disclosure` - Sponsor information
|
|
127
75
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
Records user clicks for revenue attribution. Call this when a user clicks an ad. Handles deduplication and retries automatically.
|
|
133
|
-
|
|
134
|
-
**Required:** `click_context` - The actual message shown to the user. This helps optimize ad creative based on what converts.
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
await client.trackClick({
|
|
138
|
-
agent_id: 'your_agent_id',
|
|
139
|
-
request_id: ad.request_id,
|
|
140
|
-
decision_id: ad.offer_id,
|
|
141
|
-
unit_id: ad.offer_id,
|
|
142
|
-
tracking_token: ad.tracking_token,
|
|
143
|
-
href: ad.click_url,
|
|
144
|
-
click_context: "The message shown to user that they clicked"
|
|
145
|
-
});
|
|
76
|
+
if (ad) {
|
|
77
|
+
// Show ad to user
|
|
78
|
+
displayAd(ad);
|
|
79
|
+
}
|
|
146
80
|
```
|
|
147
81
|
|
|
148
|
-
###
|
|
82
|
+
### Using Raw HTTP or `decide()` (Manual Tracking Required)
|
|
149
83
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
Mock client for testing without API calls. Simulates latency and fill rate behavior.
|
|
84
|
+
If you're making raw HTTP calls or using the low-level `decide()` method, you **must manually track impressions**:
|
|
153
85
|
|
|
154
86
|
```typescript
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
verbose: true // Log what's happening
|
|
87
|
+
// Step 1: Get ad
|
|
88
|
+
const response = await fetch('https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/decide', {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
headers: { 'X-AM-API-Key': 'am_live_...' },
|
|
91
|
+
body: JSON.stringify({ context: 'I need car insurance' })
|
|
161
92
|
});
|
|
93
|
+
const data = await response.json();
|
|
94
|
+
|
|
95
|
+
if (data.status === 'filled') {
|
|
96
|
+
const ad = data.units[0];
|
|
97
|
+
|
|
98
|
+
// Step 2: Track impression IMMEDIATELY when showing ad ✅
|
|
99
|
+
await fetch('https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/event', {
|
|
100
|
+
method: 'POST',
|
|
101
|
+
headers: { 'X-AM-API-Key': 'am_live_...' },
|
|
102
|
+
body: JSON.stringify({
|
|
103
|
+
event_id: `evt_${crypto.randomUUID()}`,
|
|
104
|
+
event_type: 'impression',
|
|
105
|
+
occurred_at: new Date().toISOString(),
|
|
106
|
+
agent_id: 'YOUR_AGENT_ID',
|
|
107
|
+
unit_id: ad.unit_id,
|
|
108
|
+
tracking_token: ad.tracking.token
|
|
109
|
+
})
|
|
110
|
+
});
|
|
162
111
|
|
|
163
|
-
//
|
|
164
|
-
|
|
112
|
+
// Step 3: Now safe to show ad and earn from clicks
|
|
113
|
+
displayAd(ad);
|
|
114
|
+
}
|
|
165
115
|
```
|
|
166
116
|
|
|
167
117
|
---
|
|
168
118
|
|
|
169
|
-
##
|
|
170
|
-
|
|
171
|
-
<details>
|
|
172
|
-
<summary><strong>Click to view advanced APIs (most developers don't need these)</strong></summary>
|
|
119
|
+
## Use Case 1: Monetize Your Chatbot or AI Assistant
|
|
173
120
|
|
|
174
|
-
|
|
121
|
+
Any app with conversations can earn revenue. Users ask questions with commercial intent every day — insurance, legal help, home services, travel, weddings, software. When they do, you can surface a relevant offer and earn.
|
|
175
122
|
|
|
176
|
-
|
|
123
|
+
**Platforms this works on:**
|
|
177
124
|
|
|
178
|
-
|
|
125
|
+
| Type | Examples |
|
|
126
|
+
|------|---------|
|
|
127
|
+
| **AI Assistants** | Mobile AI apps, productivity tools, personal assistants |
|
|
128
|
+
| **Chatbots** | Website chat, customer service bots, FAQ bots |
|
|
129
|
+
| **Messaging Bots** | WhatsApp, Discord, Telegram, Slack |
|
|
130
|
+
| **Voice Assistants** | Alexa Skills, Google Actions, voice apps |
|
|
131
|
+
| **AI Companions** | Coaching bots, tutors, entertainment assistants |
|
|
179
132
|
|
|
180
|
-
|
|
181
|
-
When you know the exact category, use manual taxonomy matching for deterministic results.
|
|
133
|
+
### How It Works
|
|
182
134
|
|
|
183
|
-
```typescript
|
|
184
|
-
const decision = await client.decide({
|
|
185
|
-
request_id: crypto.randomUUID(),
|
|
186
|
-
agent_id: 'your_agent_id',
|
|
187
|
-
placement: { type: 'sponsored_suggestion' },
|
|
188
|
-
opportunity: {
|
|
189
|
-
intent: { taxonomy: 'insurance.auto.full_coverage.quote' },
|
|
190
|
-
context: { country: 'US', language: 'en', platform: 'web' }
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
135
|
```
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
### 🌐 Intenture Network APIs (Agent-to-Agent)
|
|
200
|
-
|
|
201
|
-
#### `requestOffer()` - Intent-key based matching for high confidence scenarios
|
|
202
|
-
When you KNOW what the user wants (they said "order coffee" or "book lawyer"), use intent-keys like `coffee.purchase.delivery` for deterministic matching. Enables agent-to-agent coordination and revenue sharing.
|
|
203
|
-
|
|
204
|
-
```typescript
|
|
205
|
-
const offer = await client.requestOffer({
|
|
206
|
-
placementId: 'order_card',
|
|
207
|
-
intentKey: 'coffee.purchase.delivery',
|
|
208
|
-
context: { geo: { city: 'SF', country: 'US' } }
|
|
209
|
-
});
|
|
136
|
+
User sends message → You call our API with context → We return a relevant ad
|
|
137
|
+
→ You show it → User clicks → You earn $5–$150
|
|
210
138
|
```
|
|
211
139
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
140
|
+
### Platform Examples
|
|
141
|
+
|
|
142
|
+
**iOS (Swift)** — drop this into your Xcode project:
|
|
143
|
+
```swift
|
|
144
|
+
// Initialize once
|
|
145
|
+
let client = AttentionMarketClient(
|
|
146
|
+
apiKey: "am_live_YOUR_KEY",
|
|
147
|
+
agentId: "agt_YOUR_ID"
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
// Call after your AI responds
|
|
151
|
+
if let ad = await client.getAd(for: userMessage) {
|
|
152
|
+
showAdInChat(
|
|
153
|
+
title: ad.suggestion.title,
|
|
154
|
+
body: ad.suggestion.body,
|
|
155
|
+
cta: ad.suggestion.cta,
|
|
156
|
+
url: ad.suggestion.trackingUrl
|
|
157
|
+
)
|
|
158
|
+
}
|
|
222
159
|
```
|
|
160
|
+
[Full iOS example →](./examples/ios/AttentionMarketClient.swift)
|
|
223
161
|
|
|
224
|
-
|
|
225
|
-
If another agent sends users to you, include their agent_id to split revenue (0-50%). Currently in preview mode (logs only) - payouts activate Q2 2026. Think affiliate marketing for AI agents.
|
|
162
|
+
---
|
|
226
163
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
164
|
+
**Android (Kotlin)**:
|
|
165
|
+
```kotlin
|
|
166
|
+
val client = AttentionMarketClient(
|
|
167
|
+
apiKey = "am_live_YOUR_KEY",
|
|
168
|
+
agentId = "agt_YOUR_ID"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
client.getAd(context = userMessage)?.let { ad ->
|
|
172
|
+
showAdInChat(
|
|
173
|
+
title = ad.suggestion.title,
|
|
174
|
+
body = ad.suggestion.body,
|
|
175
|
+
url = ad.suggestion.trackingUrl
|
|
176
|
+
)
|
|
177
|
+
}
|
|
234
178
|
```
|
|
179
|
+
[Full Android example →](./examples/android/AttentionMarketClient.kt)
|
|
235
180
|
|
|
236
181
|
---
|
|
237
182
|
|
|
238
|
-
|
|
183
|
+
**Web (JavaScript)** — plain fetch, no dependencies:
|
|
184
|
+
```javascript
|
|
185
|
+
const response = await fetch('https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/decide', {
|
|
186
|
+
method: 'POST',
|
|
187
|
+
headers: {
|
|
188
|
+
'X-AM-API-Key': 'am_live_YOUR_KEY',
|
|
189
|
+
'Content-Type': 'application/json'
|
|
190
|
+
},
|
|
191
|
+
body: JSON.stringify({ context: userMessage })
|
|
192
|
+
});
|
|
239
193
|
|
|
240
|
-
|
|
241
|
-
Analyzes queries to determine if they're researching ("what is X?"), comparing ("X vs Y"), getting quotes ("how much?"), or ready to buy ("I want X"). Returns 'research', 'compare', 'quote', 'apply', 'support', or 'other'.
|
|
194
|
+
const data = await response.json();
|
|
242
195
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
detectIntent("I want to buy car insurance") // → 'apply'
|
|
196
|
+
if (data.status === 'filled') {
|
|
197
|
+
const ad = data.units[0];
|
|
198
|
+
showAdInChat(ad.suggestion.title, ad.suggestion.body, ad.suggestion.tracking_url);
|
|
199
|
+
}
|
|
248
200
|
```
|
|
201
|
+
[Full Web example →](./examples/web/attentionmarket.js)
|
|
249
202
|
|
|
250
|
-
|
|
251
|
-
Constructs valid taxonomies like "insurance.auto.full_coverage.quote" with validation. Pass vertical, category, subcategory, and intent - it handles the formatting and catches errors.
|
|
203
|
+
---
|
|
252
204
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
205
|
+
**Node.js (optional SDK)**:
|
|
206
|
+
```bash
|
|
207
|
+
npm install @the_ro_show/agent-ads-sdk
|
|
256
208
|
```
|
|
209
|
+
```javascript
|
|
210
|
+
import { AttentionMarketClient } from '@the_ro_show/agent-ads-sdk';
|
|
257
211
|
|
|
258
|
-
|
|
259
|
-
|
|
212
|
+
const client = new AttentionMarketClient({
|
|
213
|
+
apiKey: process.env.ATTENTIONMARKET_API_KEY,
|
|
214
|
+
agentId: process.env.ATTENTIONMARKET_AGENT_ID
|
|
215
|
+
});
|
|
260
216
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
// → ['legal.family.divorce.consultation', 'legal.family.custody.consultation']
|
|
217
|
+
const ad = await client.decideFromContext({ userMessage });
|
|
218
|
+
if (ad) console.log(ad.creative.title, ad.click_url);
|
|
264
219
|
```
|
|
265
220
|
|
|
266
|
-
#### Taxonomy Utilities
|
|
267
|
-
- `isValidTaxonomy(taxonomy)` - Validate taxonomy format
|
|
268
|
-
- `parseTaxonomy(taxonomy)` - Parse taxonomy into components
|
|
269
|
-
- `getBaseTaxonomy(taxonomy)` - Get taxonomy without intent
|
|
270
|
-
- `matchesTaxonomy(tax1, tax2)` - Check if taxonomies match
|
|
271
|
-
- `getVertical(taxonomy)` - Extract industry vertical
|
|
272
|
-
|
|
273
221
|
---
|
|
274
222
|
|
|
275
|
-
|
|
223
|
+
## Use Case 2: List Your AI Agent on the Exchange
|
|
276
224
|
|
|
277
|
-
|
|
278
|
-
Transforms sponsored suggestions into conversational responses that feel native to your agent. Handles disclosure labels, CTA integration, and tone matching automatically.
|
|
225
|
+
You built a specialized AI agent — a legal document drafter, a wedding photographer booker, a travel planner, a code reviewer. Other AI assistants encounter users who need exactly what you do every day. List your agent on AttentionMarket and earn every time another agent calls yours.
|
|
279
226
|
|
|
280
|
-
|
|
281
|
-
const formatted = formatNatural(ad, {
|
|
282
|
-
tone: 'friendly',
|
|
283
|
-
includeDisclosure: true
|
|
284
|
-
});
|
|
285
|
-
// → "I found a great option for you! [Sponsored: Lemonade]..."
|
|
286
|
-
```
|
|
227
|
+
**This is the ad exchange for the agentic world.** Instead of humans clicking ads, AI agents discover and call specialized agents. You pay to be discovered. You earn when your agent gets used.
|
|
287
228
|
|
|
288
|
-
|
|
289
|
-
Weaves ads into your agent's response as natural mentions. Like "Btw, Lemonade offers great rates for new drivers [Sponsored]". Less intrusive than separate ad blocks.
|
|
229
|
+
### How It Works
|
|
290
230
|
|
|
291
|
-
```typescript
|
|
292
|
-
const mention = formatInlineMention(ad);
|
|
293
|
-
// → "Btw, Lemonade offers 20% off for new drivers [Sponsored]"
|
|
294
231
|
```
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
const fits = validateAdFits(ad, conversationContext);
|
|
301
|
-
if (fits) {
|
|
302
|
-
// Show the ad
|
|
303
|
-
}
|
|
232
|
+
General assistant encounters a task it can't handle well
|
|
233
|
+
→ Calls AttentionMarket with context + response_type: "agent"
|
|
234
|
+
→ Exchange returns the best specialized agent for that task
|
|
235
|
+
→ General assistant calls your agent
|
|
236
|
+
→ You earn per call
|
|
304
237
|
```
|
|
305
238
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
### 📊 Event Tracking
|
|
239
|
+
### Example
|
|
309
240
|
|
|
310
|
-
|
|
311
|
-
Record that an ad was shown to a user. Required for billing and analytics. Include the unit_id and tracking token from the ad response.
|
|
241
|
+
**Developer A** built a general wedding planning AI assistant. A user asks: *"Can you find me a photographer in Austin under $3,000?"*
|
|
312
242
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
243
|
+
Developer A's assistant calls AttentionMarket:
|
|
244
|
+
```bash
|
|
245
|
+
curl -X POST https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/decide \
|
|
246
|
+
-H "X-AM-API-Key: am_live_DEV_A_KEY" \
|
|
247
|
+
-H "Content-Type: application/json" \
|
|
248
|
+
-d '{
|
|
249
|
+
"context": "User needs a wedding photographer in Austin under $3,000",
|
|
250
|
+
"response_type": "agent"
|
|
251
|
+
}'
|
|
321
252
|
```
|
|
322
253
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
254
|
+
**AttentionMarket returns Developer B's agent:**
|
|
255
|
+
```json
|
|
256
|
+
{
|
|
257
|
+
"status": "filled",
|
|
258
|
+
"units": [{
|
|
259
|
+
"agent_name": "WeddingPhoto AI",
|
|
260
|
+
"capability": "Book wedding photographers by location and budget",
|
|
261
|
+
"endpoint": "https://weddingphoto.ai/api/v1",
|
|
262
|
+
"input_description": "Send: location (string), budget (number), date (string)",
|
|
263
|
+
"output_description": "Returns: photographer name, price, booking URL",
|
|
264
|
+
"tracking": {
|
|
265
|
+
"call_url": "https://.../track-call/token"
|
|
266
|
+
}
|
|
267
|
+
}]
|
|
268
|
+
}
|
|
338
269
|
```
|
|
339
270
|
|
|
340
|
-
|
|
271
|
+
**Developer A** calls WeddingPhoto AI, gets a result, passes it back to the user.
|
|
272
|
+
**Developer B** earns per call. **Developer A** earns a routing fee.
|
|
341
273
|
|
|
342
|
-
###
|
|
274
|
+
### List Your Agent
|
|
343
275
|
|
|
344
|
-
|
|
345
|
-
Helper to construct the opportunity payload for decide() calls. Handles defaults and validation.
|
|
276
|
+
Sign up as an advertiser at [api.attentionmarket.ai](https://api.attentionmarket.ai) and create an **Agent Ad** campaign:
|
|
346
277
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
278
|
+
| Field | Description |
|
|
279
|
+
|-------|-------------|
|
|
280
|
+
| Agent Name | Display name (e.g. "WeddingPhoto AI") |
|
|
281
|
+
| What does your agent do? | Natural language capability description — used for matching |
|
|
282
|
+
| Endpoint URL | Where calling agents send requests |
|
|
283
|
+
| What to send | Input format description |
|
|
284
|
+
| What you return | Output format description |
|
|
285
|
+
| Bid per call | What you pay each time your agent is called |
|
|
353
286
|
|
|
354
|
-
|
|
355
|
-
- `escapeHTML(text)` - Sanitize ad content before rendering to prevent XSS attacks
|
|
356
|
-
- `sanitizeURL(url)` - Validate and sanitize URLs before opening
|
|
287
|
+
**Matching is semantic** — describe your agent clearly in plain English and we handle the rest.
|
|
357
288
|
|
|
358
|
-
|
|
289
|
+
---
|
|
359
290
|
|
|
360
|
-
|
|
361
|
-
- `generateUUID()` - Create unique request IDs (crypto-secure randomness)
|
|
362
|
-
- `generateTimestamp()` - Generate timestamps that match our API requirements
|
|
291
|
+
## Revenue Model
|
|
363
292
|
|
|
364
|
-
|
|
293
|
+
### As a Developer (showing ads or routing to agents)
|
|
365
294
|
|
|
366
|
-
|
|
295
|
+
- **70% revenue share** on every click or agent call you facilitate
|
|
296
|
+
- Earn $5–$150 per click for ads
|
|
297
|
+
- Earn a routing fee per agent-to-agent call
|
|
298
|
+
- Monthly payouts via Stripe (minimum $100 balance)
|
|
299
|
+
- Free to integrate — no setup fees, no monthly costs
|
|
367
300
|
|
|
368
|
-
|
|
369
|
-
Drop-in replacement that returns fake ads for testing. Simulates latency, errors, and no-fill scenarios. Perfect for unit tests and local development.
|
|
301
|
+
**Example earnings:**
|
|
370
302
|
|
|
371
|
-
|
|
372
|
-
|
|
303
|
+
| Monthly clicks/calls | Avg payout | Monthly revenue |
|
|
304
|
+
|---------------------|------------|-----------------|
|
|
305
|
+
| 50 | $50 | $2,500 |
|
|
306
|
+
| 200 | $50 | $10,000 |
|
|
307
|
+
| 1,000 | $50 | $50,000 |
|
|
373
308
|
|
|
374
|
-
|
|
375
|
-
fillRate: 1.0, // Always return ads
|
|
376
|
-
latencyMs: 100, // Simulate API latency
|
|
377
|
-
verbose: true // Log activity
|
|
378
|
-
});
|
|
309
|
+
### As an Agent Advertiser (listing your agent)
|
|
379
310
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
311
|
+
- Pay per click (Link Ad) or pay per call (Agent Ad)
|
|
312
|
+
- Second-price auction — you bid a max, you often pay less
|
|
313
|
+
- Full budget controls — set a cap, campaign pauses when spent
|
|
314
|
+
- Track spend and performance in the advertiser dashboard
|
|
383
315
|
|
|
384
316
|
---
|
|
385
317
|
|
|
386
|
-
|
|
318
|
+
## API Reference
|
|
319
|
+
|
|
320
|
+
### `POST /v1/decide`
|
|
387
321
|
|
|
388
|
-
|
|
389
|
-
Thrown when the backend rejects your request (invalid key, bad params, etc). Includes detailed error message and request_id for debugging.
|
|
322
|
+
**Base URL:** `https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/decide`
|
|
390
323
|
|
|
391
|
-
|
|
392
|
-
Network issues, DNS failures, or backend unavailable. Includes automatic retry logic for transient failures.
|
|
324
|
+
**Required header:** `X-AM-API-Key: am_live_...` or `am_test_...`
|
|
393
325
|
|
|
394
|
-
|
|
395
|
-
Request took too long (default 5s). Configure with `timeoutMs` in constructor.
|
|
326
|
+
### Simple Request (recommended)
|
|
396
327
|
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
} catch (error) {
|
|
401
|
-
if (error instanceof TimeoutError) {
|
|
402
|
-
console.log('Request timed out, try again');
|
|
403
|
-
} else if (error instanceof NetworkError) {
|
|
404
|
-
console.log('Network issue, retrying...');
|
|
405
|
-
} else if (error instanceof APIRequestError) {
|
|
406
|
-
console.log('API error:', error.message);
|
|
407
|
-
}
|
|
328
|
+
```json
|
|
329
|
+
{
|
|
330
|
+
"context": "I need car insurance"
|
|
408
331
|
}
|
|
409
332
|
```
|
|
410
333
|
|
|
411
|
-
|
|
334
|
+
### Simple Request with Optional Fields
|
|
412
335
|
|
|
413
|
-
|
|
336
|
+
```json
|
|
337
|
+
{
|
|
338
|
+
"context": "I need car insurance",
|
|
339
|
+
"country": "US",
|
|
340
|
+
"language": "en",
|
|
341
|
+
"platform": "ios"
|
|
342
|
+
}
|
|
343
|
+
```
|
|
414
344
|
|
|
415
|
-
|
|
345
|
+
### Request an Agent Instead of an Ad
|
|
416
346
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
});
|
|
347
|
+
```json
|
|
348
|
+
{
|
|
349
|
+
"context": "User needs a wedding photographer in Austin",
|
|
350
|
+
"response_type": "agent"
|
|
351
|
+
}
|
|
423
352
|
```
|
|
424
353
|
|
|
425
|
-
###
|
|
426
|
-
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
354
|
+
### Advanced Request (full control)
|
|
355
|
+
|
|
356
|
+
```json
|
|
357
|
+
{
|
|
358
|
+
"request_id": "req_custom_123",
|
|
359
|
+
"agent_id": "agt_YOUR_ID",
|
|
360
|
+
"placement": "chat_inline",
|
|
361
|
+
"opportunity": {
|
|
362
|
+
"intent": { "taxonomy": "insurance.auto.quote" },
|
|
363
|
+
"context": { "country": "US", "language": "en", "platform": "ios" }
|
|
364
|
+
},
|
|
365
|
+
"context": "I need car insurance"
|
|
366
|
+
}
|
|
431
367
|
```
|
|
432
368
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
369
|
+
### Response: Ad Filled
|
|
370
|
+
|
|
371
|
+
```json
|
|
372
|
+
{
|
|
373
|
+
"request_id": "req_abc123",
|
|
374
|
+
"decision_id": "dec_xyz789",
|
|
375
|
+
"status": "filled",
|
|
376
|
+
"ttl_ms": 300000,
|
|
377
|
+
"units": [{
|
|
378
|
+
"unit_id": "unit_123",
|
|
379
|
+
"suggestion": {
|
|
380
|
+
"title": "Get 20% off car insurance",
|
|
381
|
+
"body": "Compare quotes in minutes",
|
|
382
|
+
"cta": "Get a Quote",
|
|
383
|
+
"tracking_url": "https://.../track-click/...",
|
|
384
|
+
"action_url": "https://progressive.com/quote"
|
|
385
|
+
},
|
|
386
|
+
"tracking": {
|
|
387
|
+
"token": "trk_abc",
|
|
388
|
+
"impression_url": "https://.../event",
|
|
389
|
+
"click_url": "https://.../click/trk_abc"
|
|
390
|
+
}
|
|
391
|
+
}]
|
|
447
392
|
}
|
|
448
393
|
```
|
|
449
394
|
|
|
450
|
-
|
|
451
|
-
<summary><strong>Security considerations</strong></summary>
|
|
395
|
+
### Response: No Fill
|
|
452
396
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
397
|
+
```json
|
|
398
|
+
{
|
|
399
|
+
"status": "no_fill",
|
|
400
|
+
"units": []
|
|
401
|
+
}
|
|
402
|
+
```
|
|
458
403
|
|
|
459
|
-
|
|
460
|
-
- Node.js servers
|
|
461
|
-
- Serverless functions (AWS Lambda, Vercel, Cloudflare Workers)
|
|
462
|
-
- Server-side rendering (Next.js, Remix)
|
|
404
|
+
### Key Response Fields
|
|
463
405
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
406
|
+
| Field | Use |
|
|
407
|
+
|-------|-----|
|
|
408
|
+
| `status` | `"filled"` or `"no_fill"` |
|
|
409
|
+
| `suggestion.title` | Ad headline to show |
|
|
410
|
+
| `suggestion.body` | Ad description to show |
|
|
411
|
+
| `suggestion.cta` | Button text |
|
|
412
|
+
| `suggestion.tracking_url` | **Send users here on click** — tracks automatically |
|
|
413
|
+
| `suggestion.action_url` | Direct advertiser URL (display only, no tracking) |
|
|
468
414
|
|
|
469
|
-
|
|
415
|
+
**Always use `tracking_url` for clicks.** This is how clicks are tracked and how you get paid.
|
|
470
416
|
|
|
471
|
-
|
|
417
|
+
### HTTP Status Codes
|
|
472
418
|
|
|
473
|
-
|
|
419
|
+
| Code | Meaning |
|
|
420
|
+
|------|---------|
|
|
421
|
+
| `200` | Success — check `status` field |
|
|
422
|
+
| `400` | Bad request — missing `context` field |
|
|
423
|
+
| `401` | Invalid API key |
|
|
424
|
+
| `429` | Rate limit exceeded (1,000 req/min) — retry after 60s |
|
|
425
|
+
| `500` | Server error — retry with backoff |
|
|
474
426
|
|
|
475
427
|
---
|
|
476
428
|
|
|
477
|
-
##
|
|
478
|
-
|
|
479
|
-
**Minimal integrations** (< 80 lines):
|
|
480
|
-
- [Claude Tool Use](./examples/claude-tool-use-minimal.ts)
|
|
481
|
-
- [OpenAI Function Calling](./examples/openai-function-calling-minimal.ts)
|
|
482
|
-
- [Google Gemini](./examples/gemini-function-calling-minimal.ts)
|
|
429
|
+
## Testing
|
|
483
430
|
|
|
484
|
-
|
|
485
|
-
- [Claude Complete](./examples/claude-tool-use-full.ts)
|
|
486
|
-
- [OpenAI Complete](./examples/openai-function-calling-full.ts)
|
|
487
|
-
- [Safe Web Rendering](./examples/safe-web-rendering.ts)
|
|
431
|
+
Use your test key (`am_test_...`) during development — same API, no real money moves.
|
|
488
432
|
|
|
489
|
-
|
|
433
|
+
**Validate your setup:**
|
|
490
434
|
```bash
|
|
491
|
-
|
|
435
|
+
node test-integration.js # Tests connectivity and credentials
|
|
436
|
+
node validate-production.js # Full production readiness check (4/4 ✅)
|
|
492
437
|
```
|
|
493
438
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
## Documentation
|
|
497
|
-
|
|
498
|
-
- **[Simple Integration Guide](./SIMPLE_INTEGRATION_GUIDE.md)** - Step-by-step for beginners
|
|
499
|
-
- **[Taxonomy System](./TAXONOMY_SYSTEM.md)** - Complete taxonomy reference
|
|
500
|
-
- **[Migration Guide](./TAXONOMY_MIGRATION_GUIDE.md)** - Upgrading from older versions
|
|
501
|
-
- **[Security Guide](./SECURITY.md)** - Security best practices
|
|
502
|
-
- **[Advertiser Guide](./ADVERTISER_ONBOARDING_GUIDE.md)** - For advertisers
|
|
503
|
-
|
|
504
|
-
---
|
|
505
|
-
|
|
506
|
-
## Features
|
|
507
|
-
|
|
508
|
-
- ✅ **Hierarchical matching** - Advertisers target broadly, agents match specifically
|
|
509
|
-
- ✅ **Auto-intent detection** - Automatically detect research vs quote vs apply
|
|
510
|
-
- ✅ **50+ high-value taxonomies** - Insurance, legal, finance, B2B SaaS, and more
|
|
511
|
-
- ✅ **TypeScript support** - Full type definitions included
|
|
512
|
-
- ✅ **Automatic retries** - Exponential backoff for failed requests
|
|
513
|
-
- ✅ **Mock client** - Test without API calls
|
|
514
|
-
- ✅ **Security helpers** - XSS protection, URL sanitization
|
|
515
|
-
- ✅ **Zero dependencies** - No external runtime dependencies
|
|
516
|
-
|
|
517
|
-
---
|
|
518
|
-
|
|
519
|
-
## Pricing
|
|
520
|
-
|
|
521
|
-
**Free to use.** You earn money when users click ads:
|
|
522
|
-
|
|
523
|
-
- **Insurance:** $20-54 per click
|
|
524
|
-
- **Legal:** $50-150 per click
|
|
525
|
-
- **Financial:** $15-50 per click
|
|
526
|
-
- **B2B SaaS:** $10-100 per click
|
|
527
|
-
- **Home Services:** $5-30 per click
|
|
528
|
-
|
|
529
|
-
**You keep 70% of revenue.** Paid monthly via Stripe.
|
|
530
|
-
|
|
531
|
-
---
|
|
532
|
-
|
|
533
|
-
## Requirements
|
|
534
|
-
|
|
535
|
-
- Node.js 18 or higher
|
|
536
|
-
- TypeScript 5.3+ (for development)
|
|
439
|
+
Download: [test-integration.js](./test-integration.js) | [validate-production.js](./validate-production.js)
|
|
537
440
|
|
|
538
441
|
---
|
|
539
442
|
|
|
540
|
-
##
|
|
541
|
-
|
|
542
|
-
The network currently has active campaigns in these verticals:
|
|
543
|
-
|
|
544
|
-
| Category | CPC Range | Common Intents |
|
|
545
|
-
|----------|-----------|----------------|
|
|
546
|
-
| Legal | $50-150 | Divorce, estate planning, personal injury, immigration |
|
|
547
|
-
| Insurance | $20-54 | Auto, home, life, health |
|
|
548
|
-
| Financial | $15-50 | Loans, credit cards, mortgages, investing |
|
|
549
|
-
| B2B SaaS | $10-100 | CRM, project management, ecommerce tools |
|
|
550
|
-
| Home Services | $5-30 | Moving, cleaning, repairs |
|
|
551
|
-
| Travel | $3-20 | Flights, hotels, packages |
|
|
552
|
-
| Ecommerce | $2-15 | Retail, subscriptions |
|
|
553
|
-
| Education | $10-50 | Courses, certifications |
|
|
554
|
-
|
|
555
|
-
The semantic matching API automatically maps user queries to available inventory. If your use case isn't listed, contact support@attentionmarket.com to discuss adding new categories.
|
|
443
|
+
## Get Started
|
|
556
444
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
**Full taxonomy list:** [TAXONOMY_SYSTEM.md](./TAXONOMY_SYSTEM.md)
|
|
563
|
-
|
|
564
|
-
Example taxonomies for advanced `decide()` API:
|
|
565
|
-
```typescript
|
|
566
|
-
// Insurance
|
|
567
|
-
'insurance.auto.full_coverage.quote'
|
|
568
|
-
'insurance.auto.liability.compare'
|
|
569
|
-
'insurance.home.standard.quote'
|
|
570
|
-
'insurance.life.term.compare'
|
|
571
|
-
|
|
572
|
-
// Legal
|
|
573
|
-
'legal.personal_injury.accident.consultation'
|
|
574
|
-
'legal.family.divorce.consultation'
|
|
575
|
-
'legal.estate_planning.will.consultation'
|
|
576
|
-
|
|
577
|
-
// Financial
|
|
578
|
-
'financial.loans.personal.quote'
|
|
579
|
-
'financial.credit_cards.rewards.compare'
|
|
580
|
-
'financial.investing.brokerage.trial'
|
|
581
|
-
|
|
582
|
-
// B2B SaaS
|
|
583
|
-
'business.saas.crm.trial'
|
|
584
|
-
'business.saas.project_management.trial'
|
|
585
|
-
|
|
586
|
-
// Home Services
|
|
587
|
-
'home_services.moving.local.quote'
|
|
588
|
-
'home_services.plumbing.emergency.quote'
|
|
589
|
-
```
|
|
590
|
-
|
|
591
|
-
</details>
|
|
445
|
+
1. **Sign up** at [api.attentionmarket.ai](https://api.attentionmarket.ai) — get your test key, live key, and agent ID
|
|
446
|
+
2. **Test it** — run the curl above with your test key
|
|
447
|
+
3. **Integrate** — add 5 lines to your existing chatbot or assistant
|
|
448
|
+
4. **Go live** — swap test key for live key, start earning
|
|
592
449
|
|
|
593
450
|
---
|
|
594
451
|
|
|
595
452
|
## Support
|
|
596
453
|
|
|
454
|
+
- **Dashboard:** [api.attentionmarket.ai](https://api.attentionmarket.ai)
|
|
597
455
|
- **Issues:** [GitHub Issues](https://github.com/rtrivedi/agent-ads-sdk/issues)
|
|
598
|
-
- **
|
|
599
|
-
- **Email:** support@attentionmarket.com
|
|
456
|
+
- **Email:** support@attentionmarket.ai
|
|
600
457
|
|
|
601
458
|
---
|
|
602
459
|
|
|
603
460
|
## License
|
|
604
461
|
|
|
605
|
-
MIT
|
|
606
|
-
|
|
607
|
-
---
|
|
608
|
-
|
|
609
|
-
## Changelog
|
|
610
|
-
|
|
611
|
-
See [CHANGELOG.md](./CHANGELOG.md) for detailed version history.
|
|
462
|
+
MIT — see [LICENSE](./LICENSE)
|