Adverteks OpenRTB Integration Guide
Adverteks is a real-time bidding exchange supporting OpenRTB 2.5. This guide covers everything external DSPs and SSPs need to connect, submit bids, receive win notices, and track ad events.
Base URL
Authentication
All partner management endpoints require an API key passed in the Authorization: Bearer {api_key} header. RTB bid endpoints are public — register as a partner first to receive your partner_id and api_key.
/api/rtb/bid, /api/rtb/win, /api/rtb/event) are public — use your partner_id inside request payloads as the identifier.
Rate Limits
| Endpoint | Limit | Window |
|---|---|---|
| POST /api/rtb/bid | 100 req/min | Per IP |
| GET /api/ad/serve/:zoneKey | 1,000 req/min | Per zone key |
| POST /api/auth/* | 3 req/hr | Per IP |
| General API | 30 req/min | Per IP |
Rate limit exceeded → HTTP 429 Too Many Requests with Retry-After header.
Bid Request
DSPs can submit bids directly to Adverteks via the inbound bid endpoint. Adverteks runs a unified second-price auction combining your bid with internal campaigns. Hard timeout: 200ms.
Submit an OpenRTB 2.5 bid request. Returns a full bid response on match, HTTP 204 on no-fill.
Bid Request Object
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | Required | Unique auction ID. Echoed in response and used in win notice as ${AUCTION_ID}. |
| imp | array | Required | Impression objects. At least one required. |
| imp[].id | string | Required | Impression identifier within this request. |
| imp[].banner | object | Optional | Banner object with w and h. Supported: 728×90, 300×250, 320×50. |
| imp[].bidfloor | float | Optional | Minimum CPM in USD. Default: 0.0. Zone floor pricing may override. |
| site.id | string | Optional | Zone key. Used to route bid to the correct publisher inventory. |
| device.geo.lat/lon | float | Optional | User coordinates. Enables geofence bid multipliers (0.8×–2.0×). |
| device.ip | string | Optional | User IP. Used for geo fallback and fraud detection. |
| at | integer | Optional | Auction type. 2 = Second price (always used). |
| tmax | integer | Optional | Timeout in ms. Adverteks enforces 200ms hard limit regardless of this value. |
Bid Response Object
| Field | Type | Description |
|---|---|---|
| id | string | Echoes bid request id. |
| seatbid[].bid[].id | string | Unique bid ID — use as ${AUCTION_BID_ID} in win notice. |
| seatbid[].bid[].price | float | Clearing price (CPM USD). What you'll be charged on win. |
| seatbid[].bid[].adm | string | Ad markup HTML with impression tracker and click URL. |
| seatbid[].bid[].nurl | string | Win notice URL with macro placeholders. Fire on win. |
| seatbid[].seat | string | Seat ID — use as ${AUCTION_SEAT_ID}. |
| cur | string | Always "USD". |
{
"id": "8a3f5d2b-1c47-4e89-b0a2-6f9e7d4c1b83",
"at": 2,
"tmax": 150,
"imp": [
{
"id": "1",
"banner": { "w": 300, "h": 250, "pos": 1 },
"bidfloor": 0.50,
"bidfloorcur": "USD",
"secure": 1
}
],
"site": {
"id": "zone_abc123",
"page": "https://example.com/article/sports",
"domain": "example.com",
"cat": ["IAB17"]
},
"device": {
"ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)...",
"ip": "203.0.113.42",
"geo": { "lat": 40.7128, "lon": -74.0060, "country": "USA" },
"devicetype": 4
},
"user": { "id": "usr_9c2e7f1a" }
}
{
"id": "8a3f5d2b-1c47-4e89-b0a2-6f9e7d4c1b83",
"cur": "USD",
"seatbid": [
{
"seat": "seat_adverteks_001",
"bid": [
{
"id": "bid_7e2a9f4d",
"impid": "1",
"price": 1.82,
"adid": "creative_445",
"adm": "<div class=\"ad-unit\">...</div>",
"nurl": "https://adverteks.com/api/rtb/win?auction_id=${AUCTION_ID}&price=${AUCTION_PRICE}&bid_id=${AUCTION_BID_ID}",
"w": 300,
"h": 250
}
]
}
]
}
No-Bid Handling
When no campaign matches the zone or no bid exceeds the floor, Adverteks returns:
DSPs should treat 204 as a no-fill and serve a passback or house ad.
Win Notice
Fire the win notice URL from the bid response after winning an auction. This confirms the impression, triggers budget deduction, and credits the publisher's 70% revenue share.
Fire win notice via POST body or GET (pixel nURL). Must be fired within 30 seconds of auction. Late notices are rejected and the impression is not billed.
| Parameter | Type | Required | Description |
|---|---|---|---|
| auction_id | string | Required | Original bid request id. Substitute ${AUCTION_ID}. |
| price | float | Required | Clearing price CPM in USD. Substitute ${AUCTION_PRICE}. |
| bid_id | string | Optional | Bid ID from response. Substitute ${AUCTION_BID_ID}. |
| seat_id | string | Optional | Seat ID. Substitute ${AUCTION_SEAT_ID}. |
Macro Substitution
| Macro | Example Value | Description |
|---|---|---|
| ${AUCTION_PRICE} | 1.82 | Clearing CPM in USD. Use for budget deduction. |
| ${AUCTION_ID} | 8a3f5d2b-1c47-... | Auction/bid request ID. Links win to original request. |
| ${AUCTION_BID_ID} | bid_7e2a9f4d | Bid ID from response seatbid[].bid[].id. |
| ${AUCTION_SEAT_ID} | seat_001 | Seat ID for multi-seat DSP routing. |
| ${AUCTION_IMP_ID} | 1 | Impression ID from the bid request. |
| ${AUCTION_AD_ID} | creative_445 | Ad creative ID selected for this impression. |
# Before substitution (from bid response):
https://adverteks.com/api/rtb/win?auction_id=${AUCTION_ID}&price=${AUCTION_PRICE}&bid_id=${AUCTION_BID_ID}
# After macro substitution (what actually fires):
https://adverteks.com/api/rtb/win?auction_id=8a3f5d2b-1c47-4e89-b0a2-6f9e7d4c1b83&price=1.82&bid_id=bid_7e2a9f4d
Event Tracking
Report impression, click, and billing events. Events update publisher earnings, campaign performance dashboards, and fraud scoring.
Report an ad event. All event types share this endpoint — differentiate via event_type.
| Field | Type | Required | Description |
|---|---|---|---|
| event_type | string | Required | One of: impression, click, billing. |
| auction_id | string | Required | Original auction ID. Links event to impression and auction records. |
| imp_id | string | Optional | Impression ID. Required for click events. |
| price | float | Optional | Clearing price. Required for billing events. Must match win notice price. |
| timestamp | integer | Optional | Unix epoch milliseconds. Defaults to server time if omitted. |
// Impression event
{ "event_type": "impression", "auction_id": "8a3f5d2b-...", "imp_id": "1" }
// Click event
{ "event_type": "click", "auction_id": "8a3f5d2b-...", "imp_id": "1" }
// Billing confirmation
{ "event_type": "billing", "auction_id": "8a3f5d2b-...", "price": 1.82 }
Ad Serving API
Publisher ad tags call this endpoint to retrieve a winning ad. Adverteks runs the unified auction (internal + external DSP bids) and returns the winning creative in under 200ms.
Fetch a winning ad for the given publisher zone. Returns ad markup, impression tracker, and click URL on match. HTTP 204 on no-fill.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| zoneKey | string | Required | Publisher ad zone key. Found in Dashboard → Ad Zones. |
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| lat | float | User latitude. Enables geofence bid multipliers. |
| lon | float | User longitude. Paired with lat. |
| format | string | Force format: 728x90, 300x250, 320x50. |
Response Format
{
"success": true,
"ad": {
"html": "<div class=\"adverteks-ad\">...</div>",
"width": 300,
"height": 250,
"impression_url": "https://adverteks.com/api/rtb/event?event_type=impression&auction_id=...",
"click_url": "https://adverteks.com/api/ad/click/imp_8f3a2c1d",
"creative_id": "creative_445",
"cpm": 1.82
},
"auction_id": "8a3f5d2b-1c47-4e89-b0a2-6f9e7d4c1b83"
}
Click Tracking
Track a click on a served ad. HTTP 302 redirect to the advertiser's destination after logging the click. impressionId is returned in ad.click_url from the serve response.
Ad Tag Embed
<div id="adverteks-ad-zone_abc123"></div>
<script src="https://adverteks.com/ad.js"
data-zone="zone_abc123"
data-container="adverteks-ad-zone_abc123"
async>
</script>
DSP / SSP Registration
External partners must be registered before traffic is exchanged. Registration is managed via the SuperAdmin panel or Admin API.
Registration Steps
partner_id and api_key. Include partner_id in all bid request payloads.Test Mode
- ✓ Bids validated — Your requests are received and validated but excluded from live auctions.
- ✓ No billing — Zero budget deduction. Test impressions are flagged in bid logs.
- ✓ Full responses — Bid responses returned with all fields populated for integration testing.
- ✓ Win notice simulation — Fire win notice URLs; events are logged but not charged.
Performance Monitoring
Partner performance stats: win rate, average CPM, fill rate, total spend, error rate.
{
"partner_id": "dsp_acme_001",
"status": "active",
"period": "24h",
"stats": {
"bid_requests_sent": 45230,
"bids_received": 38970,
"bid_rate": 0.862,
"wins": 1204,
"win_rate": 0.031,
"avg_clearing_cpm": 1.94,
"total_spend_usd": 2337.76,
"impressions": 1204,
"clicks": 47,
"ctr": 0.039,
"errors": 12,
"avg_response_time_ms": 84
}
}
Detailed bid request/response logs for debugging. Full JSON payloads, response times, auction outcomes.
| Query Param | Type | Description |
|---|---|---|
| limit | integer | Max records. Default: 50, Max: 500. |
| since | string | ISO 8601 timestamp filter. |
| outcome | string | Filter: win, loss, nobid, error. |
SSP Integration
External SSPs can connect to Adverteks as a demand-side buyer. Adverteks competes in your auctions using active advertiser campaigns, paying second-price cleared CPMs. Revenue split: publisher receives 70%, Adverteks platform retains 30% as a commission.
How It Works
/api/rtb/external/bid. Adverteks matches against live campaigns and returns a bid.nurl from the bid response to /api/rtb/external/win with the clearing price./api/rtb/external/event for billing reconciliation.Bid Request Endpoint
Send an OpenRTB 2.5 BidRequest to Adverteks. Returns a BidResponse if Adverteks has an eligible campaign, or HTTP 204 for no bid.
| Header | Required | Description |
|---|---|---|
| X-API-Key | Yes | Your SSP partner API key issued during onboarding. |
| Content-Type | Yes | Must be application/json. |
| x-openrtb-version | No | Recommend sending 2.5. |
{
"id": "ssp-auction-a1b2c3d4",
"imp": [{
"id": "1",
"banner": { "w": 728, "h": 90, "format": [{ "w": 728, "h": 90 }] },
"bidfloor": 0.50,
"bidfloorcur": "USD"
}],
"site": {
"domain": "publisher-site.com",
"page": "https://publisher-site.com/article/tech-news",
"publisher": { "id": "pub_001" }
},
"device": {
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...",
"ip": "203.0.113.0",
"devicetype": 2,
"geo": { "country": "US", "region": "CA" }
},
"user": {},
"at": 2,
"tmax": 150,
"cur": ["USD"]
}
{
"id": "ssp-auction-a1b2c3d4",
"bidid": "adx-resp-7f3e2a1b",
"seatbid": [{
"bid": [{
"id": "bid_9f2e7d4c",
"impid": "1",
"price": 1.26,
"adm": "<!-- Adverteks creative HTML -->",
"nurl": "https://adverteks.com/api/rtb/external/win?bid_id=bid_9f2e7d4c&auction_id=ssp-auction-a1b2c3d4&price=${AUCTION_PRICE}&partner_id=ssp_acme_001",
"w": 728,
"h": 90,
"crid": "cr_104"
}],
"seat": "adverteks"
}],
"cur": "USD"
}
price in the bid response is Adverteks' net bid after the 30% platform commission is deducted. Your SSP charges this price; Adverteks reconciles internally.
Win Notice
Notify Adverteks that its bid won the auction. Fire this when serving the Adverteks creative. Triggers billing and impression recording.
The win URL is pre-built in the nurl field of the bid response. Substitute ${AUCTION_PRICE} with the actual clearing price before firing.
| Query Param | Required | Description |
|---|---|---|
| bid_id | Yes | The id from the winning bid object. |
| auction_id | Yes | The original BidRequest id. |
| price | Yes | Clearing price CPM in USD (replace ${AUCTION_PRICE} macro). |
| partner_id | Yes | Your SSP partner ID. |
POST https://adverteks.com/api/rtb/external/win?bid_id=bid_9f2e7d4c&auction_id=ssp-auction-a1b2c3d4&price=1.26&partner_id=ssp_acme_001
Returns HTTP 200 on success. If already recorded, returns 409.
Event Notifications
Send impression, click, and viewability events for served Adverteks ads. Used for billing reconciliation and performance reporting.
| Query Param | Required | Description |
|---|---|---|
| event_type | Yes | impression, click, or viewable. |
| auction_id | Yes | The original BidRequest ID. |
| bid_id | No | The winning bid ID. |
| partner_id | Yes | Your SSP partner ID. |
POST /api/rtb/external/event?event_type=impression&auction_id=ssp-auction-a1b2c3d4&bid_id=bid_9f2e7d4c&partner_id=ssp_acme_001
Floor Price Configuration
Adverteks respects publisher-set floor prices. Include imp.bidfloor in each BidRequest impression. Adverteks will only return bids that meet or exceed the floor.
- ✓ Default floor — $0.50 CPM if no
bidfloorspecified. - ✓ Per-impression floor — Set
imp.bidfloorin each impression object. - ✓ Partner-level min floor — Configurable via the Admin API; overrides lower per-request floors.
- ✓ Currency — All floors and clearing prices in USD. Set
bidfloorcur: "USD".
Error Codes
Standard HTTP status codes and application-level error responses returned by the Adverteks API.
HTTP Status Codes
| Status | Meaning | Description |
|---|---|---|
200 OK |
Success | Request processed. Bid response, win notice, or event accepted. |
204 No Content |
No Bid | No eligible campaigns matched the request. Serve passback creative. |
400 Bad Request |
Invalid Payload | Malformed JSON or missing required OpenRTB fields (id, imp). |
401 Unauthorized |
Missing Auth | No X-API-Key header provided. |
403 Forbidden |
Auth Failed | Unknown API key, inactive partner, or wrong partner type (dsp vs ssp). |
409 Conflict |
Duplicate | Win notice already recorded for this bid_id. Safe to ignore. |
429 Too Many Requests |
Rate Limited | Exceeded 100 requests/min on RTB endpoints. Back off and retry with exponential delay. |
500 Internal Error |
Server Error | Unexpected server-side error. Retry with exponential backoff. If persistent, contact support. |
OpenRTB Error Responses
When a bid fails validation, Adverteks returns HTTP 400 with a JSON error object:
{
"error": "Invalid OpenRTB BidRequest — missing id or imp"
}
Common Error Scenarios
| Error | Cause | Fix |
|---|---|---|
| 401 — X-API-Key required | Missing header | Add X-API-Key: your_api_key to all requests. |
| 403 — Unknown or inactive SSP partner | Bad API key or partner suspended | Verify key. If suspended (error rate >20%), contact partnerships@adverteks.com. |
| 400 — missing id or imp | Invalid BidRequest structure | Ensure id, imp[] with at least one impression are present. |
| 400 — imp.bidfloor must be non-negative | Negative floor price | Set imp.bidfloor to 0 or a positive CPM value. |
| 204 — No fill | No eligible campaigns | Normal — serve your passback. Check floor price isn't too high. |
| 429 — Rate limit | 100+ req/min on RTB endpoints | Implement exponential backoff. Contact us if you need a higher limit. |
GET /api/admin/rtb-partners/:partnerId/stats.
Sending a Bid Request
Complete examples for submitting an OpenRTB 2.5 bid request to Adverteks.
curl -X POST https://adverteks.com/api/rtb/bid \
-H "Content-Type: application/json" \
-d '{
"id": "8a3f5d2b-1c47-4e89-b0a2-6f9e7d4c1b83",
"at": 2,
"tmax": 150,
"imp": [{"id":"1","banner":{"w":300,"h":250},"bidfloor":0.50}],
"site": {"id":"zone_abc123","page":"https://example.com/article"},
"device": {"ip":"203.0.113.42","geo":{"lat":40.7128,"lon":-74.0060}}
}'
const { randomUUID } = require('crypto');
async function sendBidRequest(zoneKey, geo = {}) {
const bidRequest = {
id: randomUUID(),
at: 2,
tmax: 150,
imp: [{ id: '1', banner: { w: 300, h: 250 }, bidfloor: 0.50, secure: 1 }],
site: { id: zoneKey, page: 'https://example.com/article' },
device: {
ip: geo.ip || '0.0.0.0',
geo: geo.lat ? { lat: geo.lat, lon: geo.lon, country: 'USA' } : undefined
}
};
const resp = await fetch('https://adverteks.com/api/rtb/bid', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(bidRequest),
signal: AbortSignal.timeout(200)
});
if (resp.status === 204) { console.log('No fill'); return null; }
const data = await resp.json();
const bid = data.seatbid?.[0]?.bid?.[0];
if (bid) {
console.log(`Won at $${bid.price} CPM`);
// Substitute macros and fire win notice
const winUrl = bid.nurl
.replace('${AUCTION_PRICE}', bid.price)
.replace('${AUCTION_ID}', bidRequest.id)
.replace('${AUCTION_BID_ID}', bid.id);
await fetch(winUrl, { method: 'POST' });
}
return data;
}
sendBidRequest('zone_abc123', { ip: '203.0.113.42', lat: 40.7128, lon: -74.0060 });
import uuid
import httpx # pip install httpx
BASE = "https://adverteks.com"
def send_bid_request(zone_key: str, geo: dict = None) -> dict | None:
payload = {
"id": str(uuid.uuid4()),
"at": 2, "tmax": 150,
"imp": [{"id": "1", "banner": {"w": 300, "h": 250}, "bidfloor": 0.50}],
"site": {"id": zone_key, "page": "https://example.com"},
}
if geo:
payload["device"] = {
"ip": geo.get("ip", "0.0.0.0"),
"geo": {"lat": geo["lat"], "lon": geo["lon"], "country": "USA"},
}
with httpx.Client(timeout=0.2) as c:
r = c.post(f"{BASE}/api/rtb/bid", json=payload)
if r.status_code == 204:
print("No fill")
return None
r.raise_for_status()
data = r.json()
bid = data.get("seatbid", [{}])[0].get("bid", [None])[0]
if bid:
price = bid["price"]
print(f"Won at ${price:.4f} CPM")
win_url = (bid["nurl"]
.replace("${AUCTION_PRICE}", str(price))
.replace("${AUCTION_ID}", payload["id"])
.replace("${AUCTION_BID_ID}", bid["id"]))
httpx.post(win_url)
return data
send_bid_request("zone_abc123", geo={"ip": "203.0.113.42", "lat": 40.7128, "lon": -74.0060})
Firing a Win Notice
Fire win notices immediately after auction wins to confirm impressions.
# Via GET (pixel / nURL)
curl "https://adverteks.com/api/rtb/win?auction_id=8a3f5d2b-1c47&price=1.82&bid_id=bid_7e2a9f4d"
# Via POST body
curl -X POST https://adverteks.com/api/rtb/win \
-H "Content-Type: application/json" \
-d '{"auction_id":"8a3f5d2b-1c47-4e89-b0a2-6f9e7d4c1b83","price":1.82,"bid_id":"bid_7e2a9f4d"}'
async function fireWinNotice({ auctionId, price, bidId, seatId }) {
const resp = await fetch('https://adverteks.com/api/rtb/win', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ auction_id: auctionId, price, bid_id: bidId, seat_id: seatId })
});
return resp.ok;
}
// Or substitute macros in the nURL from bid response:
async function fireNurl(nurlTemplate, { price, auctionId, bidId }) {
const url = nurlTemplate
.replace('${AUCTION_PRICE}', price)
.replace('${AUCTION_ID}', auctionId)
.replace('${AUCTION_BID_ID}', bidId);
await fetch(url); // GET or POST both work
}
import httpx
def fire_win_notice(auction_id: str, price: float, bid_id: str):
resp = httpx.post(
"https://adverteks.com/api/rtb/win",
json={"auction_id": auction_id, "price": price, "bid_id": bid_id},
)
if resp.status_code == 200:
print(f"Win recorded — auction {auction_id} at ${price:.4f}")
else:
print(f"Win notice failed: {resp.status_code}")
Ad Serving & Click Tracking
Fetch ads programmatically or embed the Adverteks tag on any publisher page.
# Serve an ad
curl "https://adverteks.com/api/ad/serve/zone_abc123?lat=40.7128&lon=-74.0060"
# Force 728x90 leaderboard
curl "https://adverteks.com/api/ad/serve/zone_abc123?format=728x90"
# Track a click (follow redirects)
curl -L "https://adverteks.com/api/ad/click/imp_8f3a2c1d"
async function loadAd(zoneKey, container, geo = {}) {
const params = new URLSearchParams(
Object.fromEntries(Object.entries(geo).filter(([,v]) => v != null))
);
const resp = await fetch(`https://adverteks.com/api/ad/serve/${zoneKey}?${params}`);
if (resp.status === 204) {
container.innerHTML = ''; // no fill — serve passback
return;
}
const { ad } = await resp.json();
container.innerHTML = ad.html;
// Fire impression pixel
new Image().src = ad.impression_url;
// Wrap clicks through Adverteks tracker
container.querySelectorAll('a').forEach(a => { a.href = ad.click_url; });
}
loadAd('zone_abc123', document.getElementById('ad-slot'), { lat: 40.7128, lon: -74.0060 });
import httpx
def fetch_ad(zone_key: str, lat: float = None, lon: float = None) -> dict | None:
params = {}
if lat is not None:
params.update({"lat": lat, "lon": lon})
r = httpx.get(f"https://adverteks.com/api/ad/serve/{zone_key}", params=params)
if r.status_code == 204:
print("No fill — serving passback")
return None
r.raise_for_status()
ad = r.json()["ad"]
print(f"Served {ad['width']}x{ad['height']} at ${ad['cpm']:.4f} CPM")
return ad
ad = fetch_ad("zone_abc123", lat=40.7128, lon=-74.0060)