OpenRTB 2.5
Publisher API 2.5PubAdHub accepts OpenRTB 2.5 bid requests from publishers, supply partners, header bidding, and ad servers. Send one HTTP POST for each auction to http://rtb.pubadhub.com/openrtb/{PublisherKey}. When an ad is available, the response is a bid in US dollars plus a click URL. When no ad is available, the response is HTTP 204 with an empty body. The publisher key in the URL is your Publisher Identity. Use POST only. A GET request is not accepted as a bid request.
http://rtb.pubadhub.com
/openrtb/{PublisherKey}
price is earnings per click, not CPM
Authentication
There is no API token and no Authorization header. The {PublisherKey} path segment is your Publisher Identity. Your Account Manager provides it. It may contain letters, numbers, underscores, and hyphens, and it must be 1 to 64 characters. Replace YOUR_PUBLISHER_KEY in examples and do not leave the braces in the live URL. Keep it in your server configuration, and do not publish it on a web page. This path value is not the PublisherKey header used by product search, and it is not an AccessKey.
Headers
Send these request headers. Every response includes x-openrtb-version: 2.5. Read the HTTP status before you read the body. A 204 response has no body and no Content-Type.
Content-Type
REQUIRED
application/json
Request header. The body is an OpenRTB 2.5 bid request.
Accept
application/json
Optional request header.
| Name | Value | Required | Description |
|---|---|---|---|
| Content-Type | application/json | REQUIRED | Request header. The body is an OpenRTB 2.5 bid request. |
| Accept | application/json | — | Optional request header. |
Request fields
Send these OpenRTB fields on the bid request. A valid call needs id, imp, and imp.id, plus an advertiser domain or a keyword. A request with neither a domain nor a keyword is HTTP 204. Deeplink URLs are read from ext.deeplink on the impression, site, app, or bid request, and from imp.native.ext.url. Only the first impression is bid.
{PublisherKey}
Location: path
Your Publisher Identity, provided by your Account Manager. Letters, numbers, underscores, and hyphens only. 1 to 64 characters.
Example: YOUR_PUBLISHER_KEY
id
Location: body
Your auction id. It is returned on the bid response.
Example: auction-123
imp
Location: body
One or more impressions. Only the first is bid on. A single impression object is accepted and is treated as the first impression.
Example: [{"id":"1"}]
imp.id
Location: body
Impression id. It is returned as bid.impid.
Example: 1
site.domain or app.domain
Location: body
Brand domain, for example brand.com. A full URL is accepted and the host is used. Send a domain or a keyword. Missing both is HTTP 204.
Example: advertiser.example
site.page
Location: body
Page where the ad runs. Not an advertiser domain and not a deeplink. When no deeplink is sent, this page is used as ext.final_url when it is present.
imp.bidfloorcur
Location: body
Floor currency. USD is accepted. Any other currency is HTTP 204. If omitted, USD is used.
Example: USD
site.search or user.keywords
Location: body
User search keyword. When a keyword is present, price is the keyword bid. Send a domain or a keyword. Missing both is HTTP 204.
Example: running shoes
device.geo.country
Location: body
Send US or USA. You may place the country in user.geo.country instead. Any other country receives no bid. If the country is omitted, the request is treated as US.
Example: US
device.ua
Location: body
End-user browser user agent.
Example: Mozilla/5.0
device.ip
Location: body
End-user IPv4 address. Send an IPv6 address in device.ipv6. A valid IPv4 address is appended to the click URL as an integer.
Example: 8.8.8.8
device.ipv6
Location: body
End-user IPv6 address. Send this when device.ip is omitted. Both addresses are accepted. IPv6 is not added to the click URL.
Example: 2001:db8::1
imp.bidfloor
Location: body
Your floor, in the same USD earnings-per-click unit as price. A positive floor above the bid is HTTP 204. A bid equal to the floor can be returned.
Example: 0.10
imp.tagid
Location: body
Your placement or traffic-source id. When sent, it is appended to the click URL as subi.
Example: placement-1
site.publisher.id
Location: body
Your own id for this request. When it is present, it is used as clickid on the click URL.
user.id
Location: body
Used as clickid on the click URL only when site.publisher.id is empty or omitted.
Example: click-123
user.buyeruid
Location: body
Your user id. It is appended to the click URL as uid when sent.
Example: user-456
site.ref
Location: body
Referrer URL where the ad opportunity occurred.
Example: https://publisher.example/
ext.deeplink
Location: body
Deeplink URL on the impression, site, app, or bid request. imp.native.ext.url is also accepted. Omit it for a homepage bid. When a deeplink is sent and that advertiser has no verified deeplink campaign, the response is HTTP 204.
test
Location: body
Set to 1 only for an integration test. A bid that still clears the auction is returned with price 0, and the click URL includes tsts=1. A test flag does not turn a no-bid into a fill. Do not send this in live traffic.
Example: 1
| Name | Type | Required | Location | Description | Example |
|---|---|---|---|---|---|
| {PublisherKey} | string | Yes | path | Your Publisher Identity, provided by your Account Manager. Letters, numbers, underscores, and hyphens only. 1 to 64 characters. | YOUR_PUBLISHER_KEY |
| id | string | Yes | body | Your auction id. It is returned on the bid response. | auction-123 |
| imp | array | Yes | body | One or more impressions. Only the first is bid on. A single impression object is accepted and is treated as the first impression. | [{"id":"1"}] |
| imp.id | string | Yes | body | Impression id. It is returned as bid.impid. | 1 |
| site.domain or app.domain | string | One of these | body | Brand domain, for example brand.com. A full URL is accepted and the host is used. Send a domain or a keyword. Missing both is HTTP 204. | advertiser.example |
| site.page | string | No | body | Page where the ad runs. Not an advertiser domain and not a deeplink. When no deeplink is sent, this page is used as ext.final_url when it is present. | |
| imp.bidfloorcur | string | Recommended | body | Floor currency. USD is accepted. Any other currency is HTTP 204. If omitted, USD is used. | USD |
| site.search or user.keywords | string | One of these | body | User search keyword. When a keyword is present, price is the keyword bid. Send a domain or a keyword. Missing both is HTTP 204. | running shoes |
| device.geo.country | string | Recommended | body | Send US or USA. You may place the country in user.geo.country instead. Any other country receives no bid. If the country is omitted, the request is treated as US. | US |
| device.ua | string | Recommended | body | End-user browser user agent. | Mozilla/5.0 |
| device.ip | string | Recommended | body | End-user IPv4 address. Send an IPv6 address in device.ipv6. A valid IPv4 address is appended to the click URL as an integer. | 8.8.8.8 |
| device.ipv6 | string | Recommended | body | End-user IPv6 address. Send this when device.ip is omitted. Both addresses are accepted. IPv6 is not added to the click URL. | 2001:db8::1 |
| imp.bidfloor | number | Recommended | body | Your floor, in the same USD earnings-per-click unit as price. A positive floor above the bid is HTTP 204. A bid equal to the floor can be returned. | 0.10 |
| imp.tagid | string | Recommended | body | Your placement or traffic-source id. When sent, it is appended to the click URL as subi. | placement-1 |
| site.publisher.id | string | Recommended | body | Your own id for this request. When it is present, it is used as clickid on the click URL. | |
| user.id | string | Recommended | body | Used as clickid on the click URL only when site.publisher.id is empty or omitted. | click-123 |
| user.buyeruid | string | No | body | Your user id. It is appended to the click URL as uid when sent. | user-456 |
| site.ref | string | Recommended | body | Referrer URL where the ad opportunity occurred. | https://publisher.example/ |
| ext.deeplink | string | No | body | Deeplink URL on the impression, site, app, or bid request. imp.native.ext.url is also accepted. Omit it for a homepage bid. When a deeplink is sent and that advertiser has no verified deeplink campaign, the response is HTTP 204. | |
| test | integer | No | body | Set to 1 only for an integration test. A bid that still clears the auction is returned with price 0, and the click URL includes tsts=1. A test flag does not turn a no-bid into a fill. Do not send this in live traffic. | 1 |
API format
http://rtb.pubadhub.com/openrtb/{PublisherKey}
Request example
POST /openrtb/YOUR_PUBLISHER_KEY HTTP/1.1
Host: rtb.pubadhub.com
Content-Type: application/json
{
"id": "auction-123",
"imp": [{
"id": "1",
"bidfloor": 0.10,
"bidfloorcur": "USD",
"tagid": "placement-1"
}],
"site": {
"domain": "advertiser.example",
"ref": "https://publisher.example/",
"search": "running shoes"
},
"device": {
"ua": "Mozilla/5.0",
"ip": "8.8.8.8",
"ipv6": "2001:db8::1",
"geo": { "country": "US" }
},
"user": {
"id": "click-123",
"buyeruid": "user-456"
}
}
Response
Content-Type is application/json. x-openrtb-version is 2.5. The body is one BidResponse for the first impression only. id matches the request id. impid matches imp[0].id. bidid and bid.id are the same id. Sample seat, price, hosts, ENCRYPTED, BRAND-ID, and the UUID are placeholders. Each live response uses a new UUID. adomain, advertiser_name, and final_url can be empty. altered is false unless the request set imp.native.ext.alt. lurl is omitted because this endpoint does not send it. If HTTP 200 is not valid JSON, or id does not match the request, discard the response. This endpoint does not return a partial bid object.
{
"id": "auction-123",
"bidid": "7c1e4b2a-9f08-4d6e-a1b3-2e5f8c0d4a61",
"cur": "USD",
"seatbid": [
{
"seat": "YOUR_SEAT_OR_PUBLISHER_KEY",
"bid": [
{
"id": "7c1e4b2a-9f08-4d6e-a1b3-2e5f8c0d4a61",
"impid": "1",
"price": 0.2,
"adomain": [
"advertiser.example"
],
"adm": "{\"native\":{\"link\":{\"url\":\"https://click.example/track?encyp=ENCRYPTED&rtuli=9f3c2a1b0e8d7c6a5b4f3e2d1c0b9a87&clickid=click-123\"}}}",
"ext": {
"altered": false,
"final_url": "https://advertiser.example/",
"advertiser_name": "advertiser.example",
"advertiser_id": "BRAND-ID"
}
}
]
}
]
}
adm is a string, not an object. Parse that string as JSON. Every fill uses this shape, including when the bid request did not contain imp.native. There is no native version and there are no assets. native.link.url is the click redirect. The host in this example is a placeholder. The live URL is the click tracker configured for the integration.
{
"native": {
"link": {
"url": "https://click.example/track?encyp=ENCRYPTED&rtuli=9f3c2a1b0e8d7c6a5b4f3e2d1c0b9a87&clickid=click-123"
}
}
}
Empty body. x-openrtb-version is 2.5. There is no Content-Type and there is no JSON. Do not parse a body. This endpoint does not use HTTP 200 with an empty body, an empty seatbid array, or a no-bid reason field. HTTP 204 is returned when the country is not the United States (US and USA are accepted; an omitted country is treated as US); the request has no advertiser domain and no keyword; the Publisher Identity is not enabled for this endpoint; no advertiser matches the domain or keyword; the advertiser is blocked for this publisher or country; no homepage or deeplink campaign is available; a cap is already met, or the current hour is outside the allowed hours; a deeplink was sent and that advertiser has no verified deeplink campaign; or imp.bidfloorcur is not USD, or the bid is below a positive imp.bidfloor. HTTP 204 is a normal result. It is not an error. Do not retry the same auction in a loop.
The Publisher Identity is missing, contains characters other than letters, numbers, underscores, and hyphens, or is longer than 64 characters. The JSON error is "Invalid publisher key". Fix the request before you retry. Do not treat HTTP 400 as a no-bid.
{
"error": "Invalid publisher key"
}
The body is not JSON, id is missing or blank, or the first impression has no id. A single impression object is accepted and is treated as the first impression. Fix the request before you retry. Do not treat HTTP 400 as a no-bid.
{
"error": "Invalid OpenRTB bid request"
}
Response fields
A fill is HTTP 200 for imp[0] only. The tables in the PDF separate the OpenRTB 2.5 rule from what this endpoint sends. Extension fields are specific to this integration. This response does not send nbr, custom data, a response-level ext, seatbid[].group, lurl, campaign id, creative id, width, height, or deal id. price is USD earnings per click, rounded to 4 decimal places. JSON numbers drop trailing zeros, so 0.2000 is returned as 0.2. When the request includes a keyword, price is the keyword bid. A test request that still clears the floor is returned with price 0.
id
string
Copied from the bid request id. OpenRTB requires it. Use it to match the response to your auction.
Example: auction-123
bidid
string
A new UUID for this response. The same value is sent as seatbid[0].bid[0].id. OpenRTB marks bidid optional.
Example: 7c1e4b2a-9f08-4d6e-a1b3-2e5f8c0d4a61
cur
string
Always USD. OpenRTB treats cur as optional and uses USD when it is omitted.
Example: USD
seatbid
array
One seat object. That seat contains one bid. OpenRTB requires seatbid when a bid is made.
Example: [{...}]
seatbid[].bid
array
One bid, for imp[0] only. Additional impressions in the same request are not bid on. OpenRTB requires this array.
Example: [{...}]
seatbid[].seat
string
Buyer seat id. When a seat id has been assigned, that value is sent. Otherwise your Publisher Identity from the URL is sent. OpenRTB marks seat optional.
Example: YOUR_SEAT_OR_PUBLISHER_KEY
seatbid[].bid[].id
string
Bidder-generated bid id. Same UUID as the top-level bidid. OpenRTB requires it.
Example: 7c1e4b2a-9f08-4d6e-a1b3-2e5f8c0d4a61
seatbid[].bid[].impid
string
The imp.id of the impression that received the bid. This endpoint bids on imp[0]. OpenRTB requires it.
Example: 1
seatbid[].bid[].price
float
Earnings per click in USD, not CPM. Do not multiply or divide by 1000. Rounded to 4 decimal places. imp.bidfloor is compared in this same unit. A positive floor above the bid is HTTP 204. A bid equal to the floor can be returned. A non-USD imp.bidfloorcur is HTTP 204. If bidfloorcur is omitted, USD is used.
Example: 0.2
seatbid[].bid[].adm
string
Always sent on a fill. Ad markup as a JSON string. Parse it, then use native.link.url on a real user click. Do not call that URL from the bid server. OpenRTB marks adm optional.
Example: {"native":{"link":{"url":"https://click.example/track?encyp=ENCRYPTED&rtuli=9f3c2a1b0e8d7c6a5b4f3e2d1c0b9a87&clickid=click-123"}}}
seatbid[].bid[].adomain
array of strings
Advertiser host from site.domain or app.domain. One host, or an empty array when the advertiser was chosen from a keyword and no domain was sent. OpenRTB marks adomain optional.
Example: ["advertiser.example"]
seatbid[].bid[].lurl
string
Optional loss-notice URL in OpenRTB 2.5. This endpoint does not send lurl.
Example: Not sent
seatbid[].bid[].ext.final_url
string
Extension, sent on every fill. Absolute URL. A deeplink is used when one was sent. Otherwise site.page is used when it was sent. Otherwise the advertiser domain is used. A value without http:// or https:// is prefixed with https:// and a trailing slash. The string can be empty.
Example: https://advertiser.example/
seatbid[].bid[].ext.altered
boolean
Extension, sent on every fill. true only when imp.native.ext.alt is 1 or true, in any letter case. Otherwise false, including when imp.native is absent. This echoes the request flag. It does not mean the bidder changed the landing URL.
Example: false
seatbid[].bid[].ext.advertiser_name
string
Extension, sent on every fill. Advertiser host. Same host as the single adomain entry. Empty string when no domain was on the request.
Example: advertiser.example
seatbid[].bid[].ext.advertiser_id
string
Extension, sent on every fill. Internal advertiser id for the brand that was bid.
Example: BRAND-ID
| Name | Type | Description | Example |
|---|---|---|---|
| id | string | Copied from the bid request id. OpenRTB requires it. Use it to match the response to your auction. | auction-123 |
| bidid | string | A new UUID for this response. The same value is sent as seatbid[0].bid[0].id. OpenRTB marks bidid optional. | 7c1e4b2a-9f08-4d6e-a1b3-2e5f8c0d4a61 |
| cur | string | Always USD. OpenRTB treats cur as optional and uses USD when it is omitted. | USD |
| seatbid | array | One seat object. That seat contains one bid. OpenRTB requires seatbid when a bid is made. | [{...}] |
| seatbid[].bid | array | One bid, for imp[0] only. Additional impressions in the same request are not bid on. OpenRTB requires this array. | [{...}] |
| seatbid[].seat | string | Buyer seat id. When a seat id has been assigned, that value is sent. Otherwise your Publisher Identity from the URL is sent. OpenRTB marks seat optional. | YOUR_SEAT_OR_PUBLISHER_KEY |
| seatbid[].bid[].id | string | Bidder-generated bid id. Same UUID as the top-level bidid. OpenRTB requires it. | 7c1e4b2a-9f08-4d6e-a1b3-2e5f8c0d4a61 |
| seatbid[].bid[].impid | string | The imp.id of the impression that received the bid. This endpoint bids on imp[0]. OpenRTB requires it. | 1 |
| seatbid[].bid[].price | float | Earnings per click in USD, not CPM. Do not multiply or divide by 1000. Rounded to 4 decimal places. imp.bidfloor is compared in this same unit. A positive floor above the bid is HTTP 204. A bid equal to the floor can be returned. A non-USD imp.bidfloorcur is HTTP 204. If bidfloorcur is omitted, USD is used. | 0.2 |
| seatbid[].bid[].adm | string | Always sent on a fill. Ad markup as a JSON string. Parse it, then use native.link.url on a real user click. Do not call that URL from the bid server. OpenRTB marks adm optional. | {"native":{"link":{"url":"https://click.example/track?encyp=ENCRYPTED&rtuli=9f3c2a1b0e8d7c6a5b4f3e2d1c0b9a87&clickid=click-123"}}} |
| seatbid[].bid[].adomain | array of strings | Advertiser host from site.domain or app.domain. One host, or an empty array when the advertiser was chosen from a keyword and no domain was sent. OpenRTB marks adomain optional. | ["advertiser.example"] |
| seatbid[].bid[].lurl | string | Optional loss-notice URL in OpenRTB 2.5. This endpoint does not send lurl. | Not sent |
| seatbid[].bid[].ext.final_url | string | Extension, sent on every fill. Absolute URL. A deeplink is used when one was sent. Otherwise site.page is used when it was sent. Otherwise the advertiser domain is used. A value without http:// or https:// is prefixed with https:// and a trailing slash. The string can be empty. | https://advertiser.example/ |
| seatbid[].bid[].ext.altered | boolean | Extension, sent on every fill. true only when imp.native.ext.alt is 1 or true, in any letter case. Otherwise false, including when imp.native is absent. This echoes the request flag. It does not mean the bidder changed the landing URL. | false |
| seatbid[].bid[].ext.advertiser_name | string | Extension, sent on every fill. Advertiser host. Same host as the single adomain entry. Empty string when no domain was on the request. | advertiser.example |
| seatbid[].bid[].ext.advertiser_id | string | Extension, sent on every fill. Internal advertiser id for the brand that was bid. | BRAND-ID |
Click URL
The click URL is native.link.url inside the adm string. It is an absolute URL on the click tracker for this integration. Redirect the end user to that URL when the ad is clicked. Do not prefetch it, and do not call it from your bid server. Opening it outside a real user click can record a click. You may store the bid for the life of that auction only. Do not reuse a click URL on a later auction. Nothing on this URL is an OpenRTB macro, and nothing is substituted after the response is sent. The OpenRTB request id and the bid id are not query parameters. rtuli ties the click to the logged bid.
native.link.url
https://click.example/track?encyp=ENCRYPTED&rtuli=9f3c2a1b0e8d7c6a5b4f3e2d1c0b9a87&clickid=click-123
Redirect URL parameters
Values are appended only when they exist. The sample answers a request that sent user.id click-123 and no site.publisher.id, so clickid is user.id.
encyp
Opaque encrypted value. It contains the Publisher Identity, advertiser id, bid amount, and a typo id of 0.
Example: ENCRYPTED
rtuli
Internal request id for this auction. The click tracker uses it to associate the click with the logged bid. It is not the OpenRTB request id and it is not bid.id.
Example: 9f3c2a1b0e8d7c6a5b4f3e2d1c0b9a87
clickid
site.publisher.id when that value is present. Otherwise user.id.
Example: click-123
uid
Your user id.
Example: user-456
dl
The deeplink URL from the bid request.
subi
Your placement id.
Example: placement-1
ip
That address as an integer.
pli
Platform id for the campaign.
cc
Country used for the auction. This endpoint bids US only.
Example: US
tsts
Marks the click URL as a test. The value is 1.
Example: 1
| Name | Required | Description | Example |
|---|---|---|---|
| encyp | Always | Opaque encrypted value. It contains the Publisher Identity, advertiser id, bid amount, and a typo id of 0. | ENCRYPTED |
| rtuli | Always | Internal request id for this auction. The click tracker uses it to associate the click with the logged bid. It is not the OpenRTB request id and it is not bid.id. | 9f3c2a1b0e8d7c6a5b4f3e2d1c0b9a87 |
| clickid | When site.publisher.id or user.id was sent | site.publisher.id when that value is present. Otherwise user.id. | click-123 |
| uid | When user.buyeruid was sent | Your user id. | user-456 |
| dl | When the bid is a deeplink | The deeplink URL from the bid request. | |
| subi | When imp.tagid was sent | Your placement id. | placement-1 |
| ip | When device.ip is a valid IPv4 address | That address as an integer. | |
| pli | When the campaign has a platform id | Platform id for the campaign. | |
| cc | Always on a fill | Country used for the auction. This endpoint bids US only. | US |
| tsts | When test is 1 | Marks the click URL as a test. The value is 1. | 1 |
Errors
Invalid Publisher Identity
Invalid publisher key
{
"error": "Invalid publisher key"
}
Invalid bid request
Invalid OpenRTB bid request
{
"error": "Invalid OpenRTB bid request"
}
Notes
Original PDF
This page is sourced from the official API PDF. The original file remains available.
PubAdHub OpenRTB 2.5 Publisher Integration.pdf
Related documentation
RTB API
Request ads in real time from the PubAdHub RTB Serving Engine and receive a bid response with a redirect (tracking) URL when an ad is available.
http://rtb.pubadhub.com/serving-engine
OpenRTB Bid Response
HTTP 200 BidResponse from POST /openrtb/{PublisherKey}. price is USD earnings per click, not CPM. HTTP 204 is an empty no-bid and is not this object.
Open arrow_forwardInvalid Publisher Identity
HTTP 400 from OpenRTB 2.5 when the Publisher Identity is missing, contains characters other than letters, numbers, underscores, and hyphens, or is longer than 64 characters. The JSON error is "Invalid publisher key".
Open arrow_forwardInvalid OpenRTB bid request
HTTP 400 from OpenRTB 2.5 when the body is not JSON, id is missing or blank, or the first impression has no id.
Open arrow_forward