Context
The POST /auction endpoint accepts AdRequest { adUnits[], config? }. When called without Prebid.js (e.g. from slim-Prebid, a native app, or a server-side caller):
bids[] is optional — if absent or empty, AdSlot.bidders is an empty map
- An empty
bidders map triggers the PBS stored-request fallback: imp.ext.prebid.storedrequest = { id: slot_code }
- Full consent pipeline runs (cookies + headers + geo + KV store)
- EC ID is generated per-call (stateless — no session threading)
- No slot-template expansion — caller must construct
adUnits explicitly
Minimum valid request
{
"adUnits": [{
"code": "atf_sidebar_ad",
"mediaTypes": { "banner": { "sizes": [[300, 250]] } }
}]
}
PBS stored request keyed by "atf_sidebar_ad" must exist for this to produce bids.
Action
- Add API documentation to
auction/endpoints.rs covering both inline-params and stored-request paths
- Add an integration test covering the no-
bids path verifying storedrequest is set in the outgoing OpenRTB
- Confirm
config passthrough keys allowed via auction.allowed_context_keys are documented for callers
Parent: #677
Resolution
Server-side automatic auction (publisher page load, no Pbjs)
Distinct from POST /auction. When a publisher page loads and slots match creative-opportunities.toml, the server fires an auction automatically via publisher.rs → build_auction_request → prebid.rs:to_openrtb. The following OpenRTB fields are populated and forwarded to PBS:
| OpenRTB Field |
Value |
Source |
request.id |
"ts-{ec_id}" |
EC ID from cookie or freshly generated (publisher.rs:1213) |
site.page |
Full URL (scheme://host/path) |
Reconstructed from request headers (publisher.rs:1208) |
site.domain |
Publisher hostname |
Host header (publisher.rs:1231) |
imp[].id |
Slot ID |
creative-opportunities.toml via to_ad_slot() |
imp[].banner.formats |
Ad sizes |
creative-opportunities.toml via to_ad_slot() |
imp[].ext.prebid.storedrequest.id |
Stored request ID |
creative-opportunities.toml via to_ad_slot() |
imp[].bidfloor |
Floor price |
creative-opportunities.toml via to_ad_slot() |
user.id |
EC ID |
Cookie or freshly generated (publisher.rs:1220) |
user.ext.eids |
Extended User IDs |
ts-eids cookie, consent-gated (publisher.rs:947) |
user.ext.consent |
TCF string |
euconsent-v2 cookie via ConsentContext |
regs.ext.gdpr |
0 or 1 |
Geo + consent cookie detection via build_regs() |
device.ua |
User-Agent string |
User-Agent request header (publisher.rs:1225) |
device.ip |
Real client IP |
Fastly client_info.client_ip (publisher.rs:948) |
device.geo |
country, city, region, lat, lon, metro |
Fastly geo lookup (publisher.rs:949) |
device.dnt |
Do-Not-Track flag |
DNT header (prebid.rs:to_openrtb) |
device.language |
Language preference |
Accept-Language header (prebid.rs:to_openrtb) |
Note: device.ip and device.geo were previously missing (None). Fixed in PR #680 — missing IP caused bidders (e.g. PubMatic) to filter the request as non-human traffic, reducing fill rate.
Context
The
POST /auctionendpoint acceptsAdRequest { adUnits[], config? }. When called without Prebid.js (e.g. from slim-Prebid, a native app, or a server-side caller):bids[]is optional — if absent or empty,AdSlot.biddersis an empty mapbiddersmap triggers the PBS stored-request fallback:imp.ext.prebid.storedrequest = { id: slot_code }adUnitsexplicitlyMinimum valid request
{ "adUnits": [{ "code": "atf_sidebar_ad", "mediaTypes": { "banner": { "sizes": [[300, 250]] } } }] }PBS stored request keyed by
"atf_sidebar_ad"must exist for this to produce bids.Action
auction/endpoints.rscovering both inline-params and stored-request pathsbidspath verifyingstoredrequestis set in the outgoing OpenRTBconfigpassthrough keys allowed viaauction.allowed_context_keysare documented for callersParent: #677
Resolution
Server-side automatic auction (publisher page load, no Pbjs)
Distinct from
POST /auction. When a publisher page loads and slots matchcreative-opportunities.toml, the server fires an auction automatically viapublisher.rs → build_auction_request → prebid.rs:to_openrtb. The following OpenRTB fields are populated and forwarded to PBS:request.id"ts-{ec_id}"publisher.rs:1213)site.pagescheme://host/path)publisher.rs:1208)site.domainHostheader (publisher.rs:1231)imp[].idcreative-opportunities.tomlviato_ad_slot()imp[].banner.formatscreative-opportunities.tomlviato_ad_slot()imp[].ext.prebid.storedrequest.idcreative-opportunities.tomlviato_ad_slot()imp[].bidfloorcreative-opportunities.tomlviato_ad_slot()user.idpublisher.rs:1220)user.ext.eidsts-eidscookie, consent-gated (publisher.rs:947)user.ext.consenteuconsent-v2cookie viaConsentContextregs.ext.gdpr0or1build_regs()device.uaUser-Agentrequest header (publisher.rs:1225)device.ipclient_info.client_ip(publisher.rs:948)device.geopublisher.rs:949)device.dntDNTheader (prebid.rs:to_openrtb)device.languageAccept-Languageheader (prebid.rs:to_openrtb)Note:
device.ipanddevice.geowere previously missing (None). Fixed in PR #680 — missing IP caused bidders (e.g. PubMatic) to filter the request as non-human traffic, reducing fill rate.