@the_ro_show/agent-ads-sdk 0.7.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 CHANGED
@@ -1,656 +1,462 @@
1
- # AttentionMarket Agent Ads SDK
1
+ # AttentionMarket
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/@the_ro_show%2Fagent-ads-sdk.svg)](https://www.npmjs.com/package/@the_ro_show/agent-ads-sdk)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
6
5
 
7
- Ad network for AI agents. Pass user messages, get contextually relevant ads, earn revenue.
6
+ **The ad exchange for the AI era. Monetize your chatbot, AI assistant, or AI agent with one API call.**
8
7
 
9
- **Simple integration. High revenue. Production-ready.**
10
-
11
- ```bash
12
- npm install @the_ro_show/agent-ads-sdk
13
- ```
14
-
15
- ## How It Works
16
-
17
- ```typescript
18
- // User asks your AI agent
19
- const userMessage = "I need car insurance";
20
-
21
- // Get a relevant ad
22
- const ad = await client.decideFromContext({ userMessage });
23
-
24
- // Show it to the user
25
- console.log(ad.creative.title); // → "Get 20% off car insurance"
26
- console.log(ad.creative.body); // → "Compare quotes in minutes"
27
- console.log(ad.creative.cta); // → "Get a Quote"
28
- console.log(ad.click_url); // → Auto-tracking URL
29
-
30
- // That's it! Clicks track automatically when user follows the link
31
- ```
32
-
33
- **Result:**
34
- ```
35
- User: "My car insurance renewal is coming up and the price went up a lot.
36
- Should I shop around?"
37
-
38
- AI Agent: Yes, definitely worth shopping around! Prices can vary significantly
39
- between providers. Here are some well-rated options to compare:
40
-
41
- 1. State Farm - Large national provider with local agents
42
- 2. Geico - Known for competitive online quotes
43
- 3. Allstate - Comprehensive coverage options
44
-
45
- Also, I have access to a special deal - 20% off with Progressive where
46
- you can compare quotes in minutes. Want me to send you the link?
47
-
48
- User: "Sure, send it over"
49
-
50
- AI Agent: Here you go! This should help you compare and save:
51
- https://progressive.com/quote?ref=am_abc123
52
-
53
- 💰 You earn $5-$150 per click | 70% revenue share
54
- ```
55
-
56
- ## Why This SDK
57
-
58
- **For AI Agent Developers:**
59
- - **$5-$150 per click** - High-value leads (insurance, legal, finance, B2B)
60
- - **70% revenue share** - You keep most of the earnings
61
- - **No user friction** - Free for users, monetize without paywalls
62
- - **2 functions** - Simple API: init, get ads (clicks track automatically)
63
- - **Production-ready** - Rate limiting, error handling, retry logic built-in
8
+ Works on every platform — iOS, Android, Web, Voice, Discord, WhatsApp, Node.js, Python, and anything else that can make an HTTP request.
64
9
 
65
10
  ---
66
11
 
67
- ## Quick Start
12
+ ## Two Ways To Earn
68
13
 
69
- ### 1. Get API Key
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.
70
16
 
71
- Sign up at [api.attentionmarket.ai](https://api.attentionmarket.ai) to receive:
72
- - Test key: `am_test_...`
73
- - Live key: `am_live_...`
74
- - Agent ID
75
-
76
- ### 2. Basic Usage
77
-
78
- ```typescript
79
- import { AttentionMarketClient } from '@the_ro_show/agent-ads-sdk';
80
-
81
- const client = new AttentionMarketClient({
82
- apiKey: process.env.ATTENTIONMARKET_API_KEY,
83
- agentId: 'your_agent_id'
84
- });
85
-
86
- // Get an ad
87
- const ad = await client.decideFromContext({
88
- userMessage: "I need car insurance"
89
- });
90
-
91
- if (ad) {
92
- console.log(ad.creative.title); // "Get 20% off car insurance"
93
- console.log(ad.creative.body); // "Compare quotes in minutes"
94
- console.log(ad.creative.cta); // "Get a Quote"
95
- console.log(ad.click_url); // Auto-tracking URL
96
-
97
- // That's it! Share ad.click_url with user
98
- // Clicks track automatically, you get paid
99
- }
100
- ```
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.
101
19
 
102
20
  ---
103
21
 
104
- ## Core API
22
+ ## Quick Start — 30 Seconds
105
23
 
106
- ### Get Ads
24
+ Get your API keys at [api.attentionmarket.ai](https://api.attentionmarket.ai), then:
107
25
 
108
- ```typescript
109
- const ad = await client.decideFromContext({
110
- userMessage: "I need car insurance"
111
- });
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
+ ```
32
+
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
+ }]
45
+ }
112
46
  ```
113
47
 
114
- Returns: `creative.title`, `creative.body`, `creative.cta`, `click_url`
115
-
116
- **All URLs auto-track clicks** - No manual tracking code needed!
117
-
118
- When user clicks any link, we:
119
- 1. Track the click automatically
120
- 2. Redirect to advertiser
121
- 3. Credit your account
122
-
123
- Works in chat apps, emails, SMS, web apps - anywhere users can click links.
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.
124
49
 
125
50
  ---
126
51
 
127
- ### Track Clicks
128
-
129
- **✅ Automatic (Recommended)**
52
+ ## 🚨 CRITICAL: Impression Tracking Required (v0.9.0+)
130
53
 
131
- Clicks track automatically - no code needed! Just share the ad URL:
54
+ **As of v0.9.0, impression tracking is REQUIRED to earn revenue from clicks.**
132
55
 
133
- ```typescript
134
- const ad = await client.decideFromContext({ userMessage });
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
135
60
 
136
- // Share this with users - clicks track automatically
137
- const link = ad.click_url;
61
+ ### Why This Matters
138
62
 
139
- // Works in: chat apps, email, SMS, web apps, anywhere
140
- ```
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.
141
64
 
142
- **📊 Optional: Track Impressions**
65
+ ### Using `decideFromContext()` (Recommended)
143
66
 
144
- Track when you *show* an ad (before user clicks):
67
+ **Good news:** If you're using the SDK's `decideFromContext()` method, impressions are tracked **automatically**. No changes needed.
145
68
 
146
69
  ```typescript
147
- await client.track({
148
- agent_id: 'your_agent_id',
149
- event_type: 'ad_impression',
150
- metadata: {
151
- decision_id: ad.offer_id,
152
- unit_id: ad.offer_id,
153
- surface: 'chat_message'
154
- }
70
+ // Impressions tracked automatically ✅
71
+ const ad = await client.decideFromContext({
72
+ userMessage: "I need car insurance",
73
+ placement: 'sponsored_suggestion'
155
74
  });
75
+
76
+ if (ad) {
77
+ // Show ad to user
78
+ displayAd(ad);
79
+ }
156
80
  ```
157
81
 
158
- <details>
159
- <summary>Advanced: Manual click tracking (legacy)</summary>
82
+ ### Using Raw HTTP or `decide()` (Manual Tracking Required)
160
83
 
161
- If you need to track clicks manually (not recommended - auto-tracking is easier):
84
+ If you're making raw HTTP calls or using the low-level `decide()` method, you **must manually track impressions**:
162
85
 
163
86
  ```typescript
164
- // Before redirecting to ad.click_url
165
- await client.trackClickFromAd(ad, {
166
- click_context: "What you showed the user"
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' })
167
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
+ });
168
111
 
169
- // Then redirect: window.location.href = ad.click_url
112
+ // Step 3: Now safe to show ad and earn from clicks
113
+ displayAd(ad);
114
+ }
170
115
  ```
171
116
 
172
- **Note:** Auto-tracking is simpler and works in more scenarios (email, SMS, etc).
173
-
174
- </details>
175
-
176
117
  ---
177
118
 
178
- ## API Reference
119
+ ## Use Case 1: Monetize Your Chatbot or AI Assistant
179
120
 
180
- ### Essential Functions
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.
181
122
 
182
- #### `new AttentionMarketClient(config)`
183
- Initialize the SDK with your API key and agent ID
123
+ **Platforms this works on:**
184
124
 
185
- ```typescript
186
- const client = new AttentionMarketClient({
187
- apiKey: process.env.ATTENTIONMARKET_API_KEY,
188
- agentId: 'your_agent_id'
189
- });
190
- ```
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 |
191
132
 
192
- #### `client.decideFromContext(params)`
193
- Get a contextually relevant ad based on user's message
133
+ ### How It Works
194
134
 
195
- ```typescript
196
- const ad = await client.decideFromContext({
197
- userMessage: "I need car insurance"
198
- });
199
- // Returns: { creative, click_url, tracking_url, tracking_token, ... }
200
135
  ```
201
-
202
- #### `ad.click_url` NEW: Auto-tracking
203
- All ad URLs now track clicks automatically via server-side redirects
204
-
205
- ```typescript
206
- const ad = await client.decideFromContext({ userMessage });
207
-
208
- // Just share this URL - clicks track automatically!
209
- const link = ad.click_url;
210
-
211
- // When user clicks:
212
- // 1. We track the click
213
- // 2. User is redirected to advertiser
214
- // 3. You get paid
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
215
138
  ```
216
139
 
217
- **No manual tracking code needed.** Works in chat apps, emails, SMS, anywhere.
140
+ ### Platform Examples
218
141
 
219
- #### `client.track(event)` (Optional)
220
- Track impressions or custom events
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
+ )
221
149
 
222
- ```typescript
223
- await client.track({
224
- agent_id: 'your_agent_id',
225
- event_type: 'ad_impression',
226
- metadata: {
227
- decision_id: ad.offer_id,
228
- surface: 'chat'
229
- }
230
- });
231
- ```
232
-
233
- ### Testing
234
-
235
- #### `MockAttentionMarketClient`
236
- Mock client for testing without API calls
237
-
238
- ```typescript
239
- import { MockAttentionMarketClient } from '@the_ro_show/agent-ads-sdk';
240
-
241
- const client = new MockAttentionMarketClient({
242
- fillRate: 1.0, // Always return ads
243
- latencyMs: 100, // Simulate API latency
244
- verbose: true // Log activity
245
- });
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
+ }
246
159
  ```
160
+ [Full iOS example →](./examples/ios/AttentionMarketClient.swift)
247
161
 
248
- ### Utilities
249
-
250
- #### `escapeHTML(text)` & `sanitizeURL(url)`
251
- Sanitize ad content before rendering in HTML
252
-
253
- ```typescript
254
- import { escapeHTML, sanitizeURL } from '@the_ro_show/agent-ads-sdk';
162
+ ---
255
163
 
256
- const safeTitle = escapeHTML(ad.creative.title);
257
- const safeURL = sanitizeURL(ad.click_url);
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
+ }
258
178
  ```
179
+ [Full Android example →](./examples/android/AttentionMarketClient.kt)
259
180
 
260
181
  ---
261
182
 
262
- ## Advanced Features
263
-
264
- <details>
265
- <summary><strong>Click to view: Complete example, testing, security, and advanced APIs</strong></summary>
266
-
267
- <br>
268
-
269
- ### Complete Example
270
-
271
- Full integration including ad retrieval, display, and click tracking:
272
-
273
- ```typescript
274
- import { AttentionMarketClient } from '@the_ro_show/agent-ads-sdk';
275
-
276
- const client = new AttentionMarketClient({
277
- apiKey: process.env.ATTENTIONMARKET_API_KEY,
278
- agentId: 'your_agent_id'
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 })
279
192
  });
280
193
 
281
- async function handleUserMessage(userMessage: string) {
282
- const ad = await client.decideFromContext({ userMessage });
283
-
284
- if (!ad) {
285
- return null; // No ads available
286
- }
287
-
288
- // Display ad (customize as needed)
289
- const displayMessage = `\n[Sponsored] ${ad.disclosure.sponsor_name}\n${ad.creative.title}\n${ad.creative.body}\n${ad.creative.cta}\n`;
290
- console.log(displayMessage);
291
-
292
- // Track click when user clicks
293
- await client.trackClick({
294
- agent_id: 'your_agent_id',
295
- request_id: ad.request_id,
296
- decision_id: ad.offer_id,
297
- unit_id: ad.offer_id,
298
- tracking_token: ad.tracking_token,
299
- href: ad.click_url,
300
- click_context: displayMessage // What was actually shown
301
- });
194
+ const data = await response.json();
302
195
 
303
- return ad;
196
+ if (data.status === 'filled') {
197
+ const ad = data.units[0];
198
+ showAdInChat(ad.suggestion.title, ad.suggestion.body, ad.suggestion.tracking_url);
304
199
  }
305
200
  ```
201
+ [Full Web example →](./examples/web/attentionmarket.js)
306
202
 
307
203
  ---
308
204
 
309
- ### Testing
310
-
311
- #### `MockAttentionMarketClient`
312
-
313
- Mock client for testing without API calls. Simulates latency and fill rate behavior.
314
-
315
- ```typescript
316
- import { MockAttentionMarketClient } from '@the_ro_show/agent-ads-sdk';
317
-
318
- const client = new MockAttentionMarketClient({
319
- fillRate: 1.0, // Always return ads (0.0 = never, 0.5 = 50%)
320
- latencyMs: 100, // Simulate API latency
321
- verbose: true // Log activity
322
- });
323
-
324
- // Works exactly like the real client
325
- const ad = await client.decideFromContext({ userMessage: "test" });
205
+ **Node.js (optional SDK)**:
206
+ ```bash
207
+ npm install @the_ro_show/agent-ads-sdk
326
208
  ```
209
+ ```javascript
210
+ import { AttentionMarketClient } from '@the_ro_show/agent-ads-sdk';
327
211
 
328
- ---
329
-
330
- ### Using Test vs Live Keys
331
-
332
- **Test Environment:**
333
- ```typescript
334
212
  const client = new AttentionMarketClient({
335
- apiKey: process.env.ATTENTIONMARKET_TEST_KEY // am_test_...
213
+ apiKey: process.env.ATTENTIONMARKET_API_KEY,
214
+ agentId: process.env.ATTENTIONMARKET_AGENT_ID
336
215
  });
337
- ```
338
216
 
339
- **Production Environment:**
340
- ```typescript
341
- const client = new AttentionMarketClient({
342
- apiKey: process.env.ATTENTIONMARKET_API_KEY // am_live_...
343
- });
217
+ const ad = await client.decideFromContext({ userMessage });
218
+ if (ad) console.log(ad.creative.title, ad.click_url);
344
219
  ```
345
220
 
346
221
  ---
347
222
 
348
- ### Security
349
-
350
- #### Server-Side Only
351
-
352
- **IMPORTANT:** This SDK must run server-side. Never expose your API key in client-side code.
223
+ ## Use Case 2: List Your AI Agent on the Exchange
353
224
 
354
- **✅ Supported:**
355
- - Node.js servers
356
- - Serverless functions (AWS Lambda, Vercel, Cloudflare Workers)
357
- - Server-side rendering (Next.js, Remix)
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.
358
226
 
359
- **❌ Not supported:**
360
- - Browser JavaScript
361
- - Client-side React/Vue/Angular
362
- - Mobile apps
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.
363
228
 
364
- #### API Key Management
365
-
366
- Store your API key in environment variables:
367
-
368
- ```bash
369
- export ATTENTIONMARKET_API_KEY=am_live_...
370
- ```
371
-
372
- Never commit API keys to version control. Add to `.gitignore`:
229
+ ### How It Works
373
230
 
374
231
  ```
375
- .env
376
- .env.local
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
377
237
  ```
378
238
 
379
- #### Sanitize Ad Content
239
+ ### Example
380
240
 
381
- Ad content comes from third-party advertisers. Always sanitize before rendering in HTML:
241
+ **Developer A** built a general wedding planning AI assistant. A user asks: *"Can you find me a photographer in Austin under $3,000?"*
382
242
 
383
- ```typescript
384
- import { escapeHTML, sanitizeURL } from '@the_ro_show/agent-ads-sdk';
385
-
386
- const safeTitle = escapeHTML(ad.creative.title);
387
- const safeURL = sanitizeURL(ad.click_url);
388
-
389
- if (safeURL) {
390
- element.innerHTML = `<a href="${safeURL}">${safeTitle}</a>`;
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
+ }'
252
+ ```
253
+
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
+ }]
391
268
  }
392
269
  ```
393
270
 
394
- ---
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.
395
273
 
396
- ### Manual Category Targeting
274
+ ### List Your Agent
397
275
 
398
- #### `decide()` - Specify exact categories
276
+ Sign up as an advertiser at [api.attentionmarket.ai](https://api.attentionmarket.ai) and create an **Agent Ad** campaign:
399
277
 
400
- When you know the exact category, use manual taxonomy matching for deterministic results.
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 |
401
286
 
402
- ```typescript
403
- const decision = await client.decide({
404
- request_id: crypto.randomUUID(),
405
- agent_id: 'your_agent_id',
406
- placement: { type: 'sponsored_suggestion' },
407
- opportunity: {
408
- intent: { taxonomy: 'insurance.auto.full_coverage.quote' },
409
- context: { country: 'US', language: 'en', platform: 'web' }
410
- }
411
- });
412
- ```
413
-
414
- See [TAXONOMY_SYSTEM.md](./TAXONOMY_SYSTEM.md) for all categories.
287
+ **Matching is semantic** — describe your agent clearly in plain English and we handle the rest.
415
288
 
416
289
  ---
417
290
 
418
- ### 🌐 Intenture Network APIs (Agent-to-Agent)
419
-
420
- #### `requestOffer()` - Intent-key based matching
421
-
422
- When you KNOW what the user wants (they said "order coffee" or "book lawyer"), use intent-keys like `coffee.purchase.delivery` for deterministic matching.
291
+ ## Revenue Model
423
292
 
424
- ```typescript
425
- const offer = await client.requestOffer({
426
- placementId: 'order_card',
427
- intentKey: 'coffee.purchase.delivery',
428
- context: { geo: { city: 'SF', country: 'US' } }
429
- });
430
- ```
293
+ ### As a Developer (showing ads or routing to agents)
431
294
 
432
- #### `requestOfferFromContext()` - Semantic discovery
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
433
300
 
434
- When you're NOT sure what they need (they said "I'm so tired"), pass the conversation and let semantic search find relevant offers.
435
-
436
- ```typescript
437
- const offer = await client.requestOfferFromContext({
438
- placementId: 'chat_suggestion',
439
- userMessage: "I'm so tired, long day at work...",
440
- conversationHistory: ["How was your day?", "Exhausting"],
441
- context: { geo: { city: 'NYC' } }
442
- });
443
- ```
301
+ **Example earnings:**
444
302
 
445
- #### Revenue Share (Preview)
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 |
446
308
 
447
- If another agent sends users to you, include their agent_id to split revenue (0-50%). Currently in preview mode - payouts activate Q2 2026.
309
+ ### As an Agent Advertiser (listing your agent)
448
310
 
449
- ```typescript
450
- const offer = await client.requestOffer({
451
- intentKey: 'legal.divorce.consultation',
452
- sourceAgentId: 'agt_referrer_123', // Agent who sent the user
453
- revenueSharePct: 30, // Give them 30% of revenue
454
- // ... other params
455
- });
456
- ```
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
457
315
 
458
316
  ---
459
317
 
460
- ### 🧠 Intent Detection
461
-
462
- #### `detectIntent()` - Auto-detect user journey stage
463
-
464
- Analyzes queries to determine if they're researching, comparing, getting quotes, or ready to buy.
465
-
466
- ```typescript
467
- detectIntent("What is car insurance?") // → 'research'
468
- detectIntent("Compare car insurance options") // → 'compare'
469
- detectIntent("Get car insurance quote") // → 'quote'
470
- detectIntent("I want to buy car insurance") // → 'apply'
471
- ```
472
-
473
- #### `buildTaxonomy()` - Type-safe taxonomy builder
474
-
475
- ```typescript
476
- const taxonomy = buildTaxonomy('insurance', 'auto', 'full_coverage', 'quote');
477
- // → "insurance.auto.full_coverage.quote"
478
- ```
479
-
480
- #### `suggestTaxonomies()` - Smart taxonomy recommendations
481
-
482
- ```typescript
483
- const suggestions = suggestTaxonomies("I need a lawyer for divorce");
484
- // → ['legal.family.divorce.consultation', 'legal.family.custody.consultation']
485
- ```
318
+ ## API Reference
486
319
 
487
- #### Taxonomy Utilities
488
- - `isValidTaxonomy(taxonomy)` - Validate taxonomy format
489
- - `parseTaxonomy(taxonomy)` - Parse into components
490
- - `getBaseTaxonomy(taxonomy)` - Get taxonomy without intent
491
- - `matchesTaxonomy(tax1, tax2)` - Check if taxonomies match
492
- - `getVertical(taxonomy)` - Extract industry vertical
320
+ ### `POST /v1/decide`
493
321
 
494
- ---
322
+ **Base URL:** `https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/decide`
495
323
 
496
- ### 🎨 Response Formatting
324
+ **Required header:** `X-AM-API-Key: am_live_...` or `am_test_...`
497
325
 
498
- #### `formatNatural()` - Convert ads into natural conversation
326
+ ### Simple Request (recommended)
499
327
 
500
- ```typescript
501
- const formatted = formatNatural(ad, {
502
- tone: 'friendly',
503
- includeDisclosure: true
504
- });
505
- // → "I found a great option for you! [Sponsored: Lemonade]..."
328
+ ```json
329
+ {
330
+ "context": "I need car insurance"
331
+ }
506
332
  ```
507
333
 
508
- #### `formatInlineMention()` - Subtle in-message placement
334
+ ### Simple Request with Optional Fields
509
335
 
510
- ```typescript
511
- const mention = formatInlineMention(ad);
512
- // "Btw, Lemonade offers 20% off for new drivers [Sponsored]"
336
+ ```json
337
+ {
338
+ "context": "I need car insurance",
339
+ "country": "US",
340
+ "language": "en",
341
+ "platform": "ios"
342
+ }
513
343
  ```
514
344
 
515
- #### `validateAdFits()` - Check if ad matches context
345
+ ### Request an Agent Instead of an Ad
516
346
 
517
- ```typescript
518
- const fits = validateAdFits(ad, conversationContext);
519
- if (fits) {
520
- // Show the ad
347
+ ```json
348
+ {
349
+ "context": "User needs a wedding photographer in Austin",
350
+ "response_type": "agent"
521
351
  }
522
352
  ```
523
353
 
524
- ---
525
-
526
- ### 📊 Event Tracking
527
-
528
- #### `trackImpression()` - Log when users see an ad
354
+ ### Advanced Request (full control)
529
355
 
530
- ```typescript
531
- await client.trackImpression({
532
- agent_id: 'your_agent_id',
533
- request_id: decision.request_id,
534
- decision_id: decision.decision_id,
535
- unit_id: ad.unit_id,
536
- tracking_token: ad.tracking.token
537
- });
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
+ }
538
367
  ```
539
368
 
540
- ---
541
-
542
- ### 🛠️ Helper Utilities
543
-
544
- #### `createOpportunity()` - Build opportunity objects
545
-
546
- ```typescript
547
- const opportunity = createOpportunity({
548
- taxonomy: 'insurance.auto.quote',
549
- country: 'US'
550
- });
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
+ }]
392
+ }
551
393
  ```
552
394
 
553
- #### Security Helpers
554
- - `escapeHTML(text)` - Sanitize ad content before rendering
555
- - `sanitizeURL(url)` - Validate and sanitize URLs
556
-
557
- #### ID Generation
558
- - `generateUUID()` - Create unique request IDs
559
- - `generateTimestamp()` - Generate API-compatible timestamps
560
-
561
- ---
562
-
563
- ### ⚠️ Error Handling
564
-
565
- #### `APIRequestError` - API returned an error
566
-
567
- Thrown when the backend rejects your request. Includes detailed error message and request_id.
568
-
569
- #### `NetworkError` - Connection failed
570
-
571
- Network issues or backend unavailable. Includes automatic retry logic.
572
-
573
- #### `TimeoutError` - Request exceeded timeout
395
+ ### Response: No Fill
574
396
 
575
- Request took too long (default 5s). Configure with `timeoutMs` in constructor.
576
-
577
- ```typescript
578
- try {
579
- const decision = await client.decide(request);
580
- } catch (error) {
581
- if (error instanceof TimeoutError) {
582
- console.log('Request timed out, try again');
583
- } else if (error instanceof NetworkError) {
584
- console.log('Network issue, retrying...');
585
- } else if (error instanceof APIRequestError) {
586
- console.log('API error:', error.message);
587
- }
397
+ ```json
398
+ {
399
+ "status": "no_fill",
400
+ "units": []
588
401
  }
589
402
  ```
590
403
 
591
- </details>
592
-
593
- ---
594
-
595
- ## Monetize Your AI Agent
596
-
597
- Stop giving away your AI agent for free. Start earning revenue from every conversation.
404
+ ### Key Response Fields
598
405
 
599
- **Traditional monetization (hard):**
600
- - Paywalls → 95% of users leave before paying
601
- - Subscriptions $10-20/month per user (if they convert)
602
- - Usage limits Frustrates users, kills growth
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) |
603
414
 
604
- **AttentionMarket (easy):**
605
- - **Free for users** → No friction, keep all your users
606
- - **Earn per click** → $5-$150 per click on high-value ads (insurance, legal, finance)
607
- - **70% revenue share** → You keep most of the earnings
608
- - **Contextual ads** → Only show relevant ads when users have commercial intent
415
+ **Always use `tracking_url` for clicks.** This is how clicks are tracked and how you get paid.
609
416
 
610
- **Example earnings:**
611
- - 1,000 users/month × 5% click rate × $50 avg = **$1,750/month** (you keep $1,225)
612
- - 10,000 users/month × 3% click rate × $75 avg = **$22,500/month** (you keep $15,750)
417
+ ### HTTP Status Codes
613
418
 
614
- **Integration time:** 10 minutes. Four functions. Production-ready.
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 |
615
426
 
616
427
  ---
617
428
 
618
- ## Examples
619
-
620
- **Basic integration** (~50 lines):
621
- - [basic-example.ts](./examples/basic-example.ts) - Get ads and track clicks
622
-
623
- **Chatbot integration** (~45 lines):
624
- - [chatbot-example.ts](./examples/chatbot-example.ts) - Using `tracking_url` for shared links
429
+ ## Testing
625
430
 
626
- **Testing** (~320 lines):
627
- - [test-with-mocks.ts](./examples/test-with-mocks.ts) - Test without API calls
431
+ Use your test key (`am_test_...`) during development — same API, no real money moves.
628
432
 
629
- Run any example:
433
+ **Validate your setup:**
630
434
  ```bash
631
- npx tsx examples/basic-example.ts
435
+ node test-integration.js # Tests connectivity and credentials
436
+ node validate-production.js # Full production readiness check (4/4 ✅)
632
437
  ```
633
438
 
634
- ---
635
-
636
- ## For AI Agents
439
+ Download: [test-integration.js](./test-integration.js) | [validate-production.js](./validate-production.js)
637
440
 
638
- **AI agents:** Read **[AI_AGENT_SETUP_GUIDE.md](./AI_AGENT_SETUP_GUIDE.md)** for complete step-by-step integration instructions.
441
+ ---
639
442
 
640
- **Developers:** Give this document to your AI agent (Claude, ChatGPT, etc.) and say:
641
- > "Please integrate the AttentionMarket SDK following the AI_AGENT_SETUP_GUIDE.md"
443
+ ## Get Started
642
444
 
643
- The agent will handle: getting credentials, installing SDK, writing integration code, testing, and deployment setup.
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
644
449
 
645
450
  ---
646
451
 
647
452
  ## Support
648
453
 
454
+ - **Dashboard:** [api.attentionmarket.ai](https://api.attentionmarket.ai)
649
455
  - **Issues:** [GitHub Issues](https://github.com/rtrivedi/agent-ads-sdk/issues)
650
- - **Email:** support@attentionmarket.com
456
+ - **Email:** support@attentionmarket.ai
651
457
 
652
458
  ---
653
459
 
654
460
  ## License
655
461
 
656
- MIT
462
+ MIT — see [LICENSE](./LICENSE)