diff --git a/adapters/tpmn/params_test.go b/adapters/tpmn/params_test.go
new file mode 100644
index 00000000000..7bd7c478638
--- /dev/null
+++ b/adapters/tpmn/params_test.go
@@ -0,0 +1,44 @@
+package tpmn
+
+import (
+ "encoding/json"
+ "github.com/prebid/prebid-server/openrtb_ext"
+ "testing"
+)
+
+var validParams = []string{
+ `{"inventoryId": 10000001}`,
+}
+
+var invalidParams = []string{
+ `{"inventoryId": "00000001"}`,
+ `{"inventoryid": 100000000}`,
+}
+
+// TestValidParams makes sure that the tpmn schema accepts all imp.ext fields which we intend to support.
+func TestValidParams(t *testing.T) {
+ validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+ if err != nil {
+ t.Fatalf("Failed to fetch the json-schemas. %v", err)
+ }
+
+ for _, validParam := range validParams {
+ if err := validator.Validate(openrtb_ext.BidderTpmn, json.RawMessage(validParam)); err != nil {
+ t.Errorf("Schema rejected TPMN params: %s", validParam)
+ }
+ }
+}
+
+// TestInvalidParams makes sure that the tpmn schema rejects all the imp.ext fields we don't support.
+func TestInvalidParams(t *testing.T) {
+ validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+ if err != nil {
+ t.Fatalf("Failed to fetch the json-schemas. %v", err)
+ }
+
+ for _, invalidParam := range invalidParams {
+ if err := validator.Validate(openrtb_ext.BidderTpmn, json.RawMessage(invalidParam)); err == nil {
+ t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+ }
+ }
+}
diff --git a/adapters/tpmn/tpmn.go b/adapters/tpmn/tpmn.go
new file mode 100644
index 00000000000..7afe94e5f79
--- /dev/null
+++ b/adapters/tpmn/tpmn.go
@@ -0,0 +1,126 @@
+package tpmn
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "strings"
+
+ "github.com/prebid/openrtb/v19/openrtb2"
+ "github.com/prebid/prebid-server/adapters"
+ "github.com/prebid/prebid-server/config"
+ "github.com/prebid/prebid-server/openrtb_ext"
+)
+
+// TpmnAdapter struct
+type adapter struct {
+ uri string
+}
+
+// MakeRequests makes the HTTP requests which should be made to fetch bids from TpmnBidder.
+func (rcv *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+ validImps, errs := getValidImpressions(request, reqInfo)
+ if len(validImps) == 0 {
+ return nil, errs
+ }
+
+ request.Imp = validImps
+
+ requestBodyJSON, err := json.Marshal(request)
+ if err != nil {
+ errs = append(errs, err)
+ return nil, errs
+ }
+
+ headers := http.Header{}
+ headers.Add("Content-Type", "application/json;charset=utf-8")
+ headers.Add("Accept", "application/json")
+
+ return []*adapters.RequestData{{
+ Method: http.MethodPost,
+ Uri: rcv.uri,
+ Body: requestBodyJSON,
+ Headers: headers,
+ }}, errs
+}
+
+// getValidImpressions validate imps and check for bid floor currency. Convert to EUR if necessary
+func getValidImpressions(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]openrtb2.Imp, []error) {
+ var errs []error
+ var validImps []openrtb2.Imp
+
+ for _, imp := range request.Imp {
+ if err := preprocessBidFloorCurrency(&imp, reqInfo); err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ validImps = append(validImps, imp)
+ }
+ return validImps, errs
+}
+
+func preprocessBidFloorCurrency(imp *openrtb2.Imp, reqInfo *adapters.ExtraRequestInfo) error {
+ // we expect every currency related data to be EUR
+ if imp.BidFloor > 0 && strings.ToUpper(imp.BidFloorCur) != "USD" && imp.BidFloorCur != "" {
+ if convertedValue, err := reqInfo.ConvertCurrency(imp.BidFloor, imp.BidFloorCur, "USD"); err != nil {
+ return err
+ } else {
+ imp.BidFloor = convertedValue
+ }
+ }
+ imp.BidFloorCur = "USD"
+ return nil
+}
+
+func (a *adapter) MakeBids(request *openrtb2.BidRequest, _ *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+ if adapters.IsResponseStatusCodeNoContent(responseData) {
+ return nil, nil
+ }
+
+ if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil {
+ return nil, []error{err}
+ }
+
+ var response openrtb2.BidResponse
+ if err := json.Unmarshal(responseData.Body, &response); err != nil {
+ return nil, []error{fmt.Errorf("bid response unmarshal: %v", err)}
+ }
+
+ bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
+ bidResponse.Currency = response.Cur
+ for _, seatBid := range response.SeatBid {
+ for i, bid := range seatBid.Bid {
+ bidType, err := getMediaTypeForImp(bid)
+ if err != nil {
+ return nil, []error{err}
+ }
+ b := &adapters.TypedBid{
+ Bid: &seatBid.Bid[i],
+ BidType: bidType,
+ }
+ bidResponse.Bids = append(bidResponse.Bids, b)
+ }
+ }
+ return bidResponse, nil
+}
+
+func getMediaTypeForImp(bid openrtb2.Bid) (openrtb_ext.BidType, error) {
+ switch bid.MType {
+ case openrtb2.MarkupBanner:
+ return openrtb_ext.BidTypeBanner, nil
+ case openrtb2.MarkupVideo:
+ return openrtb_ext.BidTypeVideo, nil
+ case openrtb2.MarkupNative:
+ return openrtb_ext.BidTypeNative, nil
+ default:
+ return "", fmt.Errorf("unsupported MType %d", bid.MType)
+ }
+}
+
+// Builder builds a new instance of the TpmnBidder adapter for the given bidder with the given config.
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
+ bidder := &adapter{
+ uri: config.Endpoint,
+ }
+ return bidder, nil
+}
diff --git a/adapters/tpmn/tpmn_test.go b/adapters/tpmn/tpmn_test.go
new file mode 100644
index 00000000000..6fbd85936f1
--- /dev/null
+++ b/adapters/tpmn/tpmn_test.go
@@ -0,0 +1,20 @@
+package tpmn
+
+import (
+ "testing"
+
+ "github.com/prebid/prebid-server/adapters/adapterstest"
+ "github.com/prebid/prebid-server/config"
+ "github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestJsonSamples(t *testing.T) {
+ bidder, buildErr := Builder(openrtb_ext.BidderTpmn, config.Adapter{
+ Endpoint: "https://gat.tpmn.io/ortb/pbs_bidder"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
+
+ if buildErr != nil {
+ t.Fatalf("Builder returned unexpected error %v", buildErr)
+ }
+
+ adapterstest.RunJSONBidderTest(t, "tpmntest", bidder)
+}
diff --git a/adapters/tpmn/tpmntest/exemplary/simple-banner.json b/adapters/tpmn/tpmntest/exemplary/simple-banner.json
new file mode 100644
index 00000000000..197d03b174e
--- /dev/null
+++ b/adapters/tpmn/tpmntest/exemplary/simple-banner.json
@@ -0,0 +1,135 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "tagid": "00000001",
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "https://gat.tpmn.io/ortb/pbs_bidder",
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "tagid": "00000001",
+ "bidfloorcur": "USD",
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+ }
+ }
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "test_bid_id",
+ "impid": "test-imp-id",
+ "price": 0.27543,
+ "adm": "",
+ "cid": "test_cid",
+ "crid": "test_crid",
+ "dealid": "test_dealid",
+ "w": 300,
+ "h": 250,
+ "mtype": 1,
+ "ext": {
+ "prebid": {
+ "type": "banner"
+ }
+ }
+ }
+ ],
+ "seat": "tpmn"
+ }
+ ],
+ "cur": "USD"
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [
+ {
+ "bids": [
+ {
+ "bid": {
+ "id": "test_bid_id",
+ "impid": "test-imp-id",
+ "price": 0.27543,
+ "adm": "",
+ "cid": "test_cid",
+ "crid": "test_crid",
+ "dealid": "test_dealid",
+ "w": 300,
+ "h": 250,
+ "mtype": 1,
+ "ext": {
+ "prebid": {
+ "type": "banner"
+ }
+ }
+ },
+ "type": "banner"
+ }
+ ]
+ }
+ ]
+}
diff --git a/adapters/tpmn/tpmntest/exemplary/simple-native.json b/adapters/tpmn/tpmntest/exemplary/simple-native.json
new file mode 100644
index 00000000000..1880c74ac7e
--- /dev/null
+++ b/adapters/tpmn/tpmntest/exemplary/simple-native.json
@@ -0,0 +1,119 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "device": {
+ "ip": "123.123.123.123",
+ "ua": "iPad"
+ },
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "tagid": "test",
+ "native": {
+ "request": "{\"ver\":\"1.1\",\"layout\":1,\"adunit\":2,\"plcmtcnt\":6,\"plcmttype\":4,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"wmin\":492,\"hmin\":328,\"type\":3,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":4,\"required\":0,\"data\":{\"type\":6}},{\"id\":5,\"required\":0,\"data\":{\"type\":7}},{\"id\":6,\"required\":0,\"data\":{\"type\":1,\"len\":20}}]}",
+ "ver": "1.1"
+ },
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ]
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "https://gat.tpmn.io/ortb/pbs_bidder",
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "tagid": "test",
+ "native": {
+ "request": "{\"ver\":\"1.1\",\"layout\":1,\"adunit\":2,\"plcmtcnt\":6,\"plcmttype\":4,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"wmin\":492,\"hmin\":328,\"type\":3,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":4,\"required\":0,\"data\":{\"type\":6}},{\"id\":5,\"required\":0,\"data\":{\"type\":7}},{\"id\":6,\"required\":0,\"data\":{\"type\":1,\"len\":20}}]}",
+ "ver": "1.1"
+ },
+ "bidfloorcur": "USD",
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ua": "iPad"
+ }
+ }
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "test_bid_id",
+ "impid": "test-imp-id",
+ "price": 0.27543,
+ "adm": "",
+ "cid": "test_cid",
+ "crid": "test_crid",
+ "dealid": "test_dealid",
+ "w": 300,
+ "h": 250,
+ "mtype": 4,
+ "ext": {
+ "prebid": {
+ "type": "native"
+ }
+ }
+ }
+ ],
+ "seat": "tpmn"
+ }
+ ],
+ "cur": "USD"
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [
+ {
+ "bids": [
+ {
+ "bid": {
+ "id": "test_bid_id",
+ "impid": "test-imp-id",
+ "price": 0.27543,
+ "adm": "",
+ "cid": "test_cid",
+ "crid": "test_crid",
+ "dealid": "test_dealid",
+ "w": 300,
+ "h": 250,
+ "mtype": 4,
+ "ext": {
+ "prebid": {
+ "type": "native"
+ }
+ }
+ },
+ "type": "native"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/adapters/tpmn/tpmntest/exemplary/simple-site-banner.json b/adapters/tpmn/tpmntest/exemplary/simple-site-banner.json
new file mode 100644
index 00000000000..8f7c5d59301
--- /dev/null
+++ b/adapters/tpmn/tpmntest/exemplary/simple-site-banner.json
@@ -0,0 +1,132 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ],
+ "site": {
+ "id": "1",
+ "domain": "test.com"
+ },
+ "device": {
+ "ip": "123.123.123.123"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "https://gat.tpmn.io/ortb/pbs_bidder",
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "bidfloorcur": "USD",
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ],
+ "site": {
+ "id": "1",
+ "domain": "test.com"
+ },
+ "device": {
+ "ip": "123.123.123.123"
+ }
+ }
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "test_bid_id",
+ "impid": "test-imp-id",
+ "price": 0.27543,
+ "adm": "",
+ "cid": "test_cid",
+ "crid": "test_crid",
+ "dealid": "test_dealid",
+ "w": 468,
+ "h": 60,
+ "mtype": 1,
+ "ext": {
+ "prebid": {
+ "type": "banner"
+ }
+ }
+ }
+ ],
+ "seat": "tpmn"
+ }
+ ],
+ "cur": "USD"
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [
+ {
+ "bids": [
+ {
+ "bid": {
+ "id": "test_bid_id",
+ "impid": "test-imp-id",
+ "price": 0.27543,
+ "adm": "",
+ "cid": "test_cid",
+ "crid": "test_crid",
+ "dealid": "test_dealid",
+ "w": 468,
+ "h": 60,
+ "mtype": 1,
+ "ext": {
+ "prebid": {
+ "type": "banner"
+ }
+ }
+ },
+ "type": "banner"
+ }
+ ]
+ }
+ ]
+}
+
\ No newline at end of file
diff --git a/adapters/tpmn/tpmntest/exemplary/simple-site-native.json b/adapters/tpmn/tpmntest/exemplary/simple-site-native.json
new file mode 100644
index 00000000000..20e6c23e966
--- /dev/null
+++ b/adapters/tpmn/tpmntest/exemplary/simple-site-native.json
@@ -0,0 +1,104 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "site": {
+ "page": "prebid.org"
+ },
+ "device": {
+ "ip":"123.123.123.123"
+ },
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "native": {
+ "ver": "1.1",
+ "request": "{\"ver\":\"1.0\",\"layout\":1,\"adunit\":1,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":60,\"hmin\":60,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":75}},{\"id\":4,\"required\":0,\"data\":{\"type\":6,\"len\":1000}},{\"id\":5,\"required\":0,\"data\":{\"type\":7,\"len\":1000}},{\"id\":6,\"required\":0,\"data\":{\"type\":11,\"len\":1000}}]}"
+ },
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ]
+ },
+
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "https://gat.tpmn.io/ortb/pbs_bidder",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ]
+ },
+ "body": {
+ "id": "test-request-id",
+ "site": {
+ "page": "prebid.org"
+ },
+ "device": {
+ "ip":"123.123.123.123"
+ },
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "native": {
+ "ver": "1.1",
+ "request": "{\"ver\":\"1.0\",\"layout\":1,\"adunit\":1,\"plcmttype\":1,\"plcmtcnt\":1,\"seq\":0,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":60,\"hmin\":60,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":3,\"required\":0,\"data\":{\"type\":2,\"len\":75}},{\"id\":4,\"required\":0,\"data\":{\"type\":6,\"len\":1000}},{\"id\":5,\"required\":0,\"data\":{\"type\":7,\"len\":1000}},{\"id\":6,\"required\":0,\"data\":{\"type\":11,\"len\":1000}}]}"
+ },
+ "bidfloorcur": "USD",
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ]
+ }
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "seatbid": [
+ {
+ "seat": "tpmn",
+ "bid": [{
+ "id": "1",
+ "impid": "test-imp-id",
+ "price": 0.500000,
+ "adm": "some-test-adm",
+ "crid": "test-crid",
+ "mtype": 4
+ }]
+ }
+ ],
+ "cur": "USD"
+ }
+ }
+ }
+ ],
+
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "1",
+ "impid": "test-imp-id",
+ "price": 0.5,
+ "adm": "some-test-adm",
+ "crid": "test-crid",
+ "mtype": 4
+ },
+ "type": "native"
+ }
+ ]
+ }
+ ]
+}
diff --git a/adapters/tpmn/tpmntest/exemplary/simple-site-video.json b/adapters/tpmn/tpmntest/exemplary/simple-site-video.json
new file mode 100644
index 00000000000..7b2375cd07a
--- /dev/null
+++ b/adapters/tpmn/tpmntest/exemplary/simple-site-video.json
@@ -0,0 +1,128 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "site": {
+ "page": "prebid.org"
+ },
+ "device": {
+ "ip":"123.123.123.123"
+ },
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "protocols": [
+ 2,
+ 3,
+ 5,
+ 6
+ ],
+ "w": 1024,
+ "h": 576
+ },
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ]
+ },
+
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "https://gat.tpmn.io/ortb/pbs_bidder",
+ "headers": {
+ "Accept": [
+ "application/json"
+ ],
+ "Content-Type": [
+ "application/json;charset=utf-8"
+ ]
+ },
+ "body": {
+ "id": "test-request-id",
+ "site": {
+ "page": "prebid.org"
+ },
+ "device": {
+ "ip":"123.123.123.123"
+ },
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "protocols": [
+ 2,
+ 3,
+ 5,
+ 6
+ ],
+ "w": 1024,
+ "h": 576
+ },
+ "bidfloorcur": "USD",
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ]
+ }
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "cur": "USD",
+ "seatbid": [
+ {
+ "seat": "tpmn",
+ "bid": [
+ {
+ "id": "1",
+ "impid": "test-imp-id",
+ "price": 0.500000,
+ "adm": "some-test-adm",
+ "crid": "test-crid",
+ "w": 1024,
+ "h": 576,
+ "mtype": 2
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ],
+
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "1",
+ "impid": "test-imp-id",
+ "price": 0.5,
+ "adm": "some-test-adm",
+ "crid": "test-crid",
+ "w": 1024,
+ "h": 576,
+ "mtype": 2
+ },
+ "type": "video"
+ }
+ ]
+ }
+ ]
+}
diff --git a/adapters/tpmn/tpmntest/exemplary/simple-video.json b/adapters/tpmn/tpmntest/exemplary/simple-video.json
new file mode 100644
index 00000000000..505b6167069
--- /dev/null
+++ b/adapters/tpmn/tpmntest/exemplary/simple-video.json
@@ -0,0 +1,130 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+ },
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "protocols": [
+ 2,
+ 5
+ ],
+ "w": 1024,
+ "h": 576
+ },
+ "bidfloorcur": "USD",
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ]
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "https://gat.tpmn.io/ortb/pbs_bidder",
+ "body": {
+ "id": "test-request-id",
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+ },
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "video": {
+ "mimes": [
+ "video/mp4"
+ ],
+ "protocols": [
+ 2,
+ 5
+ ],
+ "w": 1024,
+ "h": 576
+ },
+
+ "bidfloorcur": "USD",
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ]
+ }
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": {
+ "id": "test-request-id",
+ "seatbid": [
+ {
+ "bid": [
+ {
+ "id": "test_bid_id",
+ "impid": "test-imp-id",
+ "price": 0.27543,
+ "adm": "00:01:00",
+ "cid": "test_cid",
+ "crid": "test_crid",
+ "dealid": "test_dealid",
+ "mtype": 2,
+ "ext": {
+ "prebid": {
+ "type": "video"
+ }
+ }
+ }
+ ],
+ "seat": "tpmn"
+ }
+ ],
+ "cur": "USD"
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [
+ {
+ "currency": "USD",
+ "bids": [
+ {
+ "bid": {
+ "id": "test_bid_id",
+ "impid": "test-imp-id",
+ "price": 0.27543,
+ "adm": "00:01:00",
+ "cid": "test_cid",
+ "crid": "test_crid",
+ "mtype": 2,
+ "dealid": "test_dealid",
+ "ext": {
+ "prebid": {
+ "type": "video"
+ }
+ }
+ },
+ "type": "video"
+ }
+ ]
+ }
+ ]
+}
diff --git a/adapters/tpmn/tpmntest/supplemental/bad-imp-ext.json b/adapters/tpmn/tpmntest/supplemental/bad-imp-ext.json
new file mode 100644
index 00000000000..3bbb23f95a4
--- /dev/null
+++ b/adapters/tpmn/tpmntest/supplemental/bad-imp-ext.json
@@ -0,0 +1,79 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "tagid": "00000001",
+ "ext": {
+ }
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "https://gat.tpmn.io/ortb/pbs_bidder",
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "tagid": "00000001",
+ "bidfloorcur": "USD",
+ "ext": {
+ }
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+ }
+ }
+ },
+ "mockResponse": {
+ "status": 204,
+ "body": {
+ }
+ }
+ }
+ ],
+ "expectedBidResponses": [
+ ]
+}
diff --git a/adapters/tpmn/tpmntest/supplemental/bad_response.json b/adapters/tpmn/tpmntest/supplemental/bad_response.json
new file mode 100644
index 00000000000..12c3a72d49f
--- /dev/null
+++ b/adapters/tpmn/tpmntest/supplemental/bad_response.json
@@ -0,0 +1,87 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "bidfloorcur": "USD",
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "https://gat.tpmn.io/ortb/pbs_bidder",
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "bidfloorcur": "USD",
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+ }
+ }
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": ""
+ }
+ }
+ ],
+ "expectedMakeBidsErrors": [
+ {
+ "value": "bid response unmarshal: json: cannot unmarshal string into Go value of type openrtb2.BidResponse",
+ "comparison": "literal"
+ }
+ ]
+}
diff --git a/adapters/tpmn/tpmntest/supplemental/no-imp-ext.json b/adapters/tpmn/tpmntest/supplemental/no-imp-ext.json
new file mode 100644
index 00000000000..8bcbb93d004
--- /dev/null
+++ b/adapters/tpmn/tpmntest/supplemental/no-imp-ext.json
@@ -0,0 +1,81 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "tagid": "16",
+ "ext": ""
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "https://gat.tpmn.io/ortb/pbs_bidder",
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "tagid": "16",
+ "ext": "",
+ "bidfloorcur": "USD"
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+ }
+ }
+ },
+ "mockResponse": {
+ "status": 200,
+ "body": ""
+ }
+ }
+ ],
+ "expectedMakeBidsErrors": [
+ {
+ "value": "bid response unmarshal: json: cannot unmarshal string into Go value of type openrtb2.BidResponse",
+ "comparison": "literal"
+ }
+ ]
+}
+
\ No newline at end of file
diff --git a/adapters/tpmn/tpmntest/supplemental/status-204.json b/adapters/tpmn/tpmntest/supplemental/status-204.json
new file mode 100644
index 00000000000..fdcd3f7fd55
--- /dev/null
+++ b/adapters/tpmn/tpmntest/supplemental/status-204.json
@@ -0,0 +1,81 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "https://gat.tpmn.io/ortb/pbs_bidder",
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "bidfloorcur": "USD",
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+ }
+ }
+ },
+ "mockResponse": {
+ "status": 204,
+ "body": {}
+ }
+ }
+ ],
+ "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/tpmn/tpmntest/supplemental/status-404.json b/adapters/tpmn/tpmntest/supplemental/status-404.json
new file mode 100644
index 00000000000..74ced15217c
--- /dev/null
+++ b/adapters/tpmn/tpmntest/supplemental/status-404.json
@@ -0,0 +1,86 @@
+{
+ "mockBidRequest": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+ }
+ },
+ "httpCalls": [
+ {
+ "expectedRequest": {
+ "uri": "https://gat.tpmn.io/ortb/pbs_bidder",
+ "body": {
+ "id": "test-request-id",
+ "imp": [
+ {
+ "id": "test-imp-id",
+ "banner": {
+ "format": [
+ {
+ "w": 300,
+ "h": 250
+ },
+ {
+ "w": 300,
+ "h": 600
+ }
+ ]
+ },
+ "bidfloorcur": "USD",
+ "ext": {
+ "bidder": {
+ "inventoryId": 10000001
+ }
+ }
+ }
+ ],
+ "app": {
+ "id": "1",
+ "bundle": "com.wls.testwlsapplication"
+ },
+ "device": {
+ "ip": "123.123.123.123",
+ "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+ }
+ }
+ },
+ "mockResponse": {
+ "status": 404,
+ "body": {}
+ }
+ }
+ ],
+ "expectedMakeBidsErrors": [
+ {
+ "value": "Unexpected status code: 404. Run with request.debug = 1 for more info",
+ "comparison": "literal"
+ }
+ ]
+}
diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go
index a1038d7152d..11529c5e9c3 100755
--- a/exchange/adapter_builders.go
+++ b/exchange/adapter_builders.go
@@ -157,6 +157,7 @@ import (
"github.com/prebid/prebid-server/adapters/taboola"
"github.com/prebid/prebid-server/adapters/tappx"
"github.com/prebid/prebid-server/adapters/telaria"
+ "github.com/prebid/prebid-server/adapters/tpmn"
"github.com/prebid/prebid-server/adapters/trafficgate"
"github.com/prebid/prebid-server/adapters/triplelift"
"github.com/prebid/prebid-server/adapters/triplelift_native"
@@ -355,6 +356,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
openrtb_ext.BidderTaboola: taboola.Builder,
openrtb_ext.BidderTappx: tappx.Builder,
openrtb_ext.BidderTelaria: telaria.Builder,
+ openrtb_ext.BidderTpmn: tpmn.Builder,
openrtb_ext.BidderTrafficGate: trafficgate.Builder,
openrtb_ext.BidderTriplelift: triplelift.Builder,
openrtb_ext.BidderTripleliftNative: triplelift_native.Builder,
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index e9cc81f8c38..c873e9ab567 100644
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -254,6 +254,7 @@ const (
BidderTaboola BidderName = "taboola"
BidderTappx BidderName = "tappx"
BidderTelaria BidderName = "telaria"
+ BidderTpmn BidderName = "tpmn"
BidderTrafficGate BidderName = "trafficgate"
BidderTriplelift BidderName = "triplelift"
BidderTripleliftNative BidderName = "triplelift_native"
@@ -454,6 +455,7 @@ func CoreBidderNames() []BidderName {
BidderTaboola,
BidderTappx,
BidderTelaria,
+ BidderTpmn,
BidderTrafficGate,
BidderTriplelift,
BidderTripleliftNative,
diff --git a/openrtb_ext/imp_tpmn.go b/openrtb_ext/imp_tpmn.go
new file mode 100644
index 00000000000..373b3089cc8
--- /dev/null
+++ b/openrtb_ext/imp_tpmn.go
@@ -0,0 +1,6 @@
+package openrtb_ext
+
+// ExtImpTpmn defines TPMN specifiec param
+type ExtImpTpmn struct {
+ InventoryId int `json:"inventoryId"`
+}
diff --git a/static/bidder-info/tpmn.yaml b/static/bidder-info/tpmn.yaml
new file mode 100644
index 00000000000..8d88c451da6
--- /dev/null
+++ b/static/bidder-info/tpmn.yaml
@@ -0,0 +1,20 @@
+endpoint: "https://gat.tpmn.io/ortb/pbs_bidder"
+maintainer:
+ email: "prebid@tpmn.io"
+modifyingVastXmlAllowed: true
+endpointCompression: GZIP
+capabilities:
+ app:
+ mediaTypes:
+ - banner
+ - video
+ - native
+ site:
+ mediaTypes:
+ - banner
+ - video
+ - native
+userSync:
+ redirect:
+ url: "https://gat.tpmn.io/sync/redirect?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir={{.RedirectURL}}"
+ userMacro: "$UID"
\ No newline at end of file
diff --git a/static/bidder-params/tpmn.json b/static/bidder-params/tpmn.json
new file mode 100644
index 00000000000..68b54373179
--- /dev/null
+++ b/static/bidder-params/tpmn.json
@@ -0,0 +1,16 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "title": "TPMN Adapter Params",
+ "description": "A schema which validates params accepted by the TPMN adapter",
+ "type": "object",
+ "properties": {
+ "inventoryId": {
+ "description": "Inventory ID",
+ "type": "integer",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "inventoryId"
+ ]
+}
\ No newline at end of file