Adverteks API Reference

Complete reference for the Adverteks programmatic advertising platform. Connect external DSPs and SSPs, manage campaigns, and integrate with the OpenRTB 2.5 auction engine.

Base URL

https://adverteks.com

Authentication

Two authentication methods depending on integration type.

JWT Bearer Token (DSP and SSP APIs)

User-facing endpoints require a signed JWT. Obtain one via the login endpoint and include it as a Bearer token.

Request Header
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
POST /api/auth/login
{
  "email": "your@email.com",
  "password": "your-password"
}
Response
{
  "success": true,
  "token": "eyJhbGci...",
  "user": { "id": 42, "email": "your@email.com", "role": "advertiser" }
}

Tokens expire after 7 days. Re-authenticate to refresh.

API Key (RTB / OpenRTB 2.5 Endpoints)

External DSP partners authenticate using an API key issued by Adverteks. Contact partners@adverteks.com to obtain credentials.

Request Header (either format accepted)
X-Api-Key: adtks_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
# or
Authorization: Bearer adtks_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
i
Inbound vs Outbound RTB. The /api/rtb/bid endpoint is inbound — external DSPs call you. Adverteks also operates an outbound connector where the platform bids on external SSP inventory. Both paths use the same API key scheme with optional HMAC request signing.

Rate Limits & SLA — Per Endpoint

Limits enforced per IP or API key, sliding windows. RTB limits key on the X-Api-Key header; all others key on client IP (behind Cloudflare/Render proxy). When exceeded, the API returns 429 with a Retry-After header (seconds until window resets).

Endpoint GroupLimitWindowKey ByNotes
/api/rtb/bid1,000 req1 minAPI keyCore RTB endpoint — configurable per partner
/api/rtb/win1,000 req1 minAPI keyWin notice endpoint
/api/rtb/event1,000 req1 minAPI keyEvent tracking endpoint
/api/rtb/external/*1,000 req1 minAPI keyExternal partner RTB endpoints
/api/hb/bid500 req1 minIPHeader bidding — no auth required (browser calls)
/api/hb/win500 req1 minIPHeader bidding win notice
/api/ad/serve/*1,000 req1 minZone keyAd tag serving (public endpoint)
/api/ad/click/*500 req1 minIPClick tracking redirect
/api/auth/login5 failures1 minIPOnly failed attempts count; successes don't
/api/auth/signup3 req1 hourIPAccount creation throttle
/api/auth/forgot-password3 req1 hourIPPassword reset requests
/api/auth/mfa/*10 req15 minIPMFA setup and verification attempts
/api/auth/resend-verification3 req1 hourIPEmail verification resend
/api/advertiser/billing/deposit10 req1 hourUserDeposit initiation; requires re-auth
/api/publisher/earnings/withdraw5 req1 hourUserWithdrawal initiation; requires re-auth
/api/v1/affiliate/*60 req1 minIPAffiliate program endpoints
/api/* (general)60 req1 minIPDefault for all unspecified endpoints
i
Sandbox keys use lower limits: RTB endpoints are capped at 100 req/min for adtks_test_* keys. All other sandbox limits match production.

Latency SLA

Bid Response Target
< 100ms
p50 auction-to-response time
Bid Response P95
< 200ms
95th percentile SLA
Default Timeout
200ms
tmax default; set lower to fail fast
Ad Serving
< 50ms
Tag render time target
i
Timeout Policy. If Adverteks does not return a bid within tmax milliseconds, treat the response as a no-bid (204). The tmax field in your BidRequest is honored; minimum accepted value is 50ms, maximum is 30,000ms. We recommend 150ms for competitive fill.

Auth Endpoints

Full endpoint reference for user registration, login, token refresh, and account management. All user-facing APIs require a valid JWT obtained from /api/auth/login.

POST /api/auth/signup Register a new publisher account

Creates a publisher account. Returns a JWT on success and sends an email verification link.

Request Body

FieldTypeRequiredDescription
emailstringRequiredValid email address. Must be unique.
passwordstringRequiredMinimum 8 characters.
company_namestringOptionalPublisher company or website name.
cURL Example
curl -X POST https://adverteks.com/api/auth/signup \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"securepass123","company_name":"My Site"}'
Response 201
{"success":true,"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","user":{"id":42,"email":"you@example.com","role":"publisher"}}
POST /api/advertiser/signup Register a new advertiser account

Creates an advertiser (DSP) account with a wallet initialized to $0.00. Requires email verification before campaigns can go live.

Request Body
{"email":"ads@agency.com","password":"securepass123","company_name":"Agency Inc"}
POST /api/auth/login Authenticate and receive JWT

Validates credentials and returns a short-lived access token (15 minutes) and a long-lived refresh token (7 days). Re-authenticate to get a new pair before the access token expires.

Request Body

FieldTypeRequiredDescription
emailstringRequiredRegistered email address.
passwordstringRequiredAccount password.
mfa_codestringConditional6-digit TOTP code. Required if MFA is enabled on account.
cURL Example
curl -X POST https://adverteks.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"securepass123"}'
Response 200
{
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": 42,
    "email": "you@example.com",
    "role": "publisher",
    "email_verified": true,
    "mfa_enabled": false
  }
}
i
Rate limit: 5 failed attempts per minute per IP. Successful logins do not count against the limit.
POST /api/auth/refresh Exchange refresh token for new access token

Issue a fresh JWT without requiring the user to re-enter credentials. Use this to maintain sessions beyond the 15-minute access token window.

Request Body
{"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}
Response 200
{"success":true,"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}
POST /api/auth/logout Revoke session tokens

Invalidates the current access and refresh tokens. Subsequent requests with the old token return 401.

Request (no body required)
curl -X POST https://adverteks.com/api/auth/logout \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
GET /api/auth/me Fetch authenticated user profile

Returns the user object for the authenticated token. Use to verify token validity and read account state.

Response 200
{
  "success": true,
  "user": {
    "id": 42,
    "email": "you@example.com",
    "role": "publisher",
    "email_verified": true,
    "mfa_enabled": true,
    "created_at": "2026-01-15T10:23:00Z"
  }
}

Password Reset

POST /api/auth/forgot-password Request password reset email
Request
{"email": "you@example.com"}

Sends a password reset link valid for 1 hour. Always returns 200 to prevent email enumeration.

POST /api/auth/reset-password Complete password reset
Request
{"token": "RESET_TOKEN_FROM_EMAIL", "password": "newSecurePass123"}

Multi-Factor Authentication (TOTP)

Adverteks supports TOTP-based MFA (compatible with Google Authenticator, Authy, 1Password, etc.) and hardware keys via WebAuthn/FIDO2.

EndpointMethodDescription
/api/auth/mfa/setupPOSTGenerate TOTP secret + QR code URI. Auth required.
/api/auth/mfa/verifyPOSTSubmit first TOTP code to complete MFA enrollment.
/api/auth/mfa/disablePOSTDisable TOTP. Requires current TOTP code + password.
/api/auth/mfa/statusGETReturns {"enabled": true/false}.
/api/auth/v2/mfa/regenerate-recoveryPOSTGenerate new single-use recovery codes (invalidates old set).
MFA Setup Flow (cURL)
# Step 1 — get secret + QR
curl -X POST https://adverteks.com/api/auth/mfa/setup \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json"
# → returns: {"secret":"BASE32SECRET","qr":"otpauth://totp/..."}

# Step 2 — confirm with first TOTP code to activate
curl -X POST https://adverteks.com/api/auth/mfa/verify \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","mfa_code":"123456"}'

WebAuthn / Passkeys

Passwordless login via hardware security keys (YubiKey, Touch ID, Windows Hello). Registration and authentication use the WebAuthn Ceremony API.

EndpointMethodDescription
/api/auth/webauthn/register/optionsPOSTStart registration ceremony — returns challenge.
/api/auth/webauthn/registerPOSTComplete registration with authenticator response.
/api/auth/webauthn/authenticate/optionsPOSTStart authentication ceremony — returns challenge.
/api/auth/webauthn/authenticatePOSTComplete authentication — returns JWT on success.
/api/auth/webauthn/credentialsGETList registered passkeys/credentials.
/api/auth/webauthn/credentials/:idDELETERevoke a passkey credential.

RTB Integration (OpenRTB 2.5)

Adverteks implements IAB OpenRTB 2.5 for inbound bid requests. External DSPs submit a BidRequest and receive a BidResponse or HTTP 204 for no-bid.

Protocol
OpenRTB
IAB OpenRTB 2.5
Auction Type
2nd Price
Cleared at 2nd highest + $0.01
Floor CPM
$0.50
Default; configurable per partner
Max Timeout
200ms
Default tmax value

HMAC-SHA256 Request Signing

Adverteks supports optional HMAC-SHA256 request signing for RTB partners. When enabled, every BidRequest must include an X-Signature-SHA256 header. Requests without a valid signature are rejected with 401.

!
Fail-closed. Once HMAC signing is enabled for your partner account, all requests without a valid signature will be rejected — there is no fallback to unauthenticated requests.

Signature Format

HeaderValue Format
X-Signature-SHA256sha256=<hex-digest>
X-Api-KeyYour partner API key (always required)

The signature is computed as HMAC-SHA256 over the raw request body bytes using your HMAC secret (different from your API key). Both credentials are issued together during partner onboarding.

Node.js — Generate HMAC Signature
const crypto = require('crypto');
const https  = require('https');

const API_KEY     = 'adtks_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const HMAC_SECRET = 'your-hmac-secret-from-onboarding';
const HOST        = 'adverteks.com';

function buildSignatureHeaders(bodyString, apiKey, secret) {
  const sig = crypto
    .createHmac('sha256', secret)
    .update(bodyString, 'utf8')
    .digest('hex');
  return {
    'Content-Type':       'application/json',
    'X-Api-Key':          apiKey,
    'X-OpenRTB-Version':  '2.5',
    'X-Signature-SHA256': `sha256=${sig}`,
  };
}

async function sendBidRequest(bidRequest) {
  const body    = JSON.stringify(bidRequest);
  const headers = buildSignatureHeaders(body, API_KEY, HMAC_SECRET);

  const res = await fetch(`https://${HOST}/api/rtb/bid`, {
    method:  'POST',
    headers,
    body,
  });

  if (res.status === 204) return null;           // no-bid
  return res.json();
}
Python — Generate HMAC Signature
import hmac
import hashlib
import json
import urllib.request

API_KEY     = 'adtks_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx'
HMAC_SECRET = 'your-hmac-secret-from-onboarding'
ENDPOINT    = 'https://adverteks.com/api/rtb/bid'

def build_signature_headers(body_bytes: bytes, api_key: str, secret: str) -> dict:
    sig = hmac.new(
        secret.encode('utf-8'),
        body_bytes,
        hashlib.sha256
    ).hexdigest()
    return {
        'Content-Type':       'application/json',
        'X-Api-Key':          api_key,
        'X-OpenRTB-Version':  '2.5',
        'X-Signature-SHA256': f'sha256={sig}',
    }

def send_bid_request(bid_request: dict):
    body    = json.dumps(bid_request).encode('utf-8')
    headers = build_signature_headers(body, API_KEY, HMAC_SECRET)

    req = urllib.request.Request(ENDPOINT, data=body, headers=headers, method='POST')
    try:
        with urllib.request.urlopen(req, timeout=0.2) as resp:
            if resp.status == 200:
                return json.loads(resp.read())
            return None  # 204 no-bid
    except urllib.error.HTTPError as e:
        if e.code == 204:
            return None  # no-bid
        raise
POST /api/rtb/bid Submit an OpenRTB 2.5 bid request

The primary inbound RTB endpoint. Submit an OpenRTB 2.5 BidRequest and receive a BidResponse, or 204 No Content when no eligible bid exists.

!
Banner only. Only banner impression objects are supported. Requests with video, native, or audio only return 204.

Request Headers

HeaderRequiredDescription
Content-TyperequiredMust be application/json
X-Api-KeyoptionalDSP partner API key. If omitted, processed as anonymous.
X-OpenRTB-VersionoptionalShould be 2.5

BidRequest Fields

FieldTypeRequiredDescription
idstringrequiredUnique auction ID (UUID recommended)
imparrayrequiredArray of impression objects; at least one must have a banner child
imp[].idstringrequiredImpression identifier within this request
imp[].bannerobjectrequiredBanner object with w x h or format array
imp[].bidfloorfloatoptionalMinimum bid CPM USD. Effective floor = max(bidfloor, partner floor)
imp[].bidfloorcurstringoptionalCurrency of bidfloor. Default: USD
siteobjectoptionalSite context (page, domain, cat)
userobjectoptionalUser context (id, buyeruid)
geoobjectoptionalGeo targeting (lat, lon, country, city)
tmaxintegeroptionalMax response time ms. Default 200.

Supported Banner Sizes

FormatDimensionsIAB Name
leaderboard728 x 90IAB Leaderboard
medium_rectangle300 x 250IAB Medium Rectangle
mobile_banner320 x 50IAB Mobile Banner
wide_skyscraper160 x 600IAB Wide Skyscraper
Example Bid Request
{
  "id": "7f3d2a11-c4b8-4e9a-b2f1-a3c9e8d72f01",
  "imp": [{
    "id": "1",
    "banner": {
      "w": 300,
      "h": 250,
      "format": [{ "w": 300, "h": 250 }],
      "pos": 1
    },
    "bidfloor": 0.50,
    "bidfloorcur": "USD"
  }],
  "site": {
    "page": "https://example.com/article",
    "domain": "example.com",
    "cat": ["IAB1", "IAB12"]
  },
  "geo": {
    "lat": 40.7128,
    "lon": -74.0060,
    "country": "USA",
    "city": "New York"
  },
  "user": { "id": "user-seg-abc123" },
  "tmax": 150
}

Response

200 OK Bid found — returns OpenRTB 2.5 BidResponse.
204 No Content No eligible bid (below floor, no banner, or no budget).
400 Bad Request Invalid BidRequest.

Example Bid Response (200)
{
  "id": "7f3d2a11-c4b8-4e9a-b2f1-a3c9e8d72f01",
  "seatbid": [{
    "bid": [{
      "id": "bid-a9c3e1f2",
      "impid": "1",
      "price": 1.85,
      "adid": "creative-78",
      "adm": "",
      "adomain": ["brand.com"],
      "crid": "cr-4d9a2f",
      "w": 300,
      "h": 250,
      "nurl": "https://adverteks.com/api/rtb/win?aid=${AUCTION_ID}&price=${AUCTION_PRICE}"
    }],
    "seat": "adverteks"
  }],
  "cur": "USD"
}
POST /api/rtb/win Win notice — fired when bid wins the auction

Notify Adverteks when a bid wins downstream. The nurl in BidResponse uses macro substitution.

Win Notice Macros

MacroDescription
${AUCTION_ID}Unique auction ID from BidRequest id field
${AUCTION_PRICE}Winning clearing price in CPM USD (second-price)
${AUCTION_IMP_ID}Impression ID from imp[].id
${AUCTION_BID_ID}Bid ID from the BidResponse
POST body
{
  "auction_id": "7f3d2a11-c4b8-4e9a-b2f1-a3c9e8d72f01",
  "clearing_price": 1.42,
  "imp_id": "1"
}

Returns 200 OK on success.

POST /api/rtb/event Track impression / click / conversion events

Send downstream event notifications for attribution and analytics.

FieldTypeRequiredDescription
auction_idstringrequiredAuction ID from the original BidRequest
event_typestringrequiredimpression | click | conversion
timestampintegeroptionalUnix timestamp ms. Defaults to server receive time.
revenuefloatoptionalConversion revenue in USD

External RTB Partner Endpoints

Dedicated endpoints for external DSP/SSP partners integrated via the Adverteks Exchange. These mirror the core RTB endpoints but use partner-specific authentication and logging.

i
Approval required. Access to /api/rtb/external/* endpoints requires a confirmed RTB partner agreement. Contact partners@adverteks.com to begin onboarding.
POST /api/rtb/external/bid External DSP bid request (partner-authenticated)

Identical to /api/rtb/bid in request/response format. Uses separate partner rate limits and bid-log tracking for attribution and reconciliation. HMAC-SHA256 signing follows the same scheme (see HMAC Signing).

Partner-Specific Headers

HeaderRequiredDescription
X-Api-KeyRequiredYour partner API key (prefix: adtks_live_)
X-Partner-IDOptionalYour registered partner ID for enhanced logging
X-Signature-SHA256OptionalHMAC-SHA256 of raw body. Required for production partners.
External Bid Request
curl -X POST https://adverteks.com/api/rtb/external/bid \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: adtks_live_YOUR_KEY" \
  -H "X-OpenRTB-Version: 2.5" \
  -d '{
    "id": "ext-auction-001",
    "imp": [{"id":"1","banner":{"w":300,"h":250},"bidfloor":0.50}],
    "site": {"page":"https://partner-site.com/page","domain":"partner-site.com"},
    "tmax": 150
  }'
POST /api/rtb/external/win External partner win notice

Notify Adverteks of a win on external inventory. Triggers billing, publisher revenue credit, and impression recording with demand_source: 'external_rtb'.

Win Notice
POST /api/rtb/external/win?aid=ext-auction-001&price=1.42
X-Api-Key: adtks_live_YOUR_KEY
POST /api/rtb/external/event Track events from external demand

Same payload schema as /api/rtb/event. Records impression, click, and conversion events attributed to external partner demand.

Event Payload
{"auction_id":"ext-auction-001","event_type":"impression"}

Header Bidding (Prebid.js)

Adverteks provides a native Prebid.js bid adapter. Publishers using Prebid can include Adverteks demand alongside other bidders without additional server-side infrastructure.

Protocol
Prebid.js
ES6 module bid adapter
Auth
publisherId
Publisher user ID in bid params
Latency target
<100ms
Hard tmax enforcement
CORS
Allowed
Browser-side calls permitted

Setup — Prebid.js via CDN

1. Download Prebid with Adverteks adapter
# Build Prebid.js bundle including the Adverteks adapter:
gulp build --modules=adverteksBidAdapter

# Or use the pre-built bundle from Adverteks CDN:
# https://adverteks.com/sdk/adverteksBidAdapter.js
2. Configure Prebid ad unit
const adUnits = [{
  code: 'div-header-banner',
  mediaTypes: {
    banner: { sizes: [[728, 90], [300, 250]] }
  },
  bids: [{
    bidder: 'adverteks',
    params: {
      publisherId: 42,        // Your Adverteks publisher user ID (required)
      siteId: 'site-001',     // Optional: your registered site ID
      floorCpm: 0.50          // Optional: minimum CPM you'll accept
    }
  }]
}];

pbjs.addAdUnits(adUnits);
pbjs.requestBids({ bidsBackHandler: sendAdServerRequest, timeout: 1000 });
*
publisherId is your Adverteks user account ID — find it in your publisher dashboard under Settings → Account. This is the integer user ID, not a zone key.
POST /api/hb/bid Header bidding endpoint — Prebid.js compatible

Called automatically by the Adverteks Prebid.js adapter. Publishers building custom integrations can call this endpoint directly. No API key required — authentication is via params.publisherId.

i
CORS enabled. This endpoint allows cross-origin requests from any origin, making it safe to call directly from publisher page JavaScript.

Request Body (Prebid bid request format)

FieldTypeRequiredDescription
idstringOptionalAuction ID for tracking
bidsarrayRequiredArray of bid slot objects (see below)
pagestringOptionalURL of the publisher page (improves targeting)
tmaxintegerOptionalTimeout in ms (default 500, max 1000)

Bid Slot Object Fields

FieldTypeRequiredDescription
bidIdstringRequiredUnique ID for this bid slot (echoed back in response)
params.publisherIdintegerRequiredAdverteks publisher user ID
sizesarrayOptionalFallback sizes: [[300,250],[728,90]]
mediaTypes.banner.sizesarrayOptionalPreferred sizes (takes priority over sizes)
params.floorCpmfloatOptionalMinimum CPM floor (default 0.10)
params.siteIdstringOptionalRegistered site ID for better analytics
Example Request
curl -X POST https://adverteks.com/api/hb/bid \
  -H "Content-Type: application/json" \
  -d '{
    "id": "req-001",
    "bids": [{
      "bidId": "bid-slot-1",
      "params": {"publisherId": 42, "floorCpm": 0.50},
      "mediaTypes": {"banner": {"sizes": [[300,250],[728,90]]}},
      "page": "https://mypublishersite.com/article"
    }],
    "tmax": 300
  }'
Response — Prebid-compatible bid array
{
  "id": "req-001",
  "bids": [{
    "requestId": "bid-slot-1",
    "cpm": 1.42,
    "currency": "USD",
    "width": 300,
    "height": 250,
    "ad": "<!-- creative HTML -->",
    "ttl": 30,
    "creativeId": "cr-4d9a2f",
    "netRevenue": true,
    "meta": {"advertiserDomains": [], "mediaType": "banner"},
    "_adtk": {
      "publisherId": 42,
      "campaignId": 101,
      "creativeId": "cr-4d9a2f",
      "adFormat": "300x250"
    }
  }]
}

An empty bids: [] array means no fill for that slot. Prebid handles this as a no-bid automatically.

POST /api/hb/win Win notice — fires when Adverteks wins the header bidding auction

Called by the Prebid.js adapter via sendBeacon when the Adverteks bid wins the client-side auction and the ad renders. Triggers billing (advertiser wallet deduction) and publisher revenue credit (70% rev share).

Request Body

FieldTypeRequiredDescription
publisherIdintegerRequiredPublisher user ID (from bid response _adtk.publisherId)
campaignIdintegerRequiredCampaign ID from bid response
cpmfloatRequiredWinning CPM (clearing price)
creativeIdstringOptionalCreative ID for tracking
adFormatstringOptionale.g. "300x250"
pageUrlstringOptionalPublisher page URL for impression logging
Win Notice (called by Prebid adapter automatically)
curl -X POST https://adverteks.com/api/hb/win \
  -H "Content-Type: application/json" \
  -d '{
    "publisherId": 42,
    "campaignId": 101,
    "cpm": 1.42,
    "creativeId": "cr-4d9a2f",
    "adFormat": "300x250",
    "pageUrl": "https://mypublishersite.com/article"
  }'
Response
{"ok": true}

adverteksBidAdapter.js

The official Adverteks Prebid.js bid adapter is hosted at:

https://adverteks.com/sdk/adverteksBidAdapter.js

The adapter handles: bid request construction, timeout enforcement (tmax), win notice via navigator.sendBeacon, and GDPR/CCPA consent string forwarding.

Bidder Code

{ bidder: 'adverteks', params: { publisherId: 42 } }

Supported Media Types

Media TypeStatusNotes
banner✅ Supported728×90, 300×250, 320×50, 160×600
videoRoadmapVAST 4.0 in development
nativeRoadmapPlanned Q3 2026

DSP API

Manage advertising campaigns, creatives, audience targeting, and budgets. All endpoints require a valid JWT Bearer token.

GET /api/advertiser/campaigns List all campaigns
Example Response
{
  "success": true,
  "campaigns": [{
    "id": 101,
    "name": "Summer Sale 2026",
    "status": "active",
    "budget_total": 5000.00,
    "budget_daily": 200.00,
    "budget_spent": 842.30,
    "bid_strategy": "cpm",
    "bid_amount": 2.50,
    "start_date": "2026-06-01",
    "end_date": "2026-06-30",
    "targeting": {
      "geo": ["US", "CA"],
      "categories": ["IAB1"],
      "device_types": ["desktop", "mobile"]
    },
    "impressions": 421540,
    "clicks": 3082,
    "ctr": 0.73
  }]
}
POST /api/advertiser/campaigns Create a new campaign
FieldTypeRequiredDescription
namestringrequiredCampaign display name (max 255 chars)
budget_totalfloatrequiredTotal campaign budget in USD
budget_dailyfloatoptionalDaily spend cap in USD
bid_strategystringrequiredcpm | cpc | cpa
bid_amountfloatrequiredMax bid in USD per event
start_datestringoptionalISO 8601 date YYYY-MM-DD. Defaults to today.
end_datestringoptionalISO 8601 date. Null = indefinite.
targetingobjectoptionalAudience targeting rules

Targeting Object

FieldTypeDescription
geostring[]ISO 3166-1 alpha-2 country codes e.g. ["US","GB"]
categoriesstring[]IAB content categories e.g. ["IAB1","IAB12"]
device_typesstring[]desktop | mobile | tablet
ad_formatsstring[]728x90 | 300x250 | 320x50 | 160x600
geofence_idsinteger[]IDs of geofence zones for hyper-local targeting
Example Request
{
  "name": "Q2 Brand Awareness",
  "budget_total": 10000,
  "budget_daily": 500,
  "bid_strategy": "cpm",
  "bid_amount": 3.00,
  "start_date": "2026-04-01",
  "targeting": {
    "geo": ["US"],
    "device_types": ["desktop", "mobile"],
    "ad_formats": ["300x250", "728x90"]
  }
}
PUT /api/advertiser/campaigns/:id Update campaign settings

Modify an existing campaign. Only fields included in the request body are updated (partial update). Paused campaigns can be reactivated by setting "status": "active".

Updatable Fields

FieldTypeDescription
namestringCampaign display name
statusstringactive | paused
budget_dailyfloatNew daily budget cap in USD
budget_totalfloatNew lifetime budget cap in USD
bid_cpmfloatUpdated max bid CPM
targetingobjectReplaces the entire targeting config (see Create Campaign)
start_datestringISO 8601 date
end_datestringISO 8601 date
cURL — Pause campaign
curl -X PUT https://adverteks.com/api/advertiser/campaigns/101 \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{"status": "paused"}'
DELETE /api/advertiser/campaigns/:id Delete a campaign

Permanently deletes a campaign and all associated creatives. Historical impression and analytics data is retained. Returns 200 {"success":true}.

!
Irreversible. This cannot be undone. Pause instead if you may want to resume later.
POST /api/advertiser/campaigns/:id/creatives Add a creative to a campaign
FieldTypeRequiredDescription
namestringrequiredInternal creative name
ad_formatstringrequired728x90 | 300x250 | 320x50 | 160x600
typestringrequiredimage | html
image_urlstringoptionalHTTPS URL to creative image (for image type)
html_contentstringoptionalRaw HTML markup (for html type). Max 64KB.
click_urlstringrequiredLanding page URL (HTTPS)
third_party_tracking_urlstringoptionalImpression tracking pixel URL
GET /api/advertiser/analytics Campaign performance analytics

Query Parameters

ParameterTypeDescription
campaign_idintegerFilter to specific campaign
start_datestringISO 8601 date YYYY-MM-DD
end_datestringISO 8601 date
granularitystringhour | day | week. Default: day
Example Response
{
  "success": true,
  "analytics": [{
    "date": "2026-03-22",
    "impressions": 84210,
    "clicks": 612,
    "ctr": 0.73,
    "spend": 210.53,
    "cpm": 2.50,
    "cpc": 0.34,
    "conversions": 14
  }]
}

Advertiser Billing & Wallet

Manage your advertising budget. Deposit funds, view transaction history, and download receipts. All spend is pre-paid — campaigns pause automatically when the wallet hits $0.

Model
Pre-paid
No credit — spend from balance
Currency
USD
All billing in US dollars
Min deposit
$10
Via Stripe checkout
Auto-pause
Yes
Campaigns pause at $0 balance
GET /api/advertiser/billing Get wallet balance and billing summary
Response 200
{
  "success": true,
  "billing": {
    "balance": 142.50,
    "total_deposited": 500.00,
    "total_spent": 357.50,
    "currency": "USD",
    "auto_pause_threshold": 0.00
  }
}
POST /api/advertiser/billing/deposit Create a deposit (Stripe checkout)

Initiates a Stripe-powered deposit. Returns a checkout_url — redirect the user to complete payment. Balance is credited immediately on successful payment.

i
Re-auth required. This endpoint requires a short-lived re-auth token obtained from POST /api/auth/reauth. The re-auth token expires in 5 minutes.

Request Body

FieldTypeRequiredDescription
amount_usdfloatRequiredDeposit amount in USD (minimum $10.00)
success_urlstringOptionalRedirect URL after successful payment
cURL Example
curl -X POST https://adverteks.com/api/advertiser/billing/deposit \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{"amount_usd": 100.00}'
Response 200
{
  "success": true,
  "checkout_url": "https://checkout.stripe.com/pay/cs_live_...",
  "session_id": "cs_live_...",
  "amount_usd": 100.00
}
GET /api/advertiser/billing/transactions List billing transactions

Returns a paginated list of deposits and spend deductions.

Query Parameters

ParameterTypeDescription
pageintegerPage number (default 1)
limitintegerResults per page (default 50, max 200)
typestringFilter: deposit | spend
Response 200
{
  "success": true,
  "transactions": [
    {"id": 5001, "type": "deposit", "amount": 100.00, "created_at": "2026-03-20T14:22:00Z"},
    {"id": 5002, "type": "spend",   "amount": -1.42,  "campaign_id": 101, "created_at": "2026-03-21T09:15:00Z"}
  ],
  "total": 85,
  "page": 1
}
GET /api/advertiser/billing/receipts List downloadable receipts

Returns a list of PDF receipts for all successful deposits. Each receipt includes a download_url valid for 24 hours.

SSP API

Register and manage publisher sites, generate ad tags, configure floor prices, and access revenue analytics. Requires JWT Bearer token.

GET /api/publisher/sites List all registered sites
Example Response
{
  "success": true,
  "sites": [{
    "id": 55,
    "name": "Tech Blog",
    "domain": "techblog.example.com",
    "status": "approved",
    "floor_cpm": 1.00,
    "created_at": "2026-01-15T10:22:00Z"
  }]
}
POST /api/publisher/sites Register a new site for monetization
FieldTypeRequiredDescription
namestringrequiredHuman-readable site name
domainstringrequiredSite domain without protocol e.g. example.com
categorystringoptionalIAB content category e.g. IAB1
floor_cpmfloatoptionalMinimum CPM floor USD. Default: 0.50
descriptionstringoptionalSite description for quality review
*
Approval required. New sites enter pending status and are reviewed within 24-48 hours. Ad tags become active once approved.

Ad Zone Management

Ad zones define the placements on your site where ads will serve. Each zone maps to a specific ad format and generates a unique zone key for the JS tag.

GET /api/publisher/sites/:id/zones List ad zones for a site
Response 200
{
  "success": true,
  "zones": [
    {
      "id": 12,
      "zone_key": "zk_a3f9b2c1",
      "ad_format": "300x250",
      "name": "Sidebar Rectangle",
      "status": "active",
      "floor_cpm": 0.50,
      "created_at": "2026-01-10T08:00:00Z"
    }
  ]
}
POST /api/publisher/sites/:id/zones Create a new ad zone

Returns the new zone with its generated zone_key. Use the zone key in the JS embed tag.

Request Body

FieldTypeRequiredDescription
namestringRequiredDescriptive name (e.g. "Header Leaderboard")
ad_formatstringRequired728x90 | 300x250 | 320x50 | 160x600
floor_cpmfloatOptionalMinimum CPM floor (default 0.50). Bids below this are excluded.
cURL Example
curl -X POST https://adverteks.com/api/publisher/sites/7/zones \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{"name":"Header Leaderboard","ad_format":"728x90","floor_cpm":0.75}'
Response 201
{
  "success": true,
  "zone": {
    "id": 13,
    "zone_key": "zk_b8e1d4f2",
    "ad_format": "728x90",
    "name": "Header Leaderboard",
    "status": "active",
    "floor_cpm": 0.75
  }
}
GET /api/publisher/ad-tags Retrieve embeddable ad tag JavaScript snippets

Returns embeddable script tags for all approved ad zones. Each zone has a unique zoneKey used to serve ads.

Example Response
{
  "success": true,
  "ad_tags": [{
    "zone_id": 12,
    "zone_key": "zk_a3f9b2c1",
    "site_id": 55,
    "ad_format": "300x250",
    "tag": "<script src=\"https://adverteks.com/ad.js?z=zk_a3f9b2c1\"></script>"
  }]
}
Embed in your page
<div id="ad-container"></div>
<script src="https://adverteks.com/ad.js?z=zk_a3f9b2c1"></script>
GET /api/publisher/analytics Publisher inventory and revenue analytics

Query Parameters

ParameterDescription
site_idFilter to specific site
start_dateISO 8601 date YYYY-MM-DD
end_dateISO 8601 date
granularityday | week | month
Example Response
{
  "success": true,
  "analytics": [{
    "date": "2026-03-22",
    "impressions": 24810,
    "fill_rate": 87.4,
    "revenue": 24.81,
    "ecpm": 1.00,
    "clicks": 181,
    "ctr": 0.73
  }]
}
GET /api/publisher/earnings Publisher earnings and withdrawal status
Example Response
{
  "success": true,
  "earnings": {
    "available_balance": 142.80,
    "pending_balance": 58.22,
    "lifetime_earnings": 3291.50,
    "revenue_share": 70,
    "minimum_withdrawal": 25.00,
    "currency": "USD"
  }
}
i
Publishers receive 70% of the winning CPM. Minimum withdrawal is $25.00, processed within 5 business days.
GET /api/publisher/earnings/transactions Detailed earnings transaction history

Query Parameters

ParameterTypeDescription
start_datestringISO 8601 date YYYY-MM-DD
end_datestringISO 8601 date
pageintegerPage number (default 1)
Response 200
{
  "success": true,
  "transactions": [
    {"id": 8001, "type": "impression_revenue", "amount": 0.0142, "site_id": 7, "zone_key": "zk_a3f9b2c1", "created_at": "2026-03-21T09:15:00Z"},
    {"id": 8050, "type": "withdrawal",          "amount": -50.00, "status": "paid",   "created_at": "2026-03-15T12:00:00Z"}
  ],
  "total": 1240
}

Withdrawals & Payment Methods

Publishers can withdraw available earnings once the $25.00 minimum threshold is met. Add a bank account or PayPal to receive payouts.

GET /api/publisher/payment-methods List saved payment methods
Response 200
{
  "success": true,
  "payment_methods": [
    {"id": 3, "type": "bank_transfer", "label": "Chase ****4521", "is_default": true, "created_at": "2026-01-12T10:00:00Z"}
  ]
}
POST /api/publisher/payment-methods Add a payment method

Request Body

FieldTypeRequiredDescription
typestringRequiredbank_transfer | paypal
labelstringRequiredFriendly name for this method
detailsobjectRequiredAccount details (see below)
Bank Transfer
{"type":"bank_transfer","label":"My Bank","details":{"account_holder":"Jane Doe","account_number":"****4521","routing_number":"021000021","bank_name":"Chase"}}
PayPal
{"type":"paypal","label":"My PayPal","details":{"paypal_email":"jane@example.com"}}
POST /api/publisher/earnings/withdraw Request an earnings withdrawal

Initiates a withdrawal of your available earnings balance. Payouts processed within 5 business days.

i
Re-auth required. Withdrawal requires a short-lived re-auth token from POST /api/auth/reauth. The token expires in 5 minutes.

Request Body

FieldTypeRequiredDescription
amountfloatRequiredAmount to withdraw in USD (minimum $25.00)
payment_method_idintegerRequiredID of the saved payment method to pay out to
cURL Example
curl -X POST https://adverteks.com/api/publisher/earnings/withdraw \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{"amount": 50.00, "payment_method_id": 3}'
Response 200
{
  "success": true,
  "withdrawal": {
    "id": 501,
    "amount": 50.00,
    "status": "pending",
    "payment_method": "Chase ****4521",
    "estimated_arrival": "2026-04-08",
    "created_at": "2026-04-03T03:42:00Z"
  }
}

Publisher JS Tag Setup

Complete guide to embedding Adverteks ad units on your site. Go from zone key to live revenue in under 10 minutes.

*
Prerequisites. You need an approved Adverteks publisher account and at least one approved site with active ad zones. Log in at adverteks.com → Publisher Dashboard → Ad Tags.
Step 1
Register
Add your site domain in the Publisher Dashboard
Step 2
Approve
Site reviewed within 24–48 hours
Step 3
Get Tag
Copy zone key from Ad Tags dashboard tab
Step 4
Embed
Paste one script tag — ads load automatically

Minimal Tag (Copy & Paste)

Place this snippet wherever you want an ad unit to appear. Replace YOUR_ZONE_KEY with the zone key from your Ad Tags dashboard.

Minimal Embed
<!-- Adverteks Ad Unit -->
<div id="adtks-zone-YOUR_ZONE_KEY"></div>
<script src="https://adverteks.com/ad.js?z=YOUR_ZONE_KEY" async></script>
i
async attribute. Always use async on the script tag. This prevents the ad loader from blocking your page render. The div container is populated after the script executes.

Supported Ad Formats

Adverteks serves three standard IAB display formats. Specify the desired format when creating ad zones in your dashboard. The ad tag script renders the correct dimensions automatically.

Format NameDimensionsBest PlacementTypical eCPM
Medium Rectangle300 × 250Sidebar, in-content, below article$1.00–$3.50
Leaderboard728 × 90Page header / footer, above fold$0.80–$2.80
Mobile Banner320 × 50Mobile sticky bottom, between content blocks$0.50–$1.80
Medium Rectangle — 300×250
<!-- 300x250 Medium Rectangle -->
<div id="adtks-zone-zk_a3f9b2c1" style="width:300px;height:250px;overflow:hidden;"></div>
<script src="https://adverteks.com/ad.js?z=zk_a3f9b2c1" async></script>
Leaderboard — 728×90
<!-- 728x90 Leaderboard -->
<div id="adtks-zone-zk_b8e1d4f2" style="width:728px;height:90px;overflow:hidden;"></div>
<script src="https://adverteks.com/ad.js?z=zk_b8e1d4f2" async></script>
Mobile Banner — 320×50
<!-- 320x50 Mobile Banner -->
<div id="adtks-zone-zk_c5a7e3b9" style="width:320px;height:50px;overflow:hidden;"></div>
<script src="https://adverteks.com/ad.js?z=zk_c5a7e3b9" async></script>

Advanced Configuration

Multiple Zones on One Page

Each zone is independent. Drop as many snippets as you need — one script tag per zone, each with its own container div. Scripts load in parallel; there is no shared loader to initialize.

Header + Sidebar + Mobile on one page
<!-- Header leaderboard -->
<div id="adtks-zone-zk_b8e1d4f2" style="width:728px;height:90px;"></div>
<script src="https://adverteks.com/ad.js?z=zk_b8e1d4f2" async></script>

<!-- Sidebar 300x250 -->
<div id="adtks-zone-zk_a3f9b2c1" style="width:300px;height:250px;"></div>
<script src="https://adverteks.com/ad.js?z=zk_a3f9b2c1" async></script>

<!-- Mobile sticky (hidden on desktop via CSS) -->
<div id="adtks-zone-zk_c5a7e3b9" style="width:320px;height:50px;"></div>
<script src="https://adverteks.com/ad.js?z=zk_c5a7e3b9" async></script>

Lazy Loading (Intersection Observer)

For below-the-fold zones, defer loading until the container is about to enter the viewport. This improves page load performance and viewability scores (which increase eCPM).

Lazy-load below-fold ad unit
<div id="adtks-zone-zk_a3f9b2c1" style="width:300px;height:250px;"></div>

<script>
(function() {
  var container = document.getElementById('adtks-zone-zk_a3f9b2c1');
  var observer  = new IntersectionObserver(function(entries) {
    if (entries[0].isIntersecting) {
      var s    = document.createElement('script');
      s.src    = 'https://adverteks.com/ad.js?z=zk_a3f9b2c1';
      s.async  = true;
      document.body.appendChild(s);
      observer.disconnect();
    }
  }, { rootMargin: '200px' });
  observer.observe(container);
})();
</script>

Responsive Container (Fluid Width)

Wrap the ad container in a fluid div to handle varying page widths. The ad renders at the zone's declared size but the outer wrapper prevents layout overflow on small screens.

Fluid wrapper pattern
<div style="max-width:728px; width:100%; text-align:center; margin:0 auto;">
  <div id="adtks-zone-zk_b8e1d4f2" style="width:728px;height:90px;display:inline-block;"></div>
  <script src="https://adverteks.com/ad.js?z=zk_b8e1d4f2" async></script>
</div>

Retrieving Your Zone Key via API

If you manage many sites programmatically, fetch zone keys via the Ad Tags API instead of copying them from the dashboard:

GET /api/publisher/ad-tags
curl -s https://adverteks.com/api/publisher/ad-tags \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.ad_tags[] | {zone_key, ad_format}'
Response
[
  { "zone_key": "zk_a3f9b2c1", "ad_format": "300x250" },
  { "zone_key": "zk_b8e1d4f2", "ad_format": "728x90" },
  { "zone_key": "zk_c5a7e3b9", "ad_format": "320x50" }
]

Content Security Policy (CSP)

If your site sends a Content-Security-Policy header, add Adverteks to the allowed origins for scripts and frames:

Minimum CSP additions
Content-Security-Policy:
  script-src 'self' https://adverteks.com;
  frame-src  'self' https://adverteks.com;
  img-src    'self' https://adverteks.com data:;
!
Third-party creatives. Advertiser creative assets (images, landing page redirects) are served from external CDNs. If you enforce a strict CSP, use img-src * data: and frame-src * to avoid blocking rendered ads.

Verifying Tag Installation

After embedding, verify the tag loaded correctly in your browser:

  1. Open DevTools → Network tab → filter by ad.js
  2. Confirm the script request returns 200
  3. Check the adtks-zone-* div — it should contain an <iframe> or <ins> element after load
  4. Impressions appear in your Publisher Dashboard → Analytics within ~5 minutes

Affiliate API

Earn commissions by referring publishers and advertisers to Adverteks. The affiliate program features multi-level tracking, real-time commission calculations, and flexible payout options.

Commission
% of revenue
Earned on referred accounts
Tracking
Multi-level
Up to N tiers deep
Min payout
$50
Via bank or PayPal
Cookie window
30 days
Attribution window
*
Getting started. Register as an affiliate first (one-time). Once approved, get your referral link from the affiliate dashboard and start sharing.
POST /api/v1/affiliate/register Register as an affiliate

One-time registration to join the affiliate program. Requires an existing Adverteks account (publisher or advertiser). Returns your affiliate profile with unique referral code.

cURL Example
curl -X POST https://adverteks.com/api/v1/affiliate/register \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{"agreed_to_terms": true}'
Response 200
{
  "success": true,
  "affiliate": {
    "id": 88,
    "referral_code": "ADTK-abc123",
    "referral_url": "https://adverteks.com/?ref=ADTK-abc123",
    "status": "active",
    "commission_rate": 0.10,
    "created_at": "2026-04-03T03:42:00Z"
  }
}
GET /api/v1/affiliate/me Get affiliate profile

Returns your affiliate profile including referral code, commission rate, and payout status.

Response 200
{
  "success": true,
  "affiliate": {
    "id": 88,
    "referral_code": "ADTK-abc123",
    "referral_url": "https://adverteks.com/?ref=ADTK-abc123",
    "status": "active",
    "commission_rate": 0.10,
    "tier": "standard"
  }
}
GET /api/v1/affiliate/dashboard Affiliate performance dashboard

Returns aggregate performance metrics: total referred users, active accounts, lifetime commissions, and current period earnings.

cURL Example
curl https://adverteks.com/api/v1/affiliate/dashboard \
  -H "Authorization: Bearer YOUR_JWT"
Response 200
{
  "success": true,
  "dashboard": {
    "total_referrals": 14,
    "active_referrals": 11,
    "pending_referrals": 3,
    "lifetime_commissions_usd": 284.50,
    "current_period_commissions_usd": 42.10,
    "available_balance_usd": 142.50,
    "pending_balance_usd": 42.10,
    "top_referral": {"email": "pub***@example.com", "revenue_generated_usd": 3200.00}
  }
}
GET /api/v1/affiliate/commissions List commission transactions

Returns a paginated list of individual commission events — one record per referred account billing event.

Query Parameters

ParameterTypeDescription
statusstringpending | approved | paid
start_datestringISO 8601 date YYYY-MM-DD
end_datestringISO 8601 date
pageintegerPage number (default 1)
limitintegerResults per page (default 50)
Response 200
{
  "success": true,
  "commissions": [
    {
      "id": 2001,
      "referred_user": "pub***@example.com",
      "event_type": "impression_revenue",
      "referred_revenue_usd": 24.81,
      "commission_usd": 2.48,
      "commission_rate": 0.10,
      "status": "approved",
      "earned_at": "2026-03-21T00:00:00Z"
    }
  ],
  "total": 341,
  "page": 1
}
GET /api/v1/affiliate/network View referred network

Returns the tree of referred accounts with their current status and lifetime revenue generated.

GET /api/v1/affiliate/payouts List payout history
Response 200
{
  "success": true,
  "payouts": [
    {"id": 301, "amount_usd": 100.00, "status": "paid", "method": "bank_transfer", "paid_at": "2026-03-10T00:00:00Z"},
    {"id": 302, "amount_usd": 42.50,  "status": "pending", "method": "paypal",       "requested_at": "2026-04-01T00:00:00Z"}
  ]
}
POST /api/v1/affiliate/payouts/request Request a commission payout

Submit a payout request. Minimum $50.00. Processed within 10 business days.

Request Body

FieldTypeRequiredDescription
amount_usdfloatRequiredAmount to withdraw (minimum $50.00)
methodstringRequiredbank_transfer | paypal
payout_detailsobjectRequiredBank or PayPal details
cURL Example
curl -X POST https://adverteks.com/api/v1/affiliate/payouts/request \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "amount_usd": 100.00,
    "method": "paypal",
    "payout_details": {"paypal_email": "you@example.com"}
  }'

Marketing Tools

The GET /api/v1/affiliate/tools endpoint returns ready-made marketing assets: banner ad HTML, text links, and landing page copy variants for your referral URL.

Response excerpt
{
  "success": true,
  "tools": {
    "referral_url": "https://adverteks.com/?ref=ADTK-abc123",
    "banners": [
      {"size": "728x90", "html": "<a href='...'><img src='...'></a>"}
    ],
    "text_links": [
      {"label": "Monetize your traffic with Adverteks", "url": "https://adverteks.com/?ref=ADTK-abc123"}
    ]
  }
}

Referral Stats Endpoints

EndpointMethodDescription
/api/referral/statsGETSummary stats: clicks, sign-ups, conversions, revenue generated
/api/referral/networkGETFull referral tree with per-account revenue breakdown
/api/referral/commissionsGETAlias for /api/v1/affiliate/commissions
/api/referral/leaderboardGETPublic affiliate leaderboard (top 10 earners, anonymized)
/api/v1/affiliate/statusGETCheck affiliate registration status (no requireAffiliate needed)

Ad Exchange

How the real-time auction engine works, clearing price calculation, and platform economics.

Auction Mechanics

Adverteks runs a second-price sealed-bid (Vickrey) auction on every ad request. The highest bidder wins but pays the second-highest bid price plus $0.01.

Auction Type
2nd Price
Winner pays 2nd bid + $0.01
Publisher Share
70%
Of winning clearing price
Platform Fee
30%
Retained by Adverteks
Floor CPM
$0.50
Sub-floor bids excluded

Ad Formats

Format CodeDimensionsIAB ClassificationCommon Placement
728x90728 x 90 pxLeaderboardPage header, above fold
300x250300 x 250 pxMedium RectangleSidebar, in-content
320x50320 x 50 pxMobile BannerMobile top/bottom bar
160x600160 x 600 pxWide SkyscraperRight rail

Linear Pacing

Campaigns use linear pacing to spread budget evenly over campaign lifetime. The system calculates an hourly spend target and scales bid participation accordingly.

Ad Serving Endpoint

GET /api/ad/serve/:zoneKey Serve an ad for a given zone (public, no auth required)

Called automatically by the embedded ad tag script. Returns the winning creative HTML.

ParameterTypeDescription
zoneKeystringZone identifier from ad tag
latfloatVisitor latitude for geo-targeting
lngfloatVisitor longitude
page_urlstringURL-encoded page URL for contextual targeting

Webhooks

Subscribe to real-time event notifications for wins, impressions, clicks, and conversions. Delivered via HTTP POST to your configured endpoint.

i
Webhook configuration is available for RTB partners. Contact partners@adverteks.com to configure your endpoint URL.

Event Types

EventTriggerKey Payload Fields
bid.winBid won the auctionauction_id, clearing_price, creative_id
impressionAd rendered in browserimpression_id, auction_id, timestamp
clickUser clicked the adimpression_id, auction_id, timestamp
conversionAttributed post-click conversionimpression_id, revenue, timestamp
budget.depletedCampaign budget exhaustedcampaign_id, budget_type
Example Payload — impression event
{
  "event": "impression",
  "timestamp": 1742656000000,
  "data": {
    "impression_id": "imp-9f3c2a1b",
    "auction_id":   "7f3d2a11-c4b8-4e9a-b2f1-a3c9e8d72f01",
    "campaign_id":   101,
    "creative_id":   "cr-4d9a2f",
    "ad_format":     "300x250",
    "clearing_price": 1.42
  }
}

Verifying Webhook Signatures

All webhook deliveries include an X-Adverteks-Signature header — HMAC-SHA256 of the raw request body signed with your partner secret key.

Node.js Verification Example
const crypto = require('crypto');

function verifyWebhook(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

Webhook CRUD API

Programmatically register, update, and manage webhook endpoints. Webhooks deliver real-time event payloads to your HTTP endpoint on auction wins, impressions, clicks, conversions, and budget events.

POST /api/v1/webhooks Register a new webhook endpoint

Request Body

FieldTypeRequiredDescription
urlstringRequiredHTTPS endpoint to receive event payloads
eventsarrayRequiredEvent types to subscribe to (see Event Types table)
secretstringOptionalHMAC signing secret. If omitted, one is auto-generated.
descriptionstringOptionalFriendly label for this webhook
cURL Example
curl -X POST https://adverteks.com/api/v1/webhooks \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhooks/adverteks",
    "events": ["bid.win", "impression", "click", "budget.depleted"],
    "description": "Production campaign monitoring"
  }'
Response 201
{
  "success": true,
  "webhook": {
    "id": 9,
    "url": "https://your-server.com/webhooks/adverteks",
    "events": ["bid.win","impression","click","budget.depleted"],
    "secret": "whsec_a8f2b3c1d4e5f6...",
    "status": "active",
    "description": "Production campaign monitoring",
    "created_at": "2026-04-03T03:42:00Z"
  }
}
!
Save your secret now. The webhook secret is only returned once at creation time. Store it securely — you'll need it to verify incoming payloads.
GET /api/v1/webhooks List all registered webhooks
Response 200
{
  "success": true,
  "webhooks": [
    {
      "id": 9,
      "url": "https://your-server.com/webhooks/adverteks",
      "events": ["bid.win","impression"],
      "status": "active",
      "last_delivery_at": "2026-04-02T22:14:00Z",
      "delivery_success_rate": 99.8
    }
  ]
}
PATCH /api/v1/webhooks/:id Update webhook configuration

Update the URL, subscribed events, or disable a webhook. Partial updates — only fields you provide are changed.

Pause a webhook
curl -X PATCH https://adverteks.com/api/v1/webhooks/9 \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{"status": "disabled"}'
Change subscribed events
curl -X PATCH https://adverteks.com/api/v1/webhooks/9 \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{"events": ["bid.win","conversion"]}'
DELETE /api/v1/webhooks/:id Delete a webhook

Permanently removes the webhook. No further events will be delivered to this endpoint.

curl -X DELETE https://adverteks.com/api/v1/webhooks/9 \
  -H "Authorization: Bearer YOUR_JWT"

Delivery & Retry Policy

PropertyValue
Delivery timeout10 seconds per attempt
Expected responseAny 2xx HTTP status
Retry attemptsUp to 5 retries with exponential backoff (1s, 4s, 16s, 64s, 256s)
Payload deliveryAt-least-once. Your handler should be idempotent.
Signature headerX-Adverteks-Signature — HMAC-SHA256 of raw body
Event orderingBest-effort. High-volume events may arrive out of order.

Supported Event Types

EventTriggerKey Payload Fields
bid.winAdverteks bid won the auctionauction_id, clearing_price, creative_id, campaign_id
impressionAd rendered in browserimpression_id, auction_id, zone_key, timestamp
clickUser clicked the adimpression_id, auction_id, timestamp
conversionPost-click conversion attributedimpression_id, revenue_usd, timestamp
budget.depletedCampaign balance reached $0campaign_id, budget_type (daily | total)

Receiver Example (Node.js/Express)

const crypto = require('crypto');
const express = require('express');
const app = express();

// Raw body needed for HMAC verification
app.use('/webhooks/adverteks', express.raw({ type: 'application/json' }));

app.post('/webhooks/adverteks', (req, res) => {
  const sig = req.headers['x-adverteks-signature'];
  const secret = process.env.ADVERTEKS_WEBHOOK_SECRET;

  const expected = crypto
    .createHmac('sha256', secret)
    .update(req.body)
    .digest('hex');

  if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig))) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(req.body);
  console.log(`Received ${event.event}:`, event.data);

  // Handle by type
  if (event.event === 'bid.win') {
    // Track win in your system
  } else if (event.event === 'budget.depleted') {
    // Trigger budget top-up alert
  }

  res.status(200).send('OK');
});

app.listen(3000);

Receiver Example (Python/Flask)

import hmac
import hashlib
import json
from flask import Flask, request, jsonify

app = Flask(__name__)

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    """Verify HMAC-SHA256 signature from X-Adverteks-Signature header"""
    expected = hmac.new(
        secret.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

@app.route('/webhooks/adverteks', methods=['POST'])
def handle_webhook():
    # Get signature from header (format: sha256=...)
    signature = request.headers.get('X-Adverteks-Signature', '')
    if signature.startswith('sha256='):
        signature = signature[7:]  # Remove 'sha256=' prefix

    secret = request.headers.get('X-Webhook-Secret') or 'your_secret_here'
    raw_body = request.get_data()

    # Verify signature if secret is configured
    if signature and not verify_signature(raw_body, signature, secret):
        return jsonify({'error': 'Invalid signature'}), 401

    event = json.loads(raw_body)
    event_type = event.get('event')
    data = event.get('data', {})

    print(f"Received {event_type}:", data)

    # Handle by event type
    if event_type == 'impression.served':
        # Track impression - data contains impression.id, ad_unit_id, campaign_id
        pass
    elif event_type == 'click.tracked':
        # Track click - data contains click.id, impression_id, url
        pass
    elif event_type == 'conversion.recorded':
        # Track conversion - data contains conversion.id, value, currency
        pass
    elif event_type == 'campaign.budget_exhausted':
        # Alert: campaign needs more budget
        pass
    elif event_type == 'payout.completed':
        # Payment sent to publisher
        pass
    elif event_type == 'publisher.site_approved':
        # Site is now live
        pass

    return jsonify({'status': 'ok'}), 200

if __name__ == '__main__':
    app.run(port=3000, debug=False)

Receiver Example (PHP/Laravel)

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Hash;

class WebhookController extends Controller
{
    /**
     * Handle incoming Adverteks webhook
     */
    public function handleAdverteks(Request $request)
    {
        // Get signature from header (format: sha256=...)
        $signature = $request->header('X-Adverteks-Signature', '');
        if (str_starts_with($signature, 'sha256=')) {
            $signature = substr($signature, 7);
        }

        // Get raw body for signature verification
        $rawBody = $request->getContent();
        $secret = config('services.adverteks.webhook_secret');

        // Verify HMAC-SHA256 signature
        if ($signature && $secret) {
            $expected = hash_hmac('sha256', $rawBody, $secret);
            if (!hash_equals($expected, $signature)) {
                return response()->json(['error' => 'Invalid signature'], 401);
            }
        }

        $event = json_decode($rawBody, true);
        $eventType = $event['event'] ?? null;
        $data = $event['data'] ?? [];

        Log::info("Adverteks webhook: {$eventType}", $data);

        // Handle by event type
        match ($eventType) {
            'impression.served' => $this->handleImpression($data),
            'click.tracked' => $this->handleClick($data),
            'conversion.recorded' => $this->handleConversion($data),
            'campaign.budget_exhausted' => $this->handleBudgetExhausted($data),
            'payout.completed' => $this->handlePayout($data),
            'publisher.site_approved' => $this->handleSiteApproved($data),
            default => null,
        };

        return response()->json(['status' => 'ok']);
    }

    private function handleImpression(array $data): void
    {
        // $data['impression']['id'], $data['impression']['campaign_id'], etc.
    }

    private function handleClick(array $data): void
    {
        // $data['click']['id'], $data['click']['url'], etc.
    }

    private function handleConversion(array $data): void
    {
        // $data['conversion']['value'], $data['conversion']['currency'], etc.
    }

    private function handleBudgetExhausted(array $data): void
    {
        // Notify advertiser to add funds
    }

    private function handlePayout(array $data): void
    {
        // Update publisher balance
    }

    private function handleSiteApproved(array $data): void
    {
        // Site is now live, start serving ads
    }
}

Error Codes

Standard error response format and HTTP status codes returned by all API endpoints.

Error Response Format

{
  "success": false,
  "message": "Human-readable error description",
  "code": "MACHINE_READABLE_CODE"
}

HTTP Status Codes

  • 200OKRequest succeeded. Response body contains data.
  • 204No ContentRTB: no eligible bid found. Empty body.
  • 400Bad RequestMissing or invalid parameters. See message field for details.
  • 401UnauthorizedMissing or expired authentication token. Re-authenticate.
  • 403ForbiddenToken valid but insufficient permissions for this resource.
  • 404Not FoundResource does not exist or belongs to another account.
  • 429Too Many RequestsRate limit exceeded. See Retry-After header.
  • 500Internal Server ErrorUnexpected server error. Contact support@adverteks.com.

Application Error Codes

CodeHTTPDescription
INVALID_BID_REQUEST400OpenRTB BidRequest missing required fields or fails validation
BANNER_REQUIRED204Bid request has no banner impression object
BELOW_FLOOR204Highest bid was below the effective floor CPM
TOKEN_EXPIRED401JWT expired. Request new token via /api/auth/login
BUDGET_EXHAUSTED400Campaign budget depleted. Top up wallet or increase budget.
SITE_NOT_APPROVED403Site registration still pending review
CAMPAIGN_INACTIVE400Campaign is paused, ended, or not yet started
RATE_LIMIT_EXCEEDED429Too many requests in current window. Honor Retry-After.

*
Ready to integrate? Contact partners@adverteks.com to receive your RTB partner API key and get technical onboarding support.

Partner Onboarding

Everything you need to connect as an external DSP or SSP — registration, sandbox access, and supply chain compliance.

Registration Process

External DSP/SSP integration is approval-gated. There is no self-serve API key creation — this ensures inventory quality and prevents fraudulent traffic from entering the exchange.

Step 1
Email
Send integration request to partners@adverteks.com
Step 2
Review
Technical and compliance review (1–3 business days)
Step 3
Sandbox
API key issued; test against sandbox endpoint
Step 4
Live
Production traffic enabled after QA sign-off

What to Include in Your Integration Request

FieldDescription
Company nameLegal entity name
Platform typeDSP (demand-side) or SSP (supply-side)
Daily bid volumeExpected QPS / daily impression volume
Geo focusPrimary countries and device types
Ad categoriesIAB content categories you trade in
Technical contactName + email for integration support
*
Contact: partners@adverteks.com
Subject line: DSP Integration Request — [Your Company]

Sandbox Environment

The sandbox environment mirrors the production API with deterministic test responses. Use it to validate bid request formatting, HMAC signatures, and win notice delivery before going live.

PropertyValue
Sandbox base URLhttps://adverteks.com (same host, sandbox activated per API key)
Sandbox bid endpointPOST /api/rtb/bid — same path; sandbox keys always return a deterministic bid
Test API key prefixadtks_test_ — sandbox keys are issued during onboarding
Clearing priceAlways returns $1.00 CPM in sandbox
Win noticesAccepted and logged; no actual billing
Rate limits100 req/min (lower than production)
Quick Sandbox Test (cURL)
curl -X POST https://adverteks.com/api/rtb/bid \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: adtks_test_your_sandbox_key" \
  -H "X-OpenRTB-Version: 2.5" \
  -d '{
    "id": "test-auction-001",
    "imp": [{"id": "1", "banner": {"w": 300, "h": 250}, "bidfloor": 0.50}],
    "tmax": 150
  }'

A valid sandbox response looks identical to a production BidResponse. HTTP 200 with a seatbid payload confirms your request format is correct.

ads.txt & sellers.json

Adverteks participates in the IAB supply chain transparency framework. Publishers monetizing via Adverteks must add the following entry to their ads.txt file. DSPs verifying inventory can check Adverteks in sellers.json.

ads.txt Entry

Add to the root ads.txt of every domain monetized through Adverteks:

adverteks.com, pub-XXXXXXXXXXXXXXXX, DIRECT, f08c47fec0942fa0
i
Replace pub-XXXXXXXXXXXXXXXX with your Publisher ID, visible in your publisher dashboard under Settings → Account.

sellers.json

Adverteks publishes its sellers.json at:

https://adverteks.com/.well-known/sellers.json

DSPs should validate that impression supply chains reference Adverteks using seller_id values matching your Publisher ID. The file is updated daily.

app-ads.txt (Mobile / CTV)

For in-app inventory, add the same entry to your app-ads.txt file (hosted at your developer domain root):

adverteks.com, pub-XXXXXXXXXXXXXXXX, DIRECT, f08c47fec0942fa0

Code Examples

Ready-to-run examples for the most common integration workflows. Copy, replace credentials, and run.

cURL Examples

Bid Request (no HMAC)

curl -s -X POST https://adverteks.com/api/rtb/bid \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: adtks_live_YOUR_API_KEY" \
  -H "X-OpenRTB-Version: 2.5" \
  -d '{
    "id": "7f3d2a11-c4b8-4e9a-b2f1-a3c9e8d72f01",
    "imp": [{
      "id": "1",
      "banner": { "w": 300, "h": 250, "pos": 1 },
      "bidfloor": 0.50,
      "bidfloorcur": "USD"
    }],
    "site": {
      "page": "https://example.com/article",
      "domain": "example.com",
      "cat": ["IAB1"]
    },
    "device": {
      "geo": { "lat": 40.7128, "lon": -74.0060, "country": "USA", "city": "New York" },
      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
      "devicetype": 2
    },
    "user": { "id": "user-abc123" },
    "tmax": 150
  }'

Bid Request with HMAC Signature (bash function)

#!/usr/bin/env bash
API_KEY="adtks_live_YOUR_API_KEY"
HMAC_SECRET="your-hmac-secret"
ENDPOINT="https://adverteks.com/api/rtb/bid"

BODY='{
  "id": "auction-12345",
  "imp": [{"id": "1", "banner": {"w": 728, "h": 90}, "bidfloor": 1.00}],
  "tmax": 150
}'

# Compute HMAC-SHA256 over the raw body
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$HMAC_SECRET" -hex | awk '{print "sha256="$2}')

curl -s -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: $API_KEY" \
  -H "X-OpenRTB-Version: 2.5" \
  -H "X-Signature-SHA256: $SIG" \
  -d "$BODY"

Win Notice

curl -s -X POST "https://adverteks.com/api/rtb/win?aid=auction-12345&price=1.42" \
  -H "X-Api-Key: adtks_live_YOUR_API_KEY"

Node.js Full Example

A complete bid → win → event tracking flow using the built-in fetch API (Node 18+).

const crypto = require('crypto');

const CONFIG = {
  apiKey:     process.env.ADVERTEKS_API_KEY,
  hmacSecret: process.env.ADVERTEKS_HMAC_SECRET,
  host:       'adverteks.com',
};

// ── Build auth headers ──────────────────────────────────────────────────────
function authHeaders(bodyStr) {
  const sig = crypto
    .createHmac('sha256', CONFIG.hmacSecret)
    .update(bodyStr, 'utf8')
    .digest('hex');
  return {
    'Content-Type':       'application/json',
    'X-Api-Key':          CONFIG.apiKey,
    'X-OpenRTB-Version':  '2.5',
    'X-Signature-SHA256': `sha256=${sig}`,
  };
}

// ── Submit bid request ───────────────────────────────────────────────────────
async function bid(bidRequest) {
  const body = JSON.stringify(bidRequest);
  const res  = await fetch(`https://${CONFIG.host}/api/rtb/bid`, {
    method:  'POST',
    headers: authHeaders(body),
    body,
    signal:  AbortSignal.timeout(200),
  });
  if (res.status === 204) return null;
  if (!res.ok) throw new Error(`Bid error ${res.status}: ${await res.text()}`);
  return res.json();
}

// ── Send win notice ──────────────────────────────────────────────────────────
async function sendWin(auctionId, clearingPriceCpm) {
  const res = await fetch(
    `https://${CONFIG.host}/api/rtb/win?aid=${auctionId}&price=${clearingPriceCpm}`,
    { method: 'POST', headers: { 'X-Api-Key': CONFIG.apiKey } }
  );
  if (!res.ok) console.error('Win notice failed:', res.status);
}

// ── Track impression ─────────────────────────────────────────────────────────
async function trackImpression(auctionId) {
  const body = JSON.stringify({ auction_id: auctionId, event_type: 'impression' });
  await fetch(`https://${CONFIG.host}/api/rtb/event`, {
    method: 'POST', headers: authHeaders(body), body,
  });
}

// ── Example usage ────────────────────────────────────────────────────────────
(async () => {
  const bidRequest = {
    id:  crypto.randomUUID(),
    imp: [{ id: '1', banner: { w: 300, h: 250 }, bidfloor: 0.5 }],
    site: { page: 'https://example.com/', domain: 'example.com' },
    device: { geo: { lat: 37.77, lon: -122.41, country: 'USA' } },
    user: { id: 'user-seg-xyz' },
    tmax: 150,
  };

  const response = await bid(bidRequest);
  if (!response) { console.log('No bid'); return; }

  const bidItem     = response.seatbid[0].bid[0];
  const clearingCpm = bidItem.price;
  console.log(`Won at $${clearingCpm} CPM | Creative: ${bidItem.crid}`);

  // Fire win notice and impression in parallel
  await Promise.all([
    sendWin(bidRequest.id, clearingCpm),
    trackImpression(bidRequest.id),
  ]);

  console.log('Win + impression logged');
})();

Python Full Example

Requires Python 3.8+ and no external dependencies beyond the standard library.

import hmac
import hashlib
import json
import os
import uuid
import urllib.request
import urllib.error
from typing import Optional

API_KEY     = os.environ['ADVERTEKS_API_KEY']
HMAC_SECRET = os.environ['ADVERTEKS_HMAC_SECRET']
BASE_URL    = 'https://adverteks.com'

# ── Build auth headers ──────────────────────────────────────────────────────
def auth_headers(body_bytes: bytes) -> dict:
    sig = hmac.new(HMAC_SECRET.encode(), body_bytes, hashlib.sha256).hexdigest()
    return {
        'Content-Type':       'application/json',
        'X-Api-Key':          API_KEY,
        'X-OpenRTB-Version':  '2.5',
        'X-Signature-SHA256': f'sha256={sig}',
    }

# ── Submit bid request ───────────────────────────────────────────────────────
def bid(bid_request: dict) -> Optional[dict]:
    body = json.dumps(bid_request, separators=(',', ':')).encode()
    req  = urllib.request.Request(
        f'{BASE_URL}/api/rtb/bid',
        data=body, headers=auth_headers(body), method='POST'
    )
    try:
        with urllib.request.urlopen(req, timeout=0.2) as r:
            return json.loads(r.read()) if r.status == 200 else None
    except urllib.error.HTTPError as e:
        if e.code == 204: return None
        raise

# ── Send win notice ──────────────────────────────────────────────────────────
def send_win(auction_id: str, clearing_price_cpm: float) -> None:
    url = f'{BASE_URL}/api/rtb/win?aid={auction_id}&price={clearing_price_cpm}'
    req = urllib.request.Request(url, method='POST',
                                 headers={'X-Api-Key': API_KEY})
    try:
        urllib.request.urlopen(req, timeout=1)
    except urllib.error.HTTPError as e:
        print(f'Win notice error: {e.code}')

# ── Track event ──────────────────────────────────────────────────────────────
def track_event(auction_id: str, event_type: str) -> None:
    body = json.dumps({'auction_id': auction_id, 'event_type': event_type}).encode()
    req  = urllib.request.Request(
        f'{BASE_URL}/api/rtb/event',
        data=body, headers=auth_headers(body), method='POST'
    )
    urllib.request.urlopen(req, timeout=1)

# ── Example usage ────────────────────────────────────────────────────────────
if __name__ == '__main__':
    bid_request = {
        'id':  str(uuid.uuid4()),
        'imp': [{'id': '1', 'banner': {'w': 300, 'h': 250}, 'bidfloor': 0.50}],
        'site': {'page': 'https://example.com/', 'domain': 'example.com'},
        'device': {'geo': {'lat': 37.77, 'lon': -122.41, 'country': 'USA'}},
        'user': {'id': 'user-xyz'},
        'tmax': 150,
    }

    response = bid(bid_request)
    if not response:
        print('No bid')
    else:
        bid_item     = response['seatbid'][0]['bid'][0]
        clearing_cpm = bid_item['price']
        print(f'Won at ${clearing_cpm:.3f} CPM | Creative: {bid_item["crid"]}')
        send_win(bid_request['id'], clearing_cpm)
        track_event(bid_request['id'], 'impression')
        print('Win + impression logged')