OpenRTB DOOH profile
Version 0.1.0
The profile follows IAB Tech Lab OpenRTB 2.6 and AdCOM 1.0, and uses the OpenOOH venue taxonomy. Field names are taken from those specifications. Where we ask for more than the standard requires, the text says so.
Overview
In this model the network is the supply side. For each screen slot it sends an OpenRTB bid request to the partner's bidder. The partner answers with a bid. The highest price wins, and the partner is billed after the creative has been played and the play has been verified.
This is different from the Bid protocol, which is the native protocol that we use today with individual bidders. The native protocol is simpler and is the default for new partners. This profile exists for platforms that already speak OpenRTB and cannot add a native integration.
Three properties set this profile apart from a web OpenRTB integration:
- Creatives are registered before the auction. A screen player must have the file on disk before the slot starts. A bid therefore cannot carry markup. It points to a creative that the partner has registered and that we have approved ahead of time. How the creative is registered is an open question, see below.
- Billing follows a verified play, not the win. The partner is billed when the billing notice (
burl) fires after a verified play. The win notice (nurl) is informational. - There is no user identity. A screen has no advertising id.
device.ifais never sent, and there is nouserobject.
Request profile
The bid request is a standard OpenRTB 2.6 BidRequest with a dooh object instead of site or app.
| Field | Value |
|---|---|
at |
1, first price. |
tmax |
Milliseconds the bidder has to answer, including network time. Proposed value: 500. |
cur |
One currency, the one in the contract. |
imp[0].video |
The slot as a video opportunity: mimes, minduration and maxduration (both equal to the slot length in seconds), w and h (screen resolution in pixels). |
imp[0].tagid |
The screen id as a string. The same screen always has the same id. |
imp[0].dt |
The moment the slot is scheduled to play, in Unix milliseconds. |
imp[0].exp |
Seconds from the auction to the play, at most. |
imp[0].qty |
The impression multiplier: how many audience impressions one play counts for. sourcetype tells who measured it. |
imp[0].bidfloor |
The floor, when the screen has one. |
dooh |
id (screen id), name, venuetype and venuetypetax (OpenOOH Venue Taxonomy 1.0, venuetypetax is 1), publisher and domain of the screen owner. |
device.geo |
lat and lon of the screen. |
source.schain |
The supply chain with the network as a node. |
dt and qty are the two fields that matter most for screens. A screen plays a slot at a known time, usually seconds after the auction, and a play reaches an audience whose size comes from a measurement. The multiplier we send comes from our own estimate of the passing audience. We do not claim it is a measured count of people who looked at the screen.
Response profile
A bid response is a standard BidResponse with one seatbid and one bid per impression.
| Field | Meaning |
|---|---|
bid.impid |
The imp.id of the request. |
bid.price |
The bid. By the OpenRTB definition it is a CPM, the price of one thousand impressions. The amount charged for one play is then price / 1000 × multiplier. Whether we use CPM or a price per play is an open question. |
bid.crid |
The id of a creative registered before the auction. Required. A bid with an unknown or unapproved crid is dropped. |
bid.adomain |
Advertiser domains. Required, for brand-safety checks. |
bid.dur |
Creative length in seconds. Must not exceed the slot length. |
bid.burl |
Billing noticeaddress. Required. |
bid.nurl |
Win noticeaddress. Optional. |
bid.adm |
Not used. Markup is ignored. |
No bid is 204 with an empty body, or a BidResponse with nbr.
Billing
The billing notice is called with GET after the player has reported a play and the report has been verified. The macros ${AUCTION_PRICE}, ${AUCTION_MULTIPLIER}, ${AUCTION_IMP_TS}, ${AUCTION_IMP_ID} and ${AUCTION_ID} are replaced with the clearing price (the bid price, because the auction is first price), the multiplier that was actually delivered, the time of the play in Unix milliseconds, the impression id and the bid request id. A win that is never played is never billed.
Open questions
The profile is not final. These questions decide what it will look like. They are grouped as we plan to discuss them with partners.
Protocol
Which OpenRTB version does the partner run, 2.5 or 2.6, and does it support the DOOH object, venue types and the impression multiplier? Does it use the OpenOOH taxonomy or its own? Are screens registered in advance (an inventory list or a synchronisation call), or is all screen data sent with each request? What is its response timeout, how long before the slot can a request arrive, and how long does a won ad stay valid? Where are its servers, and can they be reached from infrastructure that we host in Russia? What request rate does it expect and what throttling applies? Is there one request per slot, or are requests batched? Does it support sellers.json and schain, and how does it want the network to appear in the chain?
Auction and money
First price or second price? Is the bid price net or gross of the partner's fee, what is the fee, and is it the same in an open auction and in a deal? Are floors supported per screen and per time of day? Is payment triggered by the win notice or by a verified play? In what currency is the settlement made, what are the payment terms, and who invoices whom? How are won slots that were not played treated?
Creatives
Which formats are accepted: MP4 with H.264 or H.265, still images, HTML? What are the maximum file size, resolution and length? Can the address, id and checksum of a creative be delivered before the auction so that players can load it in advance? What is the approval flow? Can the network reject a creative for local rules without losing the deal? How are mismatches of length and aspect ratio handled?
Proof of play and audience
Which proof of play does the partner accept: playback logs, camera photos, both? Does it use its own audience data or accept ours? How is the audience per play calculated? Which third-party verification is required, and from which vendors?
Reporting and billing
How detailed is reporting (per screen, per hour, per creative), and how late can it be? How are differences between the two sides reconciled, and what difference is acceptable? Which side is the source of truth for the monthly reconciliation, and what is the dispute process?
Status
This profile is a proposal for discussion and is not live yet. Fields and behaviour may change until version 1.0.0; from then on changes follow the Partner API rules: additive only.
Calls we make to your server
These are requests our platform sends to a URL you provide. Your server answers them as described.
Bid request#
One request per screen slot. The body is an OpenRTB 2.6 BidRequest with the fields listed in the request profile. The partner answers with a BidResponse or 204.
The content type is application/json. The header x-openrtb-version: 2.6 is sent as the specification recommends.
The response is described with the same operation because OpenRTB defines it as the answer to this call.
Body we send · application/json
| Field | Type | Description | Example |
|---|---|---|---|
| idrequired | string | Identifier of the request, unique for each request. |
8f3a1c92e7b04d5a |
| atrequired | integer one of: 1 | Auction type. Always 1, first price. |
1 |
| tmaxrequired | integer | Maximum time in milliseconds for the bid to arrive, including network time. |
500 |
| currequired | string[] | Allowed currencies, ISO 4217 codes. One value. |
|
| imprequired | object[] | The offered impressions. One entry per slot. |
|
| imp[].idrequired | string | Identifier of the impression inside the request. |
1 |
| imp[].tagidrequired | string | The screen id. The same screen always has the same value. |
173 |
| imp[].bidflooroptional | number | Minimum bid. Absent when the screen has no floor. By the OpenRTB definition it is a CPM. Whether the unit stays CPM is an open question. |
4.5 |
| imp[].bidfloorcuroptional | string | Currency of the floor, ISO 4217. |
USD |
| imp[].expoptional | integer | Upper bound, in seconds, for the time between the auction and the play. |
30 |
| imp[].dtrequired | number | The moment the slot is scheduled to play, in Unix milliseconds, UTC. |
1791454530000 |
| imp[].qtyoptional | object | The impression multiplier of one play. |
|
| imp[].qty.multiplierrequired | number | How many audience impressions one play counts for. |
14.2 |
| imp[].qty.sourcetypeoptional | integer one of: 0, 1, 2, 3 | Who measured the multiplier. 1 is a measurement vendor, 2 is the publisher, 3 is the exchange. |
2 |
| imp[].qty.vendoroptional | string | Domain of the measurement vendor. Sent only when |
vendor.example.com |
| imp[].videorequired | object | The slot as a video opportunity. |
|
| imp[].video.mimesrequired | string[] | Accepted content types. |
|
| imp[].video.mindurationrequired | integer | Slot length in seconds. |
10 |
| imp[].video.maxdurationrequired | integer | Slot length in seconds. Equal to |
10 |
| imp[].video.woptional | integer | Screen width in pixels. |
1080 |
| imp[].video.hoptional | integer | Screen height in pixels. |
1920 |
| doohrequired | object | The screen. |
|
| dooh.idrequired | string | The screen id, the same as |
173 |
| dooh.nameoptional | string | Display name of the screen. |
Dubai Marina Walk, west entrance |
| dooh.venuetyperequired | string[] | Venue type ids in the taxonomy given by |
|
| dooh.venuetypetaxrequired | integer | The taxonomy. 1 is the OpenOOH Venue Taxonomy 1.0. |
1 |
| dooh.domainoptional | string | Domain of the inventory owner. |
programmatic-engine.com |
| dooh.publisheroptional | object | The screen owner. |
|
| dooh.publisher.idoptional | string | Identifier of the screen owner in the supply chain. |
7 |
| dooh.publisher.nameoptional | string | Name of the screen owner. |
Marina network |
| deviceoptional | object | The screen hardware. There is no advertising id. |
|
| device.woptional | integer | Screen width in pixels. |
1080 |
| device.hoptional | integer | Screen height in pixels. |
1920 |
| device.geooptional | object | The position of the screen. |
|
| device.geo.latrequired | number | Latitude in degrees. |
25.0805 |
| device.geo.lonrequired | number | Longitude in degrees. |
55.1403 |
| device.geo.typeoptional | integer | Source of the location data. 1 is GPS or location services, meaning a surveyed position. |
1 |
| sourcerequired | object | The origin of the request. |
|
| source.schainrequired | object | The supply chain. |
|
| source.schain.verrequired | string | Version of the supply chain specification. |
1.0 |
| source.schain.completerequired | integer | 1 when the chain reaches the screen owner. |
1 |
| source.schain.nodesrequired | object[] | The entities in the chain, in order. The last one sends this request. |
|
| source.schain.nodes[].asirequired | string | Domain of the advertising system. |
programmatic-engine.com |
| source.schain.nodes[].sidrequired | string | Seller id within that system. |
7 |
| source.schain.nodes[].hprequired | integer | 1 when the node is paid. |
1 |
{
"id": "8f3a1c92e7b04d5a",
"at": 1,
"tmax": 500,
"cur": ["USD"],
"imp": [
{
"id": "1",
"tagid": "173",
"bidfloor": 4.5,
"bidfloorcur": "USD",
"exp": 30,
"dt": 1791454530000,
"qty": {
"multiplier": 14.2,
"sourcetype": 2
},
"video": {
"mimes": ["video/mp4"],
"minduration": 10,
"maxduration": 10,
"w": 1080,
"h": 1920
}
}
],
"dooh": {
"id": "173",
"name": "Dubai Marina Walk, west entrance",
"venuetype": ["3", "302"],
"venuetypetax": 1,
"domain": "programmatic-engine.com",
"publisher": {
"id": "7",
"name": "Marina network"
}
},
"device": {
"w": 1080,
"h": 1920,
"geo": {
"lat": 25.0805,
"lon": 55.1403,
"type": 1
}
},
"source": {
"schain": {
"ver": "1.0",
"complete": 1,
"nodes": [
{
"asi": "programmatic-engine.com",
"sid": "7",
"hp": 1
}
]
}
}
}
Expected responses
A bid.
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
| idrequired | string | The |
8f3a1c92e7b04d5a |
| currequired | string | Currency of the bid, ISO 4217. Must be allowed by the request. |
USD |
| seatbidrequired | object[] | One entry. |
|
| seatbid[].seatoptional | string | Identifier of the buyer seat. |
agency-4411 |
| seatbid[].bidrequired | object[] | One bid per impression. |
|
| seatbid[].bid[].idrequired | string | Identifier of the bid, assigned by the bidder. |
b-20261009-0001 |
| seatbid[].bid[].impidrequired | string | The |
1 |
| seatbid[].bid[].pricerequired | number | The bid. A CPM by the OpenRTB definition. |
6.8 |
| seatbid[].bid[].cridrequired | string | Identifier of a creative that was registered and approved before the auction. |
spring_2026_001 |
| seatbid[].bid[].adomainrequired | string[] | Advertiser domains. |
|
| seatbid[].bid[].duroptional | integer | Length of the creative in seconds. |
10 |
| seatbid[].bid[].nurloptional | string | Win noticeaddress. Optional. |
https://bidder.example.com/openrtb/win?id=8f3a1c92e7b04d5a&price=${AUCTION_PRICE} |
| seatbid[].bid[].burlrequired | string | Billing noticeaddress. Called after a verified play. |
https://bidder.example.com/openrtb/bill?id=8f3a1c92e7b04d5a&price=${AUCTION_PRICE}&mult=${AUCTION_MULTIPLIER}&ts=${AUCTION_IMP_TS} |
{
"id": "8f3a1c92e7b04d5a",
"cur": "USD",
"seatbid": [
{
"seat": "agency-4411",
"bid": [
{
"id": "b-20261009-0001",
"impid": "1",
"price": 6.8,
"crid": "spring_2026_001",
"adomain": ["example.com"],
"dur": 10,
"nurl": "https://bidder.example.com/openrtb/win?id=8f3a1c92e7b04d5a&price=${AUCTION_PRICE}",
"burl": "https://bidder.example.com/openrtb/bill?id=8f3a1c92e7b04d5a&price=${AUCTION_PRICE}&mult=${AUCTION_MULTIPLIER}&ts=${AUCTION_IMP_TS}"
}
]
}
]
} No bid. The body must be empty.
Win notice#
Called with GET on the nurl of the winning bid, right after the auction. The macro ${AUCTION_PRICE} is replaced with the clearing price. The notice is informational. It is not a billing event, and a failure does not cancel the win.
The nurl is optional in the bid.
Expected responses
The notice was received. Any 2xx status is accepted.
Billing notice#
Called with GET on the burl of the winning bid, after the creative has been played and the play has been verified. This is the billable event.
These OpenRTB macros are replaced: ${AUCTION_PRICE}, ${AUCTION_MULTIPLIER}, ${AUCTION_IMP_TS}, ${AUCTION_IMP_ID} and ${AUCTION_ID}. No other parameters are added.
The notice is sent once for each play. Whether it is repeated after a failure is an open question. Treat a repeat of the same ${AUCTION_ID} as one play.
Expected responses
The notice was received. Any 2xx status is accepted.