API Reference
Bid Request
Orchestrates a multi-bidder auction across multiple DSPs and returns the winning ad creative in a single request
POST
Documentation Index
Fetch the complete documentation index at: https://docs.thrads.ai/llms.txt
Use this file to discover all available pages before exploring further.
Authorizations
Your API key for authentication. The key’s environment (
staging or production) determines how ads are served — see Staging vs. Production.Must be
application/jsonEnd-User Headers
These headers identify the real end-user behind the request. They are required on every bid request and every view URL ping.The end-user’s original IP address. Must be the real client IP, not your server’s IP.
The end-user’s original device/browser string exactly as received from the client.
Geolocation & Device Headers
The server resolves the user’s location and device from request headers. These are optional but strongly recommended for server-side integrations — sending them skips the server-side IP lookup and reduces latency.ISO 3166-1 alpha-2 country code (e.g.
"US", "DE"). When present, X-User-Device and X-User-Timezone are required.User’s device type:
"mobile" or "desktop". Required when X-User-Country is present. This is critical for device-targeted campaigns — without it, targeting will not work correctly.IANA timezone (e.g.
"America/Los_Angeles"). Required when X-User-Country is present. Used for time-of-day pacing.Region or state (e.g.
"CA", "Bavaria"). Optional but recommended for regional targeting.City name (e.g.
"San Francisco"). Optional but recommended for city-level targeting.X-Forwarded-For. For direct calls (browser or mobile app → our API), this is handled automatically by the load balancer. If you’re proxying requests through your own backend, you must forward the user’s IP via X-Forwarded-For — otherwise the server sees your server’s IP and geo will be wrong.
If unsure about which headers to send, contact marco@thrads.ai and we’ll help you set it up.
Body
Unique, anonymous user identifier (e.g. a UUID like
user_a1b2c3d4-...). Must be stable across sessions for the same user. Do not use email, name, or other PII. On web, store in localStorage; on mobile, use the platform’s persistent storage (e.g. UserDefaults on iOS, SharedPreferences on Android).contextual only Conversation identifier. One unique ID per conversation, not per user. Reset when user starts a new chat. Required when request_type is "contextual".contextual only Conversation history. Required when request_type is "contextual". Each message must have a role ("user" or "assistant") and content. PII (names, emails, addresses, etc.) should be masked or removed before sending.Publisher configuration for pacing, creative constraints, and analytics. All fields are optional — omitted fields fall back to defaults set on your chatbot in the platform dashboard.
Pipeline selector. Determines which ad pipeline runs and what fields are required.
"contextual"(default) — in-chat ads. RequireschatIdandmessages."opener"— pre-chat ads (e.g. sponsored prompts, banners).chatIdandmessagesare not required. Sponsored polls are not opener inventory.
Ad formats the publisher can render. The server picks the best match from this list.
- Contextual:
["sponsored_message"](default),["sponsored_poll"], or["sponsored_message", "sponsored_poll"]. - Opener:
["sponsored_message"],["sponsored_prompt"], or both. Defaults to["sponsored_prompt"]when omitted. Do not includesponsored_pollon opener requests.
sponsored_message and sponsored_poll, Thrad selects the campaign through the normal contextual auction, then uses campaign delivery settings to choose whether the returned creative is a message or poll.contextual only Current turn number in the conversation. Used for ad offset pacing and analytics. Must be >= 0. Only needed if you’re not calling the endpoint on every user-assistant exchange — if you are, the system derives this from the message count.contextual only Number of requests since the last ad was shown in this conversation. Used by the max frequency check. Optional — the system tracks this automatically. Only send this if you want to override the server-side counter.contextual only Publisher-provided conversation summary. Useful when you already have a summary from your chatbot and want to reduce latency.contextual only When true, the system serves an ad as a last resort even if the conversation context doesn’t strongly match any campaign. The normal pipeline (contextual scoring → retargeting → exploration) runs first; force only kicks in when everything else returns no bid. Hard filters (banned content, geo targeting, budget caps) still apply — force never overrides safety or budget constraints.We recommend starting without force (the default) and only enabling it if your fill rate is too low. See Maximising Fill Rate for guidance.User metadata for targeting and compliance. All fields are optional. Extra fields are accepted and stored for future use.
A
200 OK response with "bid": null is not an error - it means the auction ran successfully but no DSP submitted a winning bid. This is normal behavior.Response
Unique request identifier used in logs and tracing.
ISO 8601 timestamp of when the response was generated.
Total processing time for this request in seconds.
Response status:
"success" or "error".Human-readable message describing the result.
Response data payload.
Error details when
status = "error" (otherwise null).Status Codes
| Status Code | Meaning | Scenario |
|---|---|---|
200 OK | Success | Auction ran successfully (with or without winning bid), or pacing blocked |
400 Bad Request | Invalid input | Malformed request body or missing required fields |
401 Unauthorized | Authentication failed | Missing or invalid thrad-api-key |
403 Forbidden | Origin not allowed | Request from non-whitelisted domain (browser integration only) |
429 Too Many Requests | Rate limit exceeded | Publisher exceeded request quota |
500 Internal Server Error | Server error | DSP render failed, validation error, or internal exception |
