external supply integration · openrtb 2.5

Pop & Push Integration Guide

For SSPs and publishers sending pop-under or push traffic to TensorBids. If you can read JSON you already know most of this — the rest is where the money moves.

OpenRTB 2.5 Pop · CPM Push · CPC USD · first-price no bid · 204

Overview

Pop-underPush
RequestOpenRTB 2.5OpenRTB 2.5 or plain GET
ResponseOpenRTB bid, URL in admPush creative (title, images, click URL)
BillingCPM per 1,000 eventsCPC per click
No bid204 No Content204 No Content

Pick your integration below — you only need to read the one you are implementing. Feed setup, error handling and reporting apply to both.

Feed setup

We issue a separate feed per integration. You will receive a FEED_ID, a TOKEN, a REPORT_TOKEN and your bidder endpoint.

bidder endpoint
POST https://rtb.tensorbids.com/bidder?e={FEED_ID}&t={TOKEN} Content-Type: application/json
Keep the token private

TOKEN authenticates your feed. REPORT_TOKEN is separate and is only for the reporting API — it cannot be used to bid.

PropertyValue
ProtocolOpenRTB 2.5
MethodPOST (GET also available for push)
FormatJSON
CurrencyUSD
AuctionFirst-price
No bid204 No Content

Your integration

Bid request

A standard OpenRTB request. Mark the impression as pop with imp.ext.type and a 0×0 banner.

POST /bidder?e={FEED_ID}&t={TOKEN}
{ "id": "pop-test-1", "at": 1, "tmax": 200, "imp": [{ "id": "1", "banner": { "w": 0, "h": 0 }, "bidfloor": 0.50, "bidfloorcur": "USD", "ext": { "type": "pop" } }], "site": { "id": "66", "domain": "m.example.com", "page": "https://m.example.com/watch/1" }, "device": { "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/120.0 Safari/537.36", "ip": "8.8.8.0", "devicetype": 2, "os": "Windows", "language": "en", "connectiontype": 2 }, "user": { "id": "user-abc" } }
FieldDescription
imp.ext.typeMust be "pop"
imp.banner.w/hUse 0 × 0 for pop
imp.bidfloorMinimum CPM in USD
imp.bidfloorcurBid floor currency
site.domainPublisher domain
site.pagePage the traffic originated on
device.ipUser IP
device.uaUser-Agent
user.idPublisher-side user ID, when available
Send IP and User-Agent

device.ip and device.ua drive geo, device, OS and browser targeting. Without them a campaign that targets any of those cannot bid on your traffic, so omitting them costs you fill.

Bid response

A standard OpenRTB bid, with one important difference: adm holds a URL, not HTML.

200 OK
{ "id": "pop-test-1", "cur": "USD", "seatbid": [{ "seat": "<advertiser>", "bid": [{ "id": "<token>", "impid": "1", "price": 4.00, "adm": "https://rtb.tensorbids.com/click?b=<token>&r=<landing>", "nurl": "https://rtb.tensorbids.com/win?b=<token>&price=${AUCTION_PRICE}", "adid": "<creative>", "crid": "<creative>", "cid": "<campaign>", "adomain": ["example.com"] }] }] }
FieldDescription
priceCPM bid
admPop destination / tracking URL
nurlWin notification
adid / cridCreative identifiers
cidCampaign ID
adomainAdvertiser domain
Do not modify adm

Open it exactly as returned. It records the event and then redirects the user to the advertiser's landing page.

Do not replace it with the advertiser URL, and do not wrap it in another redirect — either one breaks tracking, and untracked traffic cannot be paid for.

Billing

Pop is billed CPM — per thousand events.

worked example
Bid price = $4.00 CPM 1,000 billable events = $4.00 1 billable event = $0.004
Two things in your favour

A bid that is never served is never charged, and duplicate tracking calls are de-duplicated automatically — so a retry cannot cost you.

Push is priced per click, not per mille

"price": 0.079 means $0.079 per click — not per 1,000 impressions. Impressions are tracked but never charged. This is the single most common misreading of this integration, so it is worth pausing on.

Bid request

A standard OpenRTB request with a push object inside the impression.

POST /bidder?e={FEED_ID}&t={TOKEN}
{ "id": "push-test-1", "at": 1, "tmax": 300, "cur": ["USD"], "imp": [{ "id": "1", "bidfloor": 0.05, "push": { "wmax": 400, "hmax": 400, "keyword": "home loan", "subId": "sub-0001" } }], "site": { "domain": "example.com", "page": "https://example.com/page" }, "device": { "ip": "103.132.244.0", "ua": "Mozilla/5.0 ..." }, "user": { "id": "user-123" } }
FieldDescription
bidfloorMinimum CPC in USD
push.keywordKeyword / topic
push.wmaxMaximum image width
push.hmaxMaximum image height
push.subIdPlacement / sub ID
Send IP and User-Agent

Used for geo, device, OS and browser targeting. Omitting them narrows which campaigns can bid on your traffic.

Bid response

200 OK
{ "id": "push-test-1", "cur": "USD", "seatbid": [{ "seat": "<advertiser>", "bid": [{ "id": "<token>", "impid": "1", "price": 0.079, "title": "Refinance today", "description": "Rates from 4.2%", "iconUrl": "https://cdn.example.com/icon.png", "imageUrl": "https://cdn.example.com/main.png", "clickUrl": "https://rtb.tensorbids.com/click?b=<token>&r=<landing>", "impTracker": [ "https://rtb.tensorbids.com/imp?b=<token>" ] }] }] }
FieldDescription
priceCPC bid
titleNotification title
descriptionNotification body
iconUrlNotification icon
imageUrlMain image
clickUrlClick tracking + redirect URL
impTrackerImpression tracking URL(s)
Use clickUrl as-is

Do not rewrite it or wrap it in another redirect.

Tracking & billing

EventWhat you doCharged?
ImpressionFire every URL in impTrackerNo
ClickOpen clickUrlYes
worked example
CPC = $0.079 1,000 clicks = $79.00
Please still fire the impression tracker

It costs you nothing — impressions are never charged — but it is what CTR and traffic-quality optimisation are computed from. Feeds that report impressions get bid on more accurately.

Duplicate clicks are de-duplicated automatically.

If you don't run OpenRTB, push can be integrated with a single GET request. The response is identical to the oRTB push response — same fields, same tracking, same CPC billing.

GET request
GET https://rtb.tensorbids.com/bidder/push ?e={FEED_ID} &t={TOKEN} &rid={REQUEST_ID} &id={IMP_ID} &ip={IP} &ua={USER_AGENT} &bid={BID_FLOOR} &dmn={DOMAIN} &wm={MAX_WIDTH} &hm={MAX_HEIGHT} &kw={KEYWORDS} &sub={SUB_ID} &pg={PAGE_URL} &lang={LANGUAGE} &cur={CURRENCY} &pid={PUBLISHER_ID} &pn={PUBLISHER_NAME} &ui={USER_ID} &cat={CATEGORIES}

Required

ParameterDescription
eFeed ID
tFeed token
ipUser IP
uaUser-Agent
bidCPC floor
dmnPublisher domain
wm / hmMaximum image dimensions

Everything else is optional. URL-encode values — pg and ua especially, since both routinely contain characters that will otherwise truncate the query.

A missing required parameter is a 400, not a 204

If you get 400, check the seven parameters above before anything else — that is almost always the cause.

Response

Identical to the oRTB push response: fire every impTracker, open clickUrl as-is, and you are billed per click.

No bid & errors

ResponseMeaningWhat to do
204No bid — nothing matched, or your floor was above every bidNormal. Move on.
400Malformed request, usually a missing required fieldCheck required params, then the JSON body
200A bidServe it

A 204 carries an empty body and is not an error — it is the expected answer whenever no campaign wants the impression.

Reporting API

Reconcile traffic, clicks and revenue against your own numbers.

GET
GET https://rtb.tensorbids.com/reportip/sspReport/reportsV2 ?fromDate={YYYY-MM-DD} &toDate={YYYY-MM-DD} &token={REPORT_TOKEN} &groupBy=date,country,device
ParameterRequiredDescription
tokenYesYour feed REPORT_TOKEN
fromDateYesStart date, UTC
toDateYesEnd date, UTC
groupByNoComma-separated dimensions

Maximum range 92 days per request.

Dimensions

groupBy accepts any of
date country region city device os browser connection isp domain publisher placement channel environment ad_position language

Response

200 OK
{ "Status": 200, "Message": "Data Found", "Timezone": "UTC", "Report": [{ "Date": "2026-07-15", "country": "us", "ssp_revenue": "27.598170", "bid_response": "26464", "bid_win": "0", "impression_count": "21242", "click_count": "3", "conversion_count": "1" }] }
Two parsing notes

Every value inside Report is a JSON string, including the numeric ones — cast before you do arithmetic on them.

When a range has no rows, Message is "No Data Found" and Report is an empty array. That is a success, not an error.

Timezone

All reporting is UTC, with the day starting at 00:00 UTC. Reconcile on UTC periods or your totals will disagree with ours by a few hours' traffic.

Quick reference

PopPush
ProtocolOpenRTB 2.5OpenRTB 2.5 / GET
PricingCPMCPC
RequestOpenRTB + imp.ext.type=popOpenRTB + push object
ResponseOpenRTB bidPush creative
CreativeURL in admTitle, description, images
Click URLadmclickUrl
Impression tracking—impTracker
No bid204204
The golden rules

Pop — send OpenRTB, receive adm, open it as-is.

Push — send OpenRTB or GET, render the creative, fire impTracker, use clickUrl for clicks.

Never rewrite or wrap a URL we return. That is the whole contract.

Questions, or a field that isn't behaving as documented? Reply to your integration thread and include a full request and response — that is almost always enough to resolve it in one round.