Skip to content

oRTB Integration Spec

Connect your CTV / video supply directly to Vuukle’s programmatic demand stack. This page is the complete spec — your engineering team should be able to ship the integration in a day.

What you need before you start

From you

A server that can POST OpenRTB 2.5/2.6 JSON to our endpoint and parse a VAST 4.x response in the bid body.

From us

Your unique Publisher ID — the same seller ID we list in vuukle.com/sellers.json. Provided as part of onboarding.

The endpoint

POST https://rtb.vuukle.com/openrtb2/video?pub=<YOUR_PUBLISHER_ID>
Content-Type: application/json
SettingValue
MethodPOST
Content-Typeapplication/json
ProtocolOpenRTB 2.5 or 2.6
Recommended client timeout1200 ms (we cap server-side at 1500 ms)
Auction modelFirst-price (at: 1)

Quick start — minimum BidRequest

This is the smallest valid request that will produce bids. Replace <...> placeholders with real values. Your Publisher ID goes in the URL only — you don’t need to repeat it inside the body.

{
"id": "<your_unique_request_id>",
"tmax": 1000,
"at": 1,
"cur": ["USD"],
"imp": [{
"id": "1",
"bidfloor": 10.0,
"bidfloorcur": "USD",
"secure": 1,
"video": {
"mimes": ["video/mp4", "video/webm", "application/javascript"],
"w": 1920, "h": 1080,
"minduration": 5,
"maxduration": 30,
"protocols": [2, 3, 5, 6, 7, 8],
"linearity": 1,
"placement": 1,
"plcmt": 1,
"startdelay": 0,
"skip": 0,
"api": [2],
"playbackmethod": [2]
}
}],
"app": {
"bundle": "roku.popcornflix",
"name": "Popcornflix",
"storeurl": "https://channelstore.roku.com/details/6119/popcornflix"
},
"device": {
"ua": "<player_user_agent>",
"ip": "<viewer_ipv4>",
"ifa": "<roku_rida_or_amazon_afai_or_etc>",
"devicetype": 3,
"make": "Roku",
"os": "Roku OS",
"geo": { "country": "USA", "region": "CA" }
},
"user": { "id": "<viewer_id_or_ifa>" },
"regs": { "coppa": 0, "gdpr": 0, "ext": { "us_privacy": "1---" } }
}

Response

{
"id": "<your_request_id>",
"cur": "USD",
"seatbid": [{
"seat": "pubmatic",
"bid": [{
"id": "<bid_id>",
"impid": "1",
"price": 12.50,
"adm": "<VAST>...</VAST>",
"nurl": "https://...",
"w": 1920,
"h": 1080,
"dur": 15
}]
}]
}

The adm field contains VAST 4.x XML (inline or wrapper). Render it in your player as-is. Tracking pixels and event firing are embedded inside the VAST.

Required fields

FieldNotes
idTrace ID — keep stable across retries
at1 (first-price) — required for CTV demand to bid correctly
tmaxAuction timeout in ms — we recommend 1000
imp[0].bidfloor + bidfloorcurFloor CPM in USD. Bidders must bid ≥ this or no-bid.
imp[0].video.mimesAt minimum ["video/mp4"]. Adding video/webm, application/javascript (VPAID) widens demand.
imp[0].video.w / hPlayer dimensions
imp[0].video.protocols[2, 3, 5, 6, 7, 8] covers VAST 2/3/4 inline and wrapper
imp[0].video.placement + plcmt1 for in-stream preroll
app.bundleThe most important field. Drives our IPD detection, ad-slot mapping, and floor routing. Use the canonical store ID (e.g. roku.popcornflix, B07DBBTDBS).
device.ua, device.ip, device.ifa, device.devicetype, device.make, device.osUsed by every bidder for inventory recognition

These materially improve bid rate and CPM:

FieldWhy
device.geo.country / region / zip / lat / lonRequired for any geo-targeted demand. Most CTV deals are US-only or US/CA.
app.content.cat (IAB taxonomy), channel, genre, language, rating, lenPremium-content signals raise CPMs significantly
app.name, app.storeurlHelps bidders recognize the inventory in their reporting
imp.video.skip, skipafter, skipminNon-skip inventory bids meaningfully higher
regs.gdpr, user.consent, regs.ext.us_privacyRequired for compliant bidding in EU/CA
bcat, badvCategory and advertiser blocklists — honored end-to-end

Floor pricing model

Vuukle runs first-price auctions (at: 1). The CPM in imp.bidfloor is the minimum bidders must beat — if a bidder bids $12 against your $10 floor, you receive $12 (not a Vickrey-discounted second-price amount).

For most publishers, imp.bidfloor is hard — bidders must bid ≥ it or no-bid:

"imp": [{
"id": "1",
"bidfloor": 10.0,
"bidfloorcur": "USD"
}]

Supply Chain (schain)

You don’t need to construct schain — we build it for you. For transparency, here’s what we send downstream:

"source": {
"fd": 0,
"schain": {
"complete": 1,
"ver": "1.0",
"nodes": [
{ "asi": "<your_domain>", "sid": "<your_pub_id>", "hp": 1 },
{ "asi": "vuukle.com", "sid": "<your_pub_id>", "hp": 1 }
]
}
}

If you already construct your own schain, send it in the request — we append the vuukle.com node without disturbing your upstream nodes.

vuukle.com/sellers.json declares every publisher we have authorized — your entry is verifiable there.

Device & IFA conventions

Devicedevice.devicetypedevice.ifa value
Roku3 (Connected TV)RIDA
Amazon Fire TV3 or 7AFAI
Apple TV3IDFA
Samsung Smart TV7TIFA
LG Smart TV7LGUDID
Android Mobile1AAID
iOS Mobile1IDFA
Desktop Web2(none — use IP-based)

Implementation checklist

  1. POST your BidRequest to https://rtb.vuukle.com/openrtb2/video?pub=<YOUR_PUBLISHER_ID>.

  2. Set Content-Type: application/json.

  3. Set "at": 1 (first-price) in the body.

  4. Set client-side timeout to 1200 ms.

  5. On HTTP 200: parse seatbid[0].bid[0].adm, render the VAST in your player. Tracking pixels and event firing happen automatically from inside the VAST.

  6. On HTTP 204: no ad available, fall through to your next waterfall step.

  7. On HTTP 5xx or timeout: treat as no-bid; do not retry within the same impression opportunity.

  8. After your first 100 requests, email adops@vuukle.com so we can run a parse-confirmation diagnostic and confirm fill is flowing.

What we do server-side

For transparency, every request you send goes through this pipeline:

  1. Cloudflare edge — bot management, geo and ASN tagging, DDoS protection.

  2. Vuukle edge — resolve your Publisher ID from ?pub=, load your config, validate request shape.

  3. Enrichment — set app.ext.inventorypartnerdomain from app.bundle, append the vuukle.com node to schain, map floor tier to bidder ad slot.

  4. Caps & IVT check — enforce daily per-tag impression caps, per-device frequency caps, daily revenue ceiling. Tag every request with an IVT signal (CF bot score, UA class, IFA presence).

  5. Auction — fan out to all configured demand partners via Prebid Server. First-price selection across returned bids.

  6. Response — return winning VAST or 204 to you.

  7. Logging — every request is logged compactly to ClickHouse (publisher / bundle / IFA / country / IVT signals / outcome). Suspicious requests get full-body archival for forensic review.

You see all of this in your publisher dashboard.

Default safety caps

To protect you against misconfigured floors, bot exploitation, and runaway financial exposure, every newly-onboarded publisher starts with conservative caps. They auto-loosen after a 7-day warm-up and can be adjusted any time by your Vuukle account manager.

CapDefaultWarm-up week
Impressions per tag per day50,00010,000
Impressions per IFA per day (freq cap)55
Revenue per publisher per day$500$100

If a cap is hit, we return HTTP 204 with response header X-Vuukle-Block-Reason: <reason> so your engineering team can monitor cap pressure.

Frequently asked questions

Do I need to set up sellers.json or ads.txt?

Your domain needs an ads.txt (or app-ads.txt for in-app supply) that lists vuukle.com as an authorized seller, with your seller ID. We provide the exact line to add during onboarding.

What about identity (UID 2.0 / RampID / etc.)?

We forward whatever you send in user.ext.eids — identity signals are not stripped. For premium demand, the more identity you include, the higher the bid prices.

Is there a test endpoint vs production endpoint?

No — both are at https://rtb.vuukle.com/openrtb2/video?pub=<YOUR_PUBLISHER_ID>. Same URL, same payload shape. Until you’ve completed onboarding, your Publisher ID is flagged “test mode” server-side: we log everything and run real auctions but don’t reconcile billing. Promotion to production happens after a successful 24-hour test run.

Where’s the server hosted?

DigitalOcean NYC3. Typical round-trip latency from US-East CTV players is under 50 ms.

Where can I see my numbers?

Your publisher dashboard at https://publishers.vuukle.com/<your_publisher_id> shows live: requests, bid rate, fill rate, CPM, revenue, IVT signals, and per-bundle breakdowns. Login is provisioned during onboarding.

How do I add a new app/bundle?

Email adops@vuukle.com with the bundle ID, store URL, and IFA type. Most bundles are live within a business day. Until then, requests from unknown bundles return 204.

What’s the support response time?

Email support is monitored Monday–Friday during business hours globally (we have offices in 4 time zones). For urgent integration issues during a test, we set up a shared Slack channel for sub-hour response.

Contact

Onboarding & technicaladops@vuukle.com
Account / commercialYour Vuukle account manager
Urgent integration issuesThe shared Slack channel set up during onboarding
Was this page helpful?
Help us improve — drop a note or open the dashboard.