# Adsourcer Developer Documentation > Machine-readable export for coding agents and LLM context. > Source: https://adsourcer.io/docs > API base: http://localhost:8000 --- # Adsourcer Developer — Overview Adsourcer is the API layer for sponsored recommendations in AI applications. Publishers retrieve relevant ads; advertisers run campaigns — all through one infrastructure. ## How it works 1. Your app sends conversation context to `POST /v1/ads/recommend` 2. Adsourcer returns ranked candidates or a `NO_AD` decision 3. You render the UI — Adsourcer never injects markup 4. Users click through signed `click_url` redirects for attribution ## Paths - **Publishers** — integrate recommendations into chatbots, agents, and copilots - **Advertisers** — create campaigns, upload products, manage budget - **SDKs** — TypeScript and Python typed clients - **API reference** — REST endpoints and response shapes ## Base URL All public endpoints use the `/v1/` prefix. Default local API: `http://localhost:8000` OpenAPI (when API is running): `http://localhost:8000/docs` --- # Quickstart Add sponsored recommendations to an AI app in four steps. ## 1. Get an API key Publishers need an API key with the `publisher` tenant type. Advertisers sign up via the dashboard to receive advertiser-scoped keys. ## 2. Install the SDK ```bash npm install @adsourcer/sdk # or pip install adsourcer ``` ## 3. Request recommendations ```typescript import { Adsourcer } from "@adsourcer/sdk"; const client = new Adsourcer({ apiKey: process.env.ADSOURCER_API_KEY! }); const result = await client.ads.recommend({ query: userMessage, context: { currency: "EUR", location: "NO", session_id: sessionId }, max_results: 3, }); if (result.decision === "SHOW") { for (const ad of result.ads) { // Render ad.title, ad.price, ad.disclosure // Link CTA to ad.click_url } } ``` ## 4. Disclose and track - Every ad includes `sponsored: true` and a `disclosure` string — display these labels (required) - Use `click_url` as the href on ad links — Adsourcer records the click and redirects - Optionally fire impression events when ads render - Use anonymous session IDs — do not send PII --- # Authentication Adsourcer supports API keys for integrations and JWT sessions for the advertiser dashboard. ## API keys Server-to-server requests use an API key prefixed with `ads_`. Keys are hashed at rest and scoped by tenant type (publisher, advertiser, platform). ```http Authorization: Bearer ads_your_api_key # or X-API-Key: ads_your_api_key ``` Never expose API keys in client-side code or public repositories. ## Dashboard sessions JWT access tokens from `POST /v1/auth/login` or `POST /v1/auth/signup`: ```http Authorization: Bearer eyJhbGciOiJIUzI1NiIs... ``` ## Social sign-in Dashboard supports OAuth (Google, GitHub, Microsoft) when configured. OAuth links to existing emails automatically. OAuth is for dashboard access only — SDK integrations use API keys. ## Auth endpoints - `POST /v1/auth/signup` - `POST /v1/auth/login` - `GET /v1/auth/me` - `POST /v1/auth/api-key` - `GET /v1/auth/oauth/{provider}` --- # API reference Base URL: `http://localhost:8000` Prefix: `/v1/` ## POST /v1/ads/recommend Publisher-only. Returns sponsored recommendations. Requires publisher-scoped API key. **Request:** ```json { "query": "wireless keyboard under €150", "context": { "currency": "EUR", "location": "NO" }, "session_id": "anon-session-uuid", "placement": "recommendation", "max_results": 3 } ``` **Response:** ```json { "request_id": "550e8400-e29b-41d4-a716-446655440000", "decision": "SHOW", "ads": [{ "ad_id": "660e8400-e29b-41d4-a716-446655440001", "title": "Keychron K2 Wireless", "price": 129.0, "currency": "EUR", "sponsored": true, "disclosure": "Sponsored", "click_url": "http://localhost:8000/v1/click/eyJ..." }] } ``` When intent is not commercial: `decision` is `NO_AD`, `ads` is empty. ## GET /v1/click/{token} Public redirect. Validates token, records click, 302 to advertiser URL. No API key required. ## Events - `POST /v1/events/impression` - `POST /v1/events/click` (legacy — prefer click_url redirect) - `POST /v1/events/conversion` ## Advertiser - `POST /v1/campaigns` - `GET /v1/campaigns` - `POST /v1/products` - `GET /v1/products` - `GET /v1/analytics/advertiser` - `GET /v1/balance` - `POST /v1/balance/topup` ## Publisher analytics - `GET /v1/analytics/publisher` OpenAPI: `http://localhost:8000/docs` --- # Click tracking Every ad includes a signed `click_url`. Use it as the link href — Adsourcer handles attribution and redirect. ## Flow 1. `POST /v1/ads/recommend` returns `click_url` for each ad 2. Your UI links the ad CTA to that URL 3. User hits `GET /v1/click/{token}` 4. Adsourcer validates token, records click, 302-redirects to advertiser ## Rules - Do not unwrap or modify `click_url` — always send users through it - Display sponsored disclosure labels on every ad - Do not prefetch or bot-click redirect URLs - Tokens are signed and time-limited; expired/tampered tokens return 404 ## Example ``` http://localhost:8000/v1/click/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` --- # Events Track the ad lifecycle from render to conversion. ## Event types - **Impression** — ad rendered. Fire when sponsored unit enters view. - **Click** — user engaged. Prefer `click_url` redirect over manual click events. - **Conversion** — purchase/signup attributed to prior click. ## Impression (TypeScript) ```typescript await client.events.impression({ request_id: result.request_id, ad_id: ad.ad_id, session_id: sessionId, }); ``` ## Conversion (Python) ```python client.events.conversion( request_id=request_id, ad_id=ad_id, value=149.0, currency="EUR", click_id=click_id, ) ``` ## Endpoints - `POST /v1/events/impression` - `POST /v1/events/click` - `POST /v1/events/conversion` ## Best practices - Reuse the same anonymous `session_id` across recommend and events - Always pass `request_id` from the recommend response - Do not send PII in event payloads --- # SDKs Typed clients for Node/TypeScript and Python. ## Installation ```bash npm install @adsourcer/sdk pip install adsourcer ``` ## TypeScript ```typescript import { Adsourcer } from "@adsourcer/sdk"; const client = new Adsourcer({ apiKey: process.env.ADSOURCER_API_KEY!, baseUrl: "https://api.adsourcer.io", // optional }); const result = await client.ads.recommend({ query: userMessage, context: { currency: "EUR", location: "NO" }, max_results: 3, }); ``` ## Python ```python from adsourcer import Adsourcer client = Adsourcer(api_key=os.environ["ADSOURCER_API_KEY"]) result = client.ads.recommend( query=user_message, context={"currency": "EUR", "location": "NO"}, max_results=3, ) ``` ## Event helpers Both SDKs expose `client.events` for impressions, clicks, and conversions. ## Repositories - https://github.com/adsourcer/adsourcer-sdk-typescript - https://github.com/adsourcer/adsourcer-sdk-python --- # Publisher integration Add sponsored recommendations to AI applications without surrendering UI control. ## Checklist 1. Obtain a publisher API key 2. Install SDK or call REST directly 3. Send queries to `POST /v1/ads/recommend` 4. Handle `SHOW` and `NO_AD` decisions 5. Render ads with mandatory disclosure labels 6. Link CTAs to `click_url` 7. Optionally record impression events on render ## Request ```json { "query": "best running shoes under €150", "context": { "currency": "EUR", "location": "NO" }, "session_id": "anon-session-uuid", "placement": "recommendation", "max_results": 1 } ``` ## Rendering Responses include structured fields (title, price, image URL, disclosure) — no HTML. You control layout. Intent gating ensures ads only appear when commercial intent is detected. **Required:** Display the `disclosure` field (typically "Sponsored") adjacent to every ad unit. ## Placements Pass `placement` hint: `recommendation`, `inline`, `sidebar`, etc. See also: [Embed](/docs/embed) for drop-in React components and iframe units. --- # Embed Drop-in ad units for publishers. Prefetch on your server, render with React or an iframe. ## Flow 1. Server calls `POST /v1/ads/recommend` with publisher API key 2. Pass response JSON to embed (never expose API key) 3. Embed renders disclosure, price, and `click_url` links 4. Proxy impression events from browser to `POST /v1/events/impression` ## Iframe ```html ``` Payload is base64url-encoded JSON: `{ request_id, session_id?, ads[] }`. ## postMessage - Parent → iframe: `{ type: "adsourcer:render", payload }` - iframe → parent: `{ type: "adsourcer:impression", request_id, ad_id, session_id? }` - iframe → parent: `{ type: "adsourcer:click", ad_id, click_url }` ## React Import `AdsourcerAdList` and pass the prefetched payload. Wire `onImpression` to your server proxy. --- # Advertiser guide Launch campaigns, connect products, and track performance. ## Getting started 1. Create an account (email/password or OAuth) 2. Add budget via Stripe top-up 3. Create campaign with daily/total budgets 4. Upload products — embeddings generated automatically 5. Build ad groups and link advertisements ## Create campaign ```bash curl -X POST http://localhost:8000/v1/campaigns \ -H "Authorization: Bearer ads_your_advertiser_key" \ -H "Content-Type: application/json" \ -d '{ "name": "Mechanical keyboards", "daily_budget": 500, "total_budget": 5000, "default_bid": 0.80, "targeting": { "regions": ["NO", "EU"], "categories": ["mechanical_keyboard"] } }' ``` ## Budget Daily and total budgets enforced transactionally — overspend prevented at auction time. - Dashboard billing page or `POST /v1/balance/topup` ## Analytics `GET /v1/analytics/advertiser` — spend, impressions, clicks, CTR, conversions, CPA by campaign. ---