OpenRTB 2.6 Integration
The OpenRTB 2.6 interface provides compatibility with standard programmatic advertising systems and Supply-Side Platforms (SSPs). This interface bridges the gap between traditional RTB workflows and the Adlocaite platform.
Deprecated Interface - Limited Functionality
This interface is maintained for legacy compatibility only. We strongly recommend using the Core API instead, which provides:
- Real-time offer management with instant acceptance/rejection
- Precise timing control for optimal DOOH playout
- Full feature set including dynamic pricing and audience targeting
- Better performance and lower latency
The OpenRTB interface has significant functional limitations due to protocol constraints. Use it only if your system cannot be integrated via the Core API. See the Migration Guide for step-by-step instructions on switching to the Core API.
Overview
The OpenRTB 2.6 interface was developed for integration with Supply-Side Platforms (SSPs) and other standard RTB systems. It provides a bridge between traditional programmatic advertising workflows and the Adlocaite DOOH platform.
When to use this interface
Use the OpenRTB interface only in these scenarios:
- Your publisher management system is already integrated with an SSP that uses OpenRTB 2.6
- Your playout system cannot make direct API calls to the Adlocaite Core API
- You need compatibility with existing RTB workflows for legacy systems
For all other cases, use the Core API which provides superior functionality and performance.
Developer utilities
The interface publishes an OpenAPI 3.0 specification with every endpoint, schema and example. Use it to generate a client, or import it into a tool such as Postman or Insomnia.
Download the specification
Download the OpenAPI specification
curl -o openrtb-openapi.json \
https://api.adlocaite.com/functions/v1/openrtb-2-6/openapi.json
Or access directly in your browser:
- Production:
https://api.adlocaite.com/functions/v1/openrtb-2-6/openapi.json - Staging:
https://staging.api.adlocaite.com/functions/v1/openrtb-2-6/openapi.json
Generate a client
The document is a plain OpenAPI 3.0 file, so any generator accepts it:
openapi-generator-cli generate -i openrtb-openapi.json -g <your-language>
Import into Postman
- Open Postman and click Import in the top left
- Select the downloaded
openrtb-openapi.jsonfile, or paste the URL directly - Postman converts the specification into a collection with every endpoint pre-configured
Configure environment variables
After importing, set up your Postman environment with these variables:
- Name
base_url- Type
- string
- Description
Base URL for the OpenRTB API
- Production:
https://api.adlocaite.com/functions/v1/openrtb-2-6 - Staging:
https://staging.api.adlocaite.com/functions/v1/openrtb-2-6
- Production:
- Name
api_key- Type
- string
- Description
Your Publisher API Key for authentication
The specification includes example BidRequests that you can modify for your specific testing needs.
Implementation constraints
The OpenRTB 2.6 standard was designed for traditional web and mobile advertising. Digital Out-of-Home advertising requires precise timing, screen availability management, and real-time content delivery - capabilities that the OpenRTB protocol does not adequately support.
Why these limitations exist
The Adlocaite platform is optimized for reactive, real-time DOOH advertising where offers must be matched, accepted, and displayed within seconds. This approach maximizes:
- Revenue for publishers: By ensuring the highest-value advertisements are shown at the right time
- Campaign performance for advertisers: Through precise audience targeting and optimal timing
- System efficiency: By avoiding bid conflicts and reducing wasted inventory
The OpenRTB protocol, designed for auction-based environments with longer decision windows, cannot fully support this reactive model. Therefore, this interface operates with significant functional constraints to maintain system integrity.
Supported features
- Name
Single impression per request- Description
Only one impression can be requested per BidRequest. Multiple impressions are not supported.
- Name
Fixed price deals only- Description
Auction type must be Fixed Price (at=3). First-price and second-price auctions are not supported.
- Name
Video format only- Description
Only the Video object format is supported. Banner format is not available.
- Name
External Screen ID required- Description
Each request must include a valid External Screen ID in the tagid field. Our implementation assumes tagid contains the screen identifier; other SSPs may use different identifier attributes.
- Name
Exact resolution matching- Description
Screen resolution must exactly match the requested dimensions. No scaling or format adaptation.
- Name
Audience quantity required- Description
Every request must state how many people one play reaches, either as imp.qty.multiplier (OpenRTB 2.6, preferred) or as the legacy imp.ext.totalaud. If both are present, imp.qty.multiplier is used.
Not supported
- Multiple impressions per request
- Open auction formats (First-price, Second-price)
- Banner object format
- Dynamic creative optimization
- Synchronous offer acceptance/rejection (the OpenRTB path learns about lost bids asynchronously via the loss notification URL, see below)
- Flexible scheduling and timing control
How it works
The OpenRTB integration follows a simplified request-response flow:
Request flow
- BidRequest received: SSP sends OpenRTB 2.6 BidRequest with screen details and deal information
- Validation: Request is validated against implementation constraints
- Screen identification: External Screen ID is extracted from imp.tagid (our implementation assumes tagid contains the screen identifier)
- Minimum bid calculation: Floor price is calculated from deal.bidfloor × the audience quantity (imp.qty.multiplier, or imp.ext.totalaud for legacy requests)
- Offer matching: Platform finds matching offers for the screen above minimum bid
- Resolution check: Asset resolution must exactly match requested dimensions
- VAST generation: VAST 4.0 XML is generated with tracking URLs and OpenRTB macros
- BidResponse returned: Response includes bid price, VAST XML, and deal information
Response types
- Name
HTTP 200 + BidResponse- Description
Successful bid with offer details and VAST XML
- Name
HTTP 200 + Empty seatbid- Description
No bid with reason code (NBR) - technical error or constraint violation
- Name
HTTP 204 No Content- Description
No bid - no matching offers available
- Name
HTTP 400 Bad Request- Description
Validation error - request does not meet implementation constraints
- Name
HTTP 401 Unauthorized- Description
Missing or invalid API key
- Name
HTTP 500 Internal Server Error- Description
Unexpected server error
Asset matching
The platform matches advertisements to screens based on the screen type configured by the publisher. When registering a screen, publishers specify which type of content their screen can display.
Screen types and asset compatibility
Publishers classify their screens into one of three types when registering them in the platform:
- Static Screen: Displays only static images (JPEG, PNG)
- Slow Screen: Displays static images and slow animations (Cinemagraphs)
- Moving Screen: Displays any asset type - static images, slow animations, or full video
The matching algorithm automatically selects assets that are compatible with the publisher-configured screen type. The following table shows which asset types can be returned for each screen type:
Screen Type | Static Assets | Slow Assets | Moving Assets |
|---|---|---|---|
Static Screen | ✓ | ✗ | ✗ |
Slow Screen | ✓ | ✓ | ✗ |
Moving Screen | ✓ | ✓ | ✓ |
How the matching works
When a BidRequest arrives, the platform performs the following steps:
- Screen identification: The External Screen ID from
imp.tagidis used to look up the screen and its type (static/slow/moving) - Asset selection: The matching algorithm finds the best matching advertisement and selects an asset that is compatible with the screen type
- MIME type check: The selected asset's MIME type is verified against the SSP's allowed types in
video.mimes - Response generation: A VAST 4.0 XML response is generated with the asset URL and correct MIME type
SSP MIME type signaling
SSPs use the video.mimes array in the BidRequest to specify which file formats they accept. For example:
- Roadside screens (image-only):
["image/jpeg", "image/png"] - Indoor video screens:
["video/mp4", "video/webm"] - Flexible screens:
["video/mp4", "video/webm", "image/jpeg", "image/png"]
The platform checks that the selected asset's MIME type is included in this list. If not, a no-bid response is returned.
Matching examples
Example 1: Moving Screen with video restriction
- Screen Type: Moving
- SSP allows:
["video/mp4"] - Available assets: Static image, Video
- Result: Video asset is selected (compatible with both screen type and SSP requirements)
Example 2: Static Screen with flexible SSP
- Screen Type: Static
- SSP allows:
["video/mp4", "image/jpeg"] - Available assets: Static image, Video
- Result: Static image is selected (only compatible asset for static screen)
Example 3: No compatible asset
- Screen Type: Static
- SSP allows:
["video/mp4"] - Available assets: Static image
- Result: No-bid (HTTP 204) - static image not allowed by SSP
VAST response format
All responses use VAST 4.0 XML format. The MediaFile tag's MIME type reflects the actual asset format:
For static images:
<MediaFile type="image/jpeg" width="1080" height="1920">
<![CDATA[https://storage.adlocaite.com/assets/static-ad.jpg]]>
</MediaFile>
<Duration>00:00:10</Duration>
For videos:
<MediaFile type="video/mp4" width="1080" height="1920">
<![CDATA[https://storage.adlocaite.com/assets/video-ad.mp4]]>
</MediaFile>
<Duration>00:00:15</Duration>
The platform automatically determines the correct MIME type from the asset file extension.
Authentication
Authentication uses Bearer token authentication with your Publisher API Key.
Authentication
curl -X POST https://api.adlocaite.com/functions/v1/openrtb-2-6/bid \
-H "Authorization: Bearer YOUR_PUBLISHER_API_KEY" \
-H "Content-Type: application/json" \
-d @bidrequest.json
See the Authentication guide for details on obtaining your API key.
Endpoints
POST /bid
Submit a BidRequest for a specific screen and receive a BidResponse with pricing and creative details.
This is the main endpoint for OpenRTB bidding. The SSP sends a BidRequest containing screen information, deal details, and audience data. The platform responds with either a bid including VAST XML or a no-bid response.
Required headers
- Name
Authorization- Type
- string
- Description
Bearer token with your Publisher API Key
- Name
Content-Type- Type
- string
- Description
Must be
application/json
Request
curl -X POST https://api.adlocaite.com/functions/v1/openrtb-2-6/bid \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": "auction-12345",
"imp": [{
"id": "1",
"tagid": "screen-ext-001",
"video": {
"mimes": ["video/mp4"],
"w": 1920,
"h": 1080
},
"pmp": {
"deals": [{
"id": "deal-001",
"bidfloor": 2.50,
"at": 3
}]
},
"qty": {
"multiplier": 119.47,
"sourcetype": 1,
"vendor": "measurement-vendor.example"
}
}],
"at": 3
}'
Response (200 - Bid)
{
"id": "auction-12345",
"seatbid": [{
"bid": [{
"id": "bid-uuid-12345",
"impid": "1",
"price": 2.50,
"adid": "offer-uuid-67890",
"adm": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><VAST version=\"4.0\">...</VAST>",
"adomain": ["adlocaite.com"],
"cid": "offer-uuid-67890",
"crid": "offer-uuid-67890",
"dealid": "deal-001",
"w": 1920,
"h": 1080
}]
}],
"bidid": "bidid-uuid-99999",
"cur": "EUR"
}
Response (204 - No Bid)
No Content
Response (400 - Validation Error)
{
"error": "MULTI_IMP_NOT_SUPPORTED",
"message": "Multiple impressions per request are currently not supported",
"details": {
"imp_count": 3
}
}
POST /
Alternative endpoint that routes to the same bid handler. Use /bid for clarity.
BidRequest format
The BidRequest must follow OpenRTB 2.6 specification with specific requirements for Adlocaite integration.
Required fields
- Name
id- Type
- string
- Description
Unique auction identifier
- Name
imp- Type
- array
- Description
Array with exactly one impression object
- Name
imp[0].id- Type
- string
- Description
Impression identifier
- Name
imp[0].tagid- Type
- string
- Description
External Screen ID for screen identification (our implementation assumes tagid contains the screen identifier; other SSPs may use different identifier attributes)
- Name
imp[0].video- Type
- object
- Description
Video object with width and height
- Name
imp[0].video.w- Type
- integer
- Description
Screen width in pixels
- Name
imp[0].video.h- Type
- integer
- Description
Screen height in pixels
- Name
imp[0].pmp- Type
- object
- Description
Private Marketplace object
- Name
imp[0].pmp.deals- Type
- array
- Description
Array with at least one deal object
- Name
imp[0].pmp.deals[0].id- Type
- string
- Description
Deal identifier
- Name
imp[0].pmp.deals[0].bidfloor- Type
- number
- Description
Minimum CPM in EUR
- Name
imp[0].pmp.deals[0].at- Type
- integer
- Description
Must be 3 (Fixed Price)
- Name
imp[0].qty.multiplier- Type
- number
- Description
Audience size for one play, used for the bid floor calculation. This is the OpenRTB 2.6 field for the purpose (section 3.2.31) and the preferred way to send the number. Required unless your request carries the audience size in the legacy imp[0].ext.totalaud instead -- send one of the two, not both.
- Name
at- Type
- integer
- Description
Auction type, must be 3 (Fixed Price)
Optional and legacy fields
These are not required. imp[0].ext.totalaud is the one exception: it stands in for imp[0].qty.multiplier, so a request that omits both is rejected.
- Name
imp[0].qty.sourcetype- Type
- integer
- Description
Optional. Who measured the quantity, per the AdCOM list "DOOH Multiplier Measurement Source Types": 0 unknown, 1 measurement vendor, 2 publisher, 3 exchange. Send it if you have it -- it tells us how the number came about.
- Name
imp[0].qty.vendor- Type
- string
- Description
Domain of the measurement vendor. Optional in general, but the specification requires it when sourcetype is 1.
- Name
imp[0].ext.totalaud- Type
- number
- Description
Legacy alternative to imp[0].qty.multiplier, carrying the same number. Predates OpenRTB 2.6 and is still accepted for existing integrations. Use imp.qty for new ones -- it is the only one of the two that can express where the number came from. If a request carries both, imp[0].qty.multiplier is used.
Minimum bid calculation
The minimum bid in cents is calculated as:
minBidCents = (bidfloor × audience) / 10
Where audience is imp.qty.multiplier, or imp.ext.totalaud if the request uses the legacy field.
Example:
- bidfloor = 2.50 EUR CPM
- audience = 119.47 impressions
- minBidCents = (2.50 × 119.47) / 10 = 30 cents
BidResponse format
The BidResponse follows OpenRTB 2.6 specification with VAST 4.0 XML for creative delivery.
Successful bid
- Name
id- Type
- string
- Description
Mirrors BidRequest.id
- Name
seatbid- Type
- array
- Description
Array containing seat bid objects
- Name
seatbid[0].bid- Type
- array
- Description
Array containing bid objects
- Name
seatbid[0].bid[0].id- Type
- string
- Description
Unique bid identifier (UUID)
- Name
seatbid[0].bid[0].impid- Type
- string
- Description
Mirrors impression ID from BidRequest
- Name
seatbid[0].bid[0].price- Type
- number
- Description
Bid price in EUR (converted from cents)
- Name
seatbid[0].bid[0].adm- Type
- string
- Description
VAST 4.0 XML containing creative and tracking information
- Name
seatbid[0].bid[0].lurl- Type
- string
- Description
Loss notice URL. Call it when the bid loses, with
${AUCTION_LOSS}substituted by the loss reason code. See Loss notifications. Nonurlorburlis sent; billing is triggered by the VAST impression callback only.
- Name
seatbid[0].bid[0].adomain- Type
- array
- Description
Advertiser domains (["adlocaite.com"])
- Name
seatbid[0].bid[0].dealid- Type
- string
- Description
Deal ID from BidRequest
- Name
seatbid[0].bid[0].w- Type
- integer
- Description
Creative width
- Name
seatbid[0].bid[0].h- Type
- integer
- Description
Creative height
- Name
bidid- Type
- string
- Description
Unique bid transaction identifier (UUID)
- Name
cur- Type
- string
- Description
Currency code (EUR)
Example Response
{
"id": "auction-12345",
"seatbid": [{
"bid": [{
"id": "f7b3c9e1-4d2a-4c8b-9a1e-3f5d6c7b8a9d",
"impid": "1",
"price": 2.53,
"adid": "offer-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"adm": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<VAST version=\"4.0\">...</VAST>",
"lurl": "https://api.adlocaite.com/functions/v1/openrtb-2-6/loss/a1b2c3d4-e5f6-7890-abcd-ef1234567890?reason=${AUCTION_LOSS}&price=${AUCTION_PRICE}&cur=${AUCTION_CURRENCY}&mtw=${AUCTION_MIN_TO_WIN}&aid=${AUCTION_ID}&pub=...&scr=...&ts=1756900000&token=...",
"adomain": ["adlocaite.com"],
"cid": "offer-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"crid": "offer-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"dealid": "deal-001",
"w": 1920,
"h": 1080
}]
}],
"bidid": "bid-transaction-uuid-99999",
"cur": "EUR"
}
Note: The adm field contains the complete VAST 4.0 XML (truncated above for readability). See the /bid endpoint response for a full example.
No-bid response
- Name
id- Type
- string
- Description
Mirrors BidRequest.id
- Name
seatbid- Type
- array
- Description
Empty array
- Name
nbr- Type
- integer
- Description
No-bid reason code (0 = Unknown, 1 = Technical Error)
- Name
cur- Type
- string
- Description
Currency code (EUR)
Example Response
{
"id": "auction-12345",
"seatbid": [],
"nbr": 0,
"cur": "EUR"
}
OpenRTB macros in tracking URLs
The VAST XML includes tracking URLs with OpenRTB macros that are replaced by the SSP:
${AUCTION_PRICE}: Final auction price${TOTAL_IMP}: Total audience impressions
Example tracking URL:
https://tracking.adlocaite.io/track?offer_id=abc-123&event=impression&price=${AUCTION_PRICE}&aud=${TOTAL_IMP}
Loss notifications
Every bid carries a loss notice URL as defined by OpenRTB 2.6: lurl. It points at the OpenRTB endpoint itself (next to the impression callback) and is signed; call it exactly as returned, with the macros substituted. No request body is required or read for the outcome itself; the information is in the URL. Win notices (nurl) and billing notices (burl) are not part of the bid response: the VAST impression callback is the only billing event.
Loss notices matter for you as much as for us: a bid that never receives a loss notice keeps its budget reservation until the offer expires, which lowers the advertiser budget available for your screens in the meantime. Sending lurl promptly frees that budget within about a minute.
GET https://api.adlocaite.com/functions/v1/openrtb-2-6/loss/{offer_id}?reason=${AUCTION_LOSS}&price=${AUCTION_PRICE}
&cur=${AUCTION_CURRENCY}&mtw=${AUCTION_MIN_TO_WIN}&aid=${AUCTION_ID}&pub=...&scr=...&ts=...&token=...
Macros
- Name
${AUCTION_LOSS}- Type
- integer
- Description
OpenRTB 2.6 loss reason code. 0 = bid won, 1 to 10 = technical (invalid response, expired impression, missing markup, ...), 100 to 104 = auction (below floor, lost to higher bid, lost to PMP deal, seat blocked), 200 to 213 = creative filtered (201 = pending approval, 202 = disapproved by the exchange), 1000 and above = exchange specific.
- Name
${AUCTION_PRICE}- Type
- number
- Description
Clearing price of the winning bid (CPM). On a loss notice this is the winner's price, not ours; it is stored for analysis and never used for billing.
- Name
${AUCTION_MIN_TO_WIN}- Type
- number
- Description
Minimum bid that would have won. Optional.
- Name
${AUCTION_ID}- Type
- string
- Description
The BidRequest id.
- Name
${AUCTION_CURRENCY}- Type
- string
- Description
Currency of the auction price.
${TOTAL_IMP} is not part of the notice URL. It belongs in the VAST impression tracking URL only.
Behaviour
- Method:
GET.POSTwith a JSON body is accepted as well and the body is stored for diagnostics, but it is not required. - Response:
204 No Contentwhen the notice was accepted. There is never a response body. - Timing: a notice may arrive late; the URL stays valid for 24 hours after the bid response.
- Idempotency: retries of the same notice are safe. The first call counts, later calls only increment a counter.
- Loss notices release the advertiser budget reserved for the bid. A loss notice for a bid that was already billed is recorded and ignored.
- Unsubstituted macros (the literal
${AUCTION_LOSS}) are tolerated: the notice is stored without the value.
Notice response codes
- Name
204- Description
Notice accepted.
- Name
403- Description
Signature invalid or
tsoutside the 24 hour window. The URL was altered or was not issued by Adlocaite.
- Name
413 / 414- Description
Request body above 16 KB or query string above 4 KB. Send the URL as returned.
- Name
503- Description
Temporary ingestion problem. Retry with backoff; the notice remains valid.
Error handling
The OpenRTB interface uses standard HTTP status codes and error response format.
Error response format
{
"error": "ERROR_CODE",
"message": "Human-readable error description",
"details": {
"additional": "context information"
},
"deprecated": true,
"deprecation_message": "This OpenRTB interface is legacy and will be phased out. Please migrate to the official Adlocaite API.",
"documentation": "https://docs.adlocaite.com",
"migration_guide": "https://docs.adlocaite.com/migration/openrtb-to-api"
}
error, message and details describe the failure. The remaining fields are the deprecation notice and are identical on every response, so match on error rather than on the text.
Deprecation signalling
Every response carries the deprecation notice as headers:
Deprecation: true
Link: <https://docs.adlocaite.com/migration/openrtb-to-api>; rel="deprecation"
The header names follow RFC 9745 (Deprecation) and RFC 8288 (Link). Note that RFC 9745 defines the value of Deprecation as a structured field date; this interface sends the boolean true instead. Treat the presence of the header as the signal and do not parse its value as a date.
The headers are on all responses, including the 204 no-bid, which has no body to carry the notice in. A successful 200 BidResponse carries it in ext.adlocaite instead of at the top level, so the OpenRTB 2.6 schema stays intact.
Common error codes
- Name
INVALID_API_KEY- Description
Missing or invalid API key in Authorization header (HTTP 401)
- Name
MULTI_IMP_NOT_SUPPORTED- Description
Request contains multiple impressions (HTTP 400)
- Name
NO_VIDEO_OBJECT- Description
Video object is missing or Banner format was used (HTTP 400)
- Name
NO_PMP_DEALS- Description
PMP deals array is missing or empty (HTTP 400)
- Name
NOT_FIXED_PRICE- Description
Auction type is not Fixed Price (at≠3) (HTTP 400)
- Name
NO_EXTERNAL_SCREEN_ID- Description
tagid field is missing (HTTP 400)
- Name
NO_TOTAL_AUDIENCE- Description
No usable audience quantity: neither imp.qty.multiplier nor imp.ext.totalaud was present and greater than 0 (HTTP 400). The code keeps its historical name. Note that if you send imp.qty, its multiplier must be valid -- we will not fall back to imp.ext.totalaud in that case.
- Name
NO_RESOLUTION- Description
Video width or height is missing (HTTP 400)
No-bid reason codes (NBR)
When returning HTTP 200 with empty seatbid, the nbr field indicates the reason:
- Name
0- Description
Unknown error or resolution mismatch
- Name
1- Description
Technical error (RPC failure, database error)
For legitimate no-bid scenarios (no matching offers, minimum bid not met), HTTP 204 is returned without a response body.