OpenRTB protocol
The OpenRTB Audio object
imp.audio is a sibling of imp.video, not a variant of it. It keeps everything about duration, protocols, delivery, bit rate, pods and companion units, drops everything visual, and adds three fields that only make sense for a medium nobody is looking at. Understanding which of those three you are receiving tells you more about the inventory than any other field in the request.
What audio does not have
The absences are informative. There is no w or h, no plcmt, no linearity, no skip, no playbackmethod, no boxingallowed. All of those describe a rectangle or a viewer's relationship to one.
The consequence for buyers is that the filtering habits built for video do not transfer. There is no placement subtype to segment on. The nearest equivalent is feed, and it carries far less resolution: three values covering the entire medium.
The core fields
| Field | Type | Status | Meaning |
|---|---|---|---|
mimes | string array | Required | Supported content MIME types, for example audio/mp4. The only required field on the object. |
protocols | integer array | Recommended | Supported creative subtypes. This is the same AdCOM list video uses, because DAAST was folded into VAST 4.1 and audio creatives are VAST documents. |
minduration | integer | Recommended | Minimum ad duration in seconds. |
maxduration | integer | Recommended | Maximum ad duration in seconds. |
startdelay | integer | Recommended | 0 pre-roll, a positive number for a mid-roll at that offset, -1 generic mid-roll, -2 generic post-roll. In podcasting this is the difference between a pre-roll and a mid-roll rate card. |
On protocols: audio creatives are VAST. DAAST was deprecated and folded into VAST 4.1 in 2018, so the creative subtype list is the same one video uses, and an audio integration that treats DAAST as a live standard is describing something that stopped existing.
A podcast mid-roll, as a request
Two slots in one dynamically inserted break, sharing a podid, on a feed type of podcast with the ad stitched server-side:
"imp": [{
"id": "1",
"audio": {
"mimes": ["audio/mpeg", "audio/mp4", "audio/aac"],
"protocols": [7, 8],
"minduration": 15,
"maxduration": 30,
"startdelay": -1,
"feed": 3,
"stitched": 1,
"nvol": 1,
"podid": "midroll-1",
"slotinpod": 1,
"maxseq": 2,
"companiontype": [1, 2],
"delivery": [2]
},
"bidfloor": 18.0,
"bidfloorcur": "USD",
"secure": 1
}]Three things in that payload are worth copying. startdelay of -1 marks a generic mid-roll, which is what dynamic insertion actually produces, rather than a fixed offset the platform cannot honour. stitched of 1 tells the buyer up front that no client will be firing trackers. And delivery of 2 says progressive, which is what a downloaded episode is, as opposed to the streaming value a music service would send.
The three audio-only fields
| Field | Type | Status | Meaning |
|---|---|---|---|
feed | integer | Audio only | Feed type from the AdCOM Feed Types list: music streaming service, broadcast simulcast, podcast. This is the single most important audio-specific field, because the three environments have different measurement, different pricing and different creative expectations. |
stitched | integer | Audio only | 1 if the ad is stitched server-side into the content stream. Dynamic ad insertion is the norm in podcasting, so this is usually 1, and it changes who is responsible for firing trackers. |
nvol | integer | Audio only | Volume normalization mode applied to the stream, from the AdCOM Volume Normalization Modes list. Loudness mismatch between content and ad is the most common listener complaint in audio, and this is the only field that addresses it. |
feed is doing an enormous amount of work for one integer. A podcast impression, a music streaming impression and a broadcast simulcast impression have different listener contexts, different completion behaviour and different measurement regimes. Podcast inventory in particular is measured from server-side download logs rather than from playback confirmation, because most podcast applications never report back to anyone.
stitched is the field that determines who fires the trackers. In a stitched break the assets are assembled server-side into the audio stream, so the player is not making a tracking decision at all. That is the same problem CTV has with imp.ssai, and it has the same consequence: identity and IP must be passed through from the real device rather than reflecting the stitching server.
Fields shared with video
| Field | Type | Status | Meaning |
|---|---|---|---|
podid, podseq, slotinpod | string, integer | 2.6 | Ad break identity and slot position, identical in shape to video. |
poddur, maxseq | integer | 2.6 | Dynamic pod duration and maximum ad count. |
rqddurs | integer array | 2.6 | Exact acceptable durations. Mutually exclusive with minduration and maxduration. |
mincpmpersec, durfloors | float, DurFloors array | 2.6 | Duration-based pricing, so a 15 second and a 60 second spot can price differently in the same slot. |
delivery | integer array | Optional | Streaming, progressive, or download. |
minbitrate, maxbitrate | integer | Optional | Bit rate bounds in Kbps. |
maxextended | integer | Optional | Extended duration beyond maxduration. 0 none, -1 unlimited. |
api | integer array | Optional | Supported API frameworks. Rarely populated meaningfully in audio. |
battr | integer array | Optional | Blocked creative attributes. |
companionad, companiontype | Banner array, integer array | Optional | Display units shown alongside the audio ad, described as Banner objects. The companion is often the only visual surface an audio campaign gets. |
sequence | integer | Deprecated | Pre-2.6 ordering within a break. Superseded by slotinpod. |
A podcast or streaming break is a pod, structurally identical to a television one. Two or three spots, ordered, sometimes with duration constraints the publisher cannot relax. The 2.6 pod fields cover it without modification, which is why they were defined on both objects at once. See CTV and ad pods for the mechanics.
The measurement asymmetry
This is the part of audio that has no analogue in video, and it explains most of the disputes on an audio campaign.
A video impression is confirmed by a player that fired a pixel. A podcast download is inferred from a server log, using a byte threshold, a deduplication window and a filter against known invalid traffic. The IAB Tech Lab Podcast Technical Measurement Guidelines exist to make that inference consistent across vendors, and version 2.3 went to public comment in July 2026 with clearer handling of duplicates, measurement windows and video podcasts.
Nothing in a bid request changes that. What the request does control is whether the creative that gets served can be measured at all: the protocols list determines which VAST versions arrive, and the tag that arrives determines whether tracking events exist. If the tag is malformed, the download count is unaffected and the impression count is wrong, and the gap between them gets attributed to methodology.
Validate it
Audio requests fail in quieter ways than video ones, because there is no screen to look at. The recurring defects are a missing or empty mimes, no protocols list at all, rqddurs sent alongside minduration and maxduration when the two are mutually exclusive, and pod fields left in ext from a pre-2.6 integration.
Paste a request into the bid request tester, run the CLI in CI, or give an agent the MCP server. The short version of this page is at how audio ads work in OpenRTB, and the creative half is covered at VASTlint's audio and podcast guide.