How do audio ads work in OpenRTB?
Short answer
Audio inventory is offered through imp.audio, a sibling of imp.video with its own object definition. Only mimes is required; the recommended set is minduration, maxduration, protocols, and startdelay, which distinguishes pre-roll, mid-roll, and post-roll. Creatives are VAST: DAAST was folded into VAST 4.1 and later, so the protocols list is the same creative subtype list video uses. Streaming audio uses the same pod fields as CTV (poddur, podid, rqddurs, slotinpod, mincpmpersec), and audio-specific fields cover feed type, whether the ad is stitched server-side, volume normalisation, and companion display units.
Audio is its own impression object
Programmatic audio, streaming music, radio simulcast, and podcasts, is sold through imp.audio. It sits alongside banner, video, and native on the impression, and like them it can be combined: an impression that carries both audio and banner is offering an audio ad with a companion display unit.
A bid on an audio impression sets mtype to 3, and the markup in adm is VAST XML. If the exchange is going to check that the markup matches what was offered, and most do, an audio bid returning display markup is dropped with loss reason 204.
The fields, and which ones you cannot skip
| Field | Status | What it decides |
|---|---|---|
mimes | Required | Which audio formats the player accepts |
minduration, maxduration | Recommended | The length window the creative must fall inside |
protocols | Recommended | Accepted creative subtypes: VAST versions and legacy DAAST |
startdelay | Recommended | Pre-roll (0), mid-roll at a known offset (>0), generic mid-roll (-1), generic post-roll (-2) |
feed | Optional | Music service, broadcast simulcast, podcast, from the AdCOM Feed Types list |
stitched | Optional | Whether the ad is inserted server-side into the stream |
nvol | Optional | Volume normalisation mode applied to the stream |
companionad, companiontype | Optional | Display units shown alongside the audio ad, described as Banner objects |
podid, poddur, rqddurs, slotinpod, maxseq, mincpmpersec, durfloors | Optional | Ad break structure and duration-based pricing, identical in shape to video |
A minimal audio impression
"imp": [{
"id": "1",
"audio": {
"mimes": ["audio/mp4", "audio/mpeg"],
"minduration": 10,
"maxduration": 30,
"protocols": [7, 8],
"startdelay": -1,
"feed": 3,
"stitched": 1,
"companiontype": [1, 2]
},
"bidfloor": 18.0,
"bidfloorcur": "USD"
}]This says: a mid-roll slot in a podcast, ten to thirty seconds, VAST 4.0 or its wrapper, stitched server-side, companion static or HTML resources accepted, floor of $18 CPM. startdelay of -1 is the generic mid-roll value, used when the exact position in the stream is not known at request time; -2 is generic post-roll.
What is different about the surrounding request
- Context is usually app. Streaming audio lives in mobile apps, smart speakers, and car head units, so
appplusdevice.devicetypeanddevice.ifacarry more weight than any page-level signal. - Content metadata matters more. The
Contentobject'sartist,album,isrc,series, andgenrefields exist for exactly this channel, and podcast buyers target on them. - No viewability. Audio has no visual surface, so measurement is completion-based. Companion banners are the only visual inventory, and they may never render on a screenless device.
- Duration pricing is common.
durfloorsandmincpmpersecapply toimp.audioexactly as they do to video. See bid floors.
The mistakes that break audio requests
Three recur. Copying a video builder and leaving visual fields behind produces openrtb.field.undefined for things like plcmt or linearity under audio, which do not exist there. Omitting mimes makes the impression unbiddable and trips openrtb.field.required. And declaring pod fields such as mincpmpersec without any pod context produces a warning, because duration-based pricing with no declared break structure is almost always a builder bug. Paste a real audio request into the tester to see which applies. Pod mechanics are covered in CTV and ad pods.