Programmatic EngineAPI All connections

OpenRTB DOOH profile

Version 0.1.0

Base URL

https://bidder.example.com/openrtb · The partner's bidder. Not defined yet. This address is a placeholder.

Authentication

API key, sent in the header X-Auth-Token

A shared secret in a header. The authentication method is to be agreed; a shared secret in a header is assumed.

Spec file
openrtb-dooh.yaml

Import into Postman: File → Import → paste the URL.

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.ifa is never sent, and there is no user object.

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.

POSTbidRequestWe send

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

FieldTypeDescriptionExample
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 sourcetype is 1.

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 minduration.

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 imp.tagid.

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 venuetypetax. For the OpenOOH taxonomy this is a parent id followed by a child id.

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

200

A bid.

Response fields
FieldTypeDescriptionExample
idrequired string

The id of the bid request.

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 id of the impression this bid is for.

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}"
                }
            ]
        }
    ]
}
204

No bid. The body must be empty.

GETwinNoticeWe send

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

200

The notice was received. Any 2xx status is accepted.

GETbillingNoticeWe send

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

200

The notice was received. Any 2xx status is accepted.