Repository: prebid/prebid-server
Pull request #2549 (2023-01-27 16:16:07)

PBS core: add hb_deal targeting to video endpoint response 
Greetings, we recently found out that the /video endpoint of PBS doesn't add `hb_deal` targeting to the response. This is a small change to add `hb_deal` to targeting response as well if it exists in bid response from bidders. I also understand that the /video endpoint is going to be deprecated sometime soon. We would like to make this change though since we're planning to use the /video endpoint in the meantime for some testing purposes.

with `dealID` in bidder response:
<img width="909" alt="Screen Shot 2023-01-26 at 1 33 41 PM" src="https://user-images.githubusercontent.com/56240400/215136195-bd470342-0a50-48bd-9f4e-0be924609963.png">

without `dealID` in bidder response:
<img width="952" alt="Screenshot 2023-01-27 at 11 08 34 AM" src="https://user-images.githubusercontent.com/56240400/215136200-e07b80f1-bb2b-40ad-b821-22fcb01ef90b.png">


shahinrahbariasl: @SyntaxNode @bretg hoping to get your thoughts on this, it's a small change and I don't think affects anything else, just that we can receive the `hb_deal` KV in video response and use it in ad server call if needed.
bretg: Sounds fine to me. Thanks for jumping in with a PR.

Patch:
diff --git a/.github/workflows/issue_prioritization.yml b/.github/workflows/issue_prioritization.yml
index 9a178577..3843507b 100644
--- a/.github/workflows/issue_prioritization.yml
+++ b/.github/workflows/issue_prioritization.yml
@@ -25,21 +25,30 @@ jobs:
           gh api graphql -f query='
             query($org: String!, $number: Int!) {
               organization(login: $org){
-                projectNext(number: $number) {
+                projectV2(number: $number) {
                   id
                   fields(first:100) {
                     nodes {
-                      id
-                      name
-                      settings
+                      ... on ProjectV2Field {
+                        id
+                        name
+                      }
+                      ... on ProjectV2SingleSelectField {
+                        id
+                        name
+                        options {
+                          id
+                          name
+                        }
+                      }
                     }
                   }
                 }
               }
             }' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json
 
-          echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV
-          echo 'DATE_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "'"$DATE_FIELD"'") | .id' project_data.json) >> $GITHUB_ENV
+          echo 'PROJECT_ID='$(jq '.data.organization.projectV2.id' project_data.json) >> $GITHUB_ENV
+          echo 'DATE_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name=="'"$DATE_FIELD"'") | .id' project_data.json) >> $GITHUB_ENV
 
       - name: Add issue to project
         env:
@@ -48,9 +57,9 @@ jobs:
         run: |
           gh api graphql -f query='
             mutation($project:ID!, $issue:ID!) {
-              addProjectNextItem(input: {projectId: $project, contentId: $issue}) {
-                projectNextItem {
-                  id,
+              addProjectV2ItemById(input: {projectId: $project, contentId: $issue}) {
+                item {
+                  id
                   content {
                      ... on Issue {
                         createdAt
@@ -63,8 +72,8 @@ jobs:
               }
             }' -f project=$PROJECT_ID -f issue=$ISSUE_ID > issue_data.json
           
-          echo 'ITEM_ID='$(jq '.data.addProjectNextItem.projectNextItem.id' issue_data.json) >> $GITHUB_ENV
-          echo 'ITEM_CREATION_DATE='$(jq '.data.addProjectNextItem.projectNextItem.content.createdAt' issue_data.json) >> $GITHUB_ENV
+          echo 'ITEM_ID='$(jq '.data.addProjectV2ItemById.item.id' issue_data.json) >> $GITHUB_ENV
+          echo 'ITEM_CREATION_DATE='$(jq '.data.addProjectV2ItemById.item.content.createdAt' issue_data.json | cut -c 2-11) >> $GITHUB_ENV
 
       - name: Set fields
         env:
@@ -75,15 +84,17 @@ jobs:
               $project: ID!
               $item: ID!
               $date_field: ID!
-              $date_value: String!
+              $date_value: Date!
             ) {
-              set_creation_date: updateProjectNextItemField(input: {
+              set_creation_date: updateProjectV2ItemFieldValue(input: {
                 projectId: $project
                 itemId: $item
                 fieldId: $date_field
-                value: $date_value
+                value: {
+                  date: $date_value
+                }
               }) {
-                projectNextItem {
+                projectV2Item {
                   id
                 }
               }
diff --git a/adapters/adnuntius/adnuntius.go b/adapters/adnuntius/adnuntius.go
index 3b01dab5..084ffc22 100644
--- a/adapters/adnuntius/adnuntius.go
+++ b/adapters/adnuntius/adnuntius.go
@@ -76,8 +76,9 @@ const minutesInHour = 60
 // Builder builds a new instance of the Adnuntius adapter for the given bidder with the given config.
 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
 	bidder := &adapter{
-		time:     &timeutil.RealTime{},
-		endpoint: config.Endpoint,
+		time:      &timeutil.RealTime{},
+		endpoint:  config.Endpoint,
+		extraInfo: config.ExtraAdapterInfo,
 	}
 
 	return bidder, nil
diff --git a/adapters/adsinteractive/adsinteractive.go b/adapters/adsinteractive/adsinteractive.go
new file mode 100644
index 00000000..503c61d2
--- /dev/null
+++ b/adapters/adsinteractive/adsinteractive.go
@@ -0,0 +1,78 @@
+package adsinteractive
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"github.com/prebid/openrtb/v17/openrtb2"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+type adapter struct {
+	endpoint string
+}
+
+// Builder builds a new instance of the Adsinteractive adapter for the given bidder with the given config.
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
+	bidder := &adapter{
+		endpoint: config.Endpoint,
+	}
+	return bidder, nil
+}
+
+func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	requestJSON, err := json.Marshal(request)
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	requestData := &adapters.RequestData{
+		Method: "POST",
+		Uri:    a.endpoint,
+		Body:   requestJSON,
+	}
+
+	return []*adapters.RequestData{requestData}, nil
+}
+
+func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	if responseData.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	if responseData.StatusCode == http.StatusBadRequest {
+		err := &errortypes.BadInput{
+			Message: "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.",
+		}
+		return nil, []error{err}
+	}
+
+	if responseData.StatusCode != http.StatusOK {
+		err := &errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode),
+		}
+		return nil, []error{err}
+	}
+
+	var response openrtb2.BidResponse
+	if err := json.Unmarshal(responseData.Body, &response); err != nil {
+		return nil, []error{err}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
+	bidResponse.Currency = response.Cur
+	for _, seatBid := range response.SeatBid {
+		for i := range seatBid.Bid {
+			b := &adapters.TypedBid{
+				Bid:     &seatBid.Bid[i],
+				BidType: "banner",
+			}
+			bidResponse.Bids = append(bidResponse.Bids, b)
+		}
+	}
+	return bidResponse, nil
+}
diff --git a/adapters/brave/brave.go b/adapters/brave/brave.go
new file mode 100755
index 00000000..627b6547
--- /dev/null
+++ b/adapters/brave/brave.go
@@ -0,0 +1,157 @@
+package brave
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"text/template"
+
+	"github.com/prebid/openrtb/v17/openrtb2"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/macros"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+type adapter struct {
+	endpoint *template.Template
+}
+
+// Builder builds a new instance of the Brave adapter for the given bidder with the given config.
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
+	uri, err := template.New("endpointTemplate").Parse(config.Endpoint)
+	if err != nil {
+		return nil, fmt.Errorf("unable to parse endpoint url template: %v", err)
+	}
+
+	bidder := &adapter{
+		endpoint: uri,
+	}
+	return bidder, nil
+}
+
+func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	var braveExt *openrtb_ext.ExtImpBrave
+	var err error
+
+	braveExt, err = a.getImpressionExt(&request.Imp[0])
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	request.Imp[0].Ext = nil
+
+	reqJSON, err := json.Marshal(request)
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+
+	url, err := a.buildEndpointURL(braveExt)
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	return []*adapters.RequestData{{
+		Method:  http.MethodPost,
+		Body:    reqJSON,
+		Uri:     url,
+		Headers: headers,
+	}}, nil
+}
+
+func (a *adapter) getImpressionExt(imp *openrtb2.Imp) (*openrtb_ext.ExtImpBrave, error) {
+	var bidderExt adapters.ExtImpBidder
+	if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
+		return nil, &errortypes.BadInput{
+			Message: "ext.bidder not provided",
+		}
+	}
+	var braveExt openrtb_ext.ExtImpBrave
+	if err := json.Unmarshal(bidderExt.Bidder, &braveExt); err != nil {
+		return nil, &errortypes.BadInput{
+			Message: "ext.bidder not provided",
+		}
+	}
+	return &braveExt, nil
+}
+
+func (a *adapter) buildEndpointURL(params *openrtb_ext.ExtImpBrave) (string, error) {
+	endpointParams := macros.EndpointTemplateParams{PublisherID: params.PlacementID}
+	return macros.ResolveMacros(a.endpoint, endpointParams)
+}
+
+func (a *adapter) MakeBids(
+	receivedRequest *openrtb2.BidRequest,
+	bidderRequest *adapters.RequestData,
+	bidderResponse *adapters.ResponseData,
+) (
+	*adapters.BidderResponse,
+	[]error,
+) {
+
+	if bidderResponse.StatusCode == http.StatusNoContent {
+		return nil, []error{&errortypes.BadInput{Message: "No bid"}}
+	}
+
+	if bidderResponse.StatusCode == http.StatusBadRequest {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", bidderResponse.StatusCode),
+		}}
+	}
+
+	if bidderResponse.StatusCode == http.StatusServiceUnavailable {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Service Unavailable. Status Code: [ %d ] ", bidderResponse.StatusCode),
+		}}
+	}
+
+	if bidderResponse.StatusCode != http.StatusOK {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Something went wrong, please contact your Account Manager. Status Code: [ %d ] ", bidderResponse.StatusCode),
+		}}
+	}
+
+	var bidResponse openrtb2.BidResponse
+	if err := json.Unmarshal(bidderResponse.Body, &bidResponse); err != nil {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Bad Server Response",
+		}}
+	}
+
+	if len(bidResponse.SeatBid) == 0 {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Empty SeatBid array",
+		}}
+	}
+
+	bidResponseFinal := adapters.NewBidderResponseWithBidsCapacity(len(bidResponse.SeatBid[0].Bid))
+	sb := bidResponse.SeatBid[0]
+
+	for _, bid := range sb.Bid {
+		bidResponseFinal.Bids = append(bidResponseFinal.Bids, &adapters.TypedBid{
+			Bid:     &bid,
+			BidType: getMediaTypeForImp(bid.ImpID, receivedRequest.Imp),
+		})
+	}
+	return bidResponseFinal, nil
+}
+
+func getMediaTypeForImp(impId string, imps []openrtb2.Imp) openrtb_ext.BidType {
+	mediaType := openrtb_ext.BidTypeBanner
+	for _, imp := range imps {
+		if imp.ID == impId {
+			if imp.Video != nil {
+				mediaType = openrtb_ext.BidTypeVideo
+			} else if imp.Native != nil {
+				mediaType = openrtb_ext.BidTypeNative
+			}
+			return mediaType
+		}
+	}
+	return mediaType
+}
diff --git a/adapters/kiviads/kiviads.go b/adapters/kiviads/kiviads.go
new file mode 100644
index 00000000..c947c2bf
--- /dev/null
+++ b/adapters/kiviads/kiviads.go
@@ -0,0 +1,154 @@
+package kiviads
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"github.com/prebid/openrtb/v17/openrtb2"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+type adapter struct {
+	endpoint string
+}
+
+type reqBodyExt struct {
+	KiviadsBidderExt reqBodyExtBidder `json:"bidder"`
+}
+
+type reqBodyExtBidder struct {
+	Type        string `json:"type"`
+	PlacementID string `json:"placementId,omitempty"`
+	EndpointID  string `json:"endpointId,omitempty"`
+}
+
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
+	bidder := &adapter{
+		endpoint: config.Endpoint,
+	}
+	return bidder, nil
+}
+
+func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	var err error
+	var adapterRequests []*adapters.RequestData
+
+	reqCopy := *request
+	for _, imp := range request.Imp {
+		reqCopy.Imp = []openrtb2.Imp{imp}
+
+		var bidderExt adapters.ExtImpBidder
+		var kiviadsExt openrtb_ext.ImpExtKiviads
+
+		if err = json.Unmarshal(reqCopy.Imp[0].Ext, &bidderExt); err != nil {
+			return nil, []error{err}
+		}
+		if err = json.Unmarshal(bidderExt.Bidder, &kiviadsExt); err != nil {
+			return nil, []error{err}
+		}
+
+		temp := reqBodyExt{KiviadsBidderExt: reqBodyExtBidder{}}
+
+		if kiviadsExt.PlacementID != "" {
+			temp.KiviadsBidderExt.PlacementID = kiviadsExt.PlacementID
+			temp.KiviadsBidderExt.Type = "publisher"
+		} else if kiviadsExt.EndpointID != "" {
+			temp.KiviadsBidderExt.EndpointID = kiviadsExt.EndpointID
+			temp.KiviadsBidderExt.Type = "network"
+		}
+
+		finalyImpExt, err := json.Marshal(temp)
+		if err != nil {
+			return nil, []error{err}
+		}
+
+		reqCopy.Imp[0].Ext = finalyImpExt
+
+		adapterReq, err := a.makeRequest(&reqCopy)
+		if err != nil {
+			return nil, []error{err}
+		}
+
+		if adapterReq != nil {
+			adapterRequests = append(adapterRequests, adapterReq)
+		}
+	}
+	return adapterRequests, nil
+}
+
+func (a *adapter) makeRequest(request *openrtb2.BidRequest) (*adapters.RequestData, error) {
+	reqJSON, err := json.Marshal(request)
+	if err != nil {
+		return nil, err
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	return &adapters.RequestData{
+		Method:  "POST",
+		Uri:     a.endpoint,
+		Body:    reqJSON,
+		Headers: headers,
+	}, err
+}
+
+func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	if responseData.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	if responseData.StatusCode != http.StatusOK {
+		err := &errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode),
+		}
+		return nil, []error{err}
+	}
+
+	var response openrtb2.BidResponse
+	if err := json.Unmarshal(responseData.Body, &response); err != nil {
+		return nil, []error{err}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
+	bidResponse.Currency = response.Cur
+	for _, seatBid := range response.SeatBid {
+		for i := range seatBid.Bid {
+			bidType, err := getMediaTypeForImp(seatBid.Bid[i].ImpID, request.Imp)
+			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(impID string, imps []openrtb2.Imp) (openrtb_ext.BidType, error) {
+	for _, imp := range imps {
+		if imp.ID == impID {
+			if imp.Banner != nil {
+				return openrtb_ext.BidTypeBanner, nil
+			}
+			if imp.Video != nil {
+				return openrtb_ext.BidTypeVideo, nil
+			}
+			if imp.Native != nil {
+				return openrtb_ext.BidTypeNative, nil
+			}
+		}
+	}
+
+	return "", &errortypes.BadInput{
+		Message: fmt.Sprintf("Failed to find impression \"%s\"", impID),
+	}
+}
diff --git a/adapters/openx/openx.go b/adapters/openx/openx.go
index 2240bd76..269d1c77 100644
--- a/adapters/openx/openx.go
+++ b/adapters/openx/openx.go
@@ -15,11 +15,13 @@ import (
 const hbconfig = "hb_pbs_1.0.0"
 
 type OpenxAdapter struct {
-	endpoint string
+	bidderName string
+	endpoint   string
 }
 
 type openxImpExt struct {
-	CustomParams map[string]interface{} `json:"customParams,omitempty"`
+	CustomParams       map[string]interface{}             `json:"customParams,omitempty"`
+	AuctionEnvironment openrtb_ext.AuctionEnvironmentType `json:"ae,omitempty"`
 }
 
 type openxReqExt struct {
@@ -28,6 +30,10 @@ type openxReqExt struct {
 	BidderConfig string `json:"bc"`
 }
 
+type openxRespExt struct {
+	FledgeAuctionConfigs map[string]json.RawMessage `json:"fledge_auction_configs,omitempty"`
+}
+
 func (a *OpenxAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
 	var errs []error
 	var bannerImps []openrtb2.Imp
@@ -133,18 +139,27 @@ func preprocess(imp *openrtb2.Imp, reqExt *openxReqExt) error {
 	if imp.BidFloor == 0 && openxExt.CustomFloor > 0 {
 		imp.BidFloor = openxExt.CustomFloor
 	}
-	imp.Ext = nil
+
+	impExt := openxImpExt{}
+	addImpExt := false
 
 	if openxExt.CustomParams != nil {
-		impExt := openxImpExt{
-			CustomParams: openxExt.CustomParams,
-		}
+		impExt.CustomParams = openxExt.CustomParams
+		addImpExt = true
+	}
+	if bidderExt.AuctionEnvironment != openrtb_ext.ServerSideAuction {
+		impExt.AuctionEnvironment = bidderExt.AuctionEnvironment
+		addImpExt = true
+	}
+	if addImpExt {
 		var err error
 		if imp.Ext, err = json.Marshal(impExt); err != nil {
 			return &errortypes.BadInput{
 				Message: err.Error(),
 			}
 		}
+	} else {
+		imp.Ext = nil
 	}
 
 	if imp.Video != nil {
@@ -189,6 +204,21 @@ func (a *OpenxAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRe
 		bidResponse.Currency = bidResp.Cur
 	}
 
+	if bidResp.Ext != nil {
+		var bidRespExt openxRespExt
+		if err := json.Unmarshal(bidResp.Ext, &bidRespExt); err == nil && bidRespExt.FledgeAuctionConfigs != nil {
+			bidResponse.FledgeAuctionConfigs = make([]*openrtb_ext.FledgeAuctionConfig, 0, len(bidRespExt.FledgeAuctionConfigs))
+			for impId, config := range bidRespExt.FledgeAuctionConfigs {
+				fledgeAuctionConfig := &openrtb_ext.FledgeAuctionConfig{
+					ImpId:  impId,
+					Bidder: a.bidderName,
+					Config: config,
+				}
+				bidResponse.FledgeAuctionConfigs = append(bidResponse.FledgeAuctionConfigs, fledgeAuctionConfig)
+			}
+		}
+	}
+
 	for _, sb := range bidResp.SeatBid {
 		for i := range sb.Bid {
 			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
@@ -220,7 +250,8 @@ func getMediaTypeForImp(impId string, imps []openrtb2.Imp) openrtb_ext.BidType {
 // Builder builds a new instance of the Openx adapter for the given bidder with the given config.
 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
 	bidder := &OpenxAdapter{
-		endpoint: config.Endpoint,
+		endpoint:   config.Endpoint,
+		bidderName: string(bidderName),
 	}
 	return bidder, nil
 }
diff --git a/adapters/rubicon/rubicon.go b/adapters/rubicon/rubicon.go
index 37c47d88..faa43e93 100644
--- a/adapters/rubicon/rubicon.go
+++ b/adapters/rubicon/rubicon.go
@@ -161,7 +161,7 @@ type rubiconSeatBid struct {
 
 type rubiconBid struct {
 	openrtb2.Bid
-	AdmObject json.RawMessage `json:"admobject,omitempty"`
+	AdmNative json.RawMessage `json:"adm_native,omitempty"`
 }
 
 type extPrebid struct {
@@ -1113,7 +1113,7 @@ func resolveAdm(bid rubiconBid) string {
 		return bidAdm
 	}
 
-	admObject := bid.AdmObject
+	admObject := bid.AdmNative
 	admObjectAsBytes, err := json.Marshal(&admObject)
 	if err != nil {
 		return ""
diff --git a/endpoints/openrtb2/amp_auction.go b/endpoints/openrtb2/amp_auction.go
index 5b85eb67..6e38f8f8 100644
--- a/endpoints/openrtb2/amp_auction.go
+++ b/endpoints/openrtb2/amp_auction.go
@@ -325,6 +325,22 @@ func sendAmpResponse(
 		}
 	}
 
+	// Extract global targeting
+	var extResponse openrtb_ext.ExtBidResponse
+	eRErr := json.Unmarshal(response.Ext, &extResponse)
+	if eRErr != nil {
+		ao.Errors = append(ao.Errors, fmt.Errorf("AMP response: failed to unpack OpenRTB response.ext, debug info cannot be forwarded: %v", eRErr))
+	}
+	// Extract global targeting
+	extPrebid := extResponse.Prebid
+	if extPrebid != nil {
+		for key, value := range extPrebid.Targeting {
+			_, exists := targets[key]
+			if !exists {
+				targets[key] = value
+			}
+		}
+	}
 	// Now JSONify the targets for the AMP response.
 	ampResponse := AmpResponse{Targeting: targets}
 	ao, ampResponse.ORTB2.Ext = getExtBidResponse(hookExecutor, response, reqWrapper, account, ao, errs)
diff --git a/endpoints/openrtb2/video_auction.go b/endpoints/openrtb2/video_auction.go
index ea1cd46b..eddc5173 100644
--- a/endpoints/openrtb2/video_auction.go
+++ b/endpoints/openrtb2/video_auction.go
@@ -516,6 +516,7 @@ func buildVideoResponse(bidresponse *openrtb2.BidResponse, podErrors []PodError)
 				HbPb:       tempRespBidExt.Prebid.Targeting[formatTargetingKey(openrtb_ext.HbpbConstantKey, seatBid.Seat)],
 				HbPbCatDur: tempRespBidExt.Prebid.Targeting[formatTargetingKey(openrtb_ext.HbCategoryDurationKey, seatBid.Seat)],
 				HbCacheID:  tempRespBidExt.Prebid.Targeting[formatTargetingKey(openrtb_ext.HbVastCacheKey, seatBid.Seat)],
+				HbDeal:     tempRespBidExt.Prebid.Targeting[formatTargetingKey(openrtb_ext.HbDealIDConstantKey, seatBid.Seat)],
 			}
 
 			adPod := findAdPod(podId, adPods)
diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go
index f808a404..bdd00819 100755
--- a/exchange/adapter_builders.go
+++ b/exchange/adapter_builders.go
@@ -20,6 +20,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/adpone"
 	"github.com/prebid/prebid-server/adapters/adprime"
 	"github.com/prebid/prebid-server/adapters/adrino"
+	"github.com/prebid/prebid-server/adapters/adsinteractive"
 	"github.com/prebid/prebid-server/adapters/adtarget"
 	"github.com/prebid/prebid-server/adapters/adtelligent"
 	"github.com/prebid/prebid-server/adapters/adtrgtme"
@@ -51,6 +52,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/blue"
 	"github.com/prebid/prebid-server/adapters/bmtm"
 	"github.com/prebid/prebid-server/adapters/boldwin"
+	"github.com/prebid/prebid-server/adapters/brave"
 	"github.com/prebid/prebid-server/adapters/brightroll"
 	"github.com/prebid/prebid-server/adapters/ccx"
 	"github.com/prebid/prebid-server/adapters/coinzilla"
@@ -92,6 +94,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/kargo"
 	"github.com/prebid/prebid-server/adapters/kayzen"
 	"github.com/prebid/prebid-server/adapters/kidoz"
+	"github.com/prebid/prebid-server/adapters/kiviads"
 	"github.com/prebid/prebid-server/adapters/krushmedia"
 	"github.com/prebid/prebid-server/adapters/kubient"
 	"github.com/prebid/prebid-server/adapters/lockerdome"
@@ -184,6 +187,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderAdpone:            adpone.Builder,
 		openrtb_ext.BidderAdprime:           adprime.Builder,
 		openrtb_ext.BidderAdrino:            adrino.Builder,
+		openrtb_ext.BidderAdsinteractive:    adsinteractive.Builder,
 		openrtb_ext.BidderAdtarget:          adtarget.Builder,
 		openrtb_ext.BidderAdtrgtme:          adtrgtme.Builder,
 		openrtb_ext.BidderAdtelligent:       adtelligent.Builder,
@@ -215,6 +219,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderBlue:              blue.Builder,
 		openrtb_ext.BidderBmtm:              bmtm.Builder,
 		openrtb_ext.BidderBoldwin:           boldwin.Builder,
+		openrtb_ext.BidderBrave:             brave.Builder,
 		openrtb_ext.BidderBrightroll:        brightroll.Builder,
 		openrtb_ext.BidderCcx:               ccx.Builder,
 		openrtb_ext.BidderCoinzilla:         coinzilla.Builder,
@@ -259,6 +264,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderKargo:             kargo.Builder,
 		openrtb_ext.BidderKayzen:            kayzen.Builder,
 		openrtb_ext.BidderKidoz:             kidoz.Builder,
+		openrtb_ext.BidderKiviads:           kiviads.Builder,
 		openrtb_ext.BidderKrushmedia:        krushmedia.Builder,
 		openrtb_ext.BidderKubient:           kubient.Builder,
 		openrtb_ext.BidderLockerDome:        lockerdome.Builder,
diff --git a/exchange/price_granularity.go b/exchange/price_granularity.go
index 242d420f..af3300b2 100644
--- a/exchange/price_granularity.go
+++ b/exchange/price_granularity.go
@@ -13,7 +13,7 @@ func GetPriceBucket(cpm float64, config openrtb_ext.PriceGranularity) string {
 	bucketMax := 0.0
 	increment := 0.0
 	precision := config.Precision
-
+	bucketMin := 0.0
 	for i := 0; i < len(config.Ranges); i++ {
 		if config.Ranges[i].Max > bucketMax {
 			bucketMax = config.Ranges[i].Max
@@ -21,6 +21,7 @@ func GetPriceBucket(cpm float64, config openrtb_ext.PriceGranularity) string {
 		// find what range cpm is in
 		if cpm >= config.Ranges[i].Min && cpm <= config.Ranges[i].Max {
 			increment = config.Ranges[i].Increment
+			bucketMin = config.Ranges[i].Min
 		}
 	}
 
@@ -29,13 +30,13 @@ func GetPriceBucket(cpm float64, config openrtb_ext.PriceGranularity) string {
 		cpmStr = strconv.FormatFloat(bucketMax, 'f', precision, 64)
 	} else if increment > 0 {
 		// If increment exists, get cpm string value
-		cpmStr = getCpmTarget(cpm, increment, precision)
+		cpmStr = getCpmTarget(cpm, bucketMin, increment, precision)
 	}
 
 	return cpmStr
 }
 
-func getCpmTarget(cpm float64, increment float64, precision int) string {
-	roundedCPM := math.Floor(cpm/increment) * increment
+func getCpmTarget(cpm float64, bucketMin float64, increment float64, precision int) string {
+	roundedCPM := math.Floor((cpm-bucketMin)/increment)*increment + bucketMin
 	return strconv.FormatFloat(roundedCPM, 'f', precision, 64)
 }
diff --git a/go.mod b/go.mod
index 90f87507..f3e3cdab 100644
--- a/go.mod
+++ b/go.mod
@@ -30,8 +30,8 @@ require (
 	github.com/vrischmann/go-metrics-influxdb v0.1.1
 	github.com/xeipuuv/gojsonschema v1.2.0
 	github.com/yudai/gojsondiff v1.0.0
-	golang.org/x/net v0.0.0-20220909164309-bea034e7d591
-	golang.org/x/text v0.3.7
+	golang.org/x/net v0.5.0
+	golang.org/x/text v0.6.0
 	google.golang.org/grpc v1.46.2
 	gopkg.in/evanphx/json-patch.v4 v4.12.0
 	gopkg.in/yaml.v3 v3.0.1
@@ -67,7 +67,7 @@ require (
 	github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
 	github.com/yudai/pp v2.0.1+incompatible // indirect
 	golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
-	golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
+	golang.org/x/sys v0.4.0 // indirect
 	google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect
 	google.golang.org/protobuf v1.28.0 // indirect
 	gopkg.in/ini.v1 v1.66.4 // indirect
diff --git a/go.sum b/go.sum
index 30f3017b..2e795639 100644
--- a/go.sum
+++ b/go.sum
@@ -29,18 +29,12 @@ cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW
 cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
 cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM=
 cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
-cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
 cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
 cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
 cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
 cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
 cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
 cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
-cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
-cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
-cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
-cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
 cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
 cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
@@ -90,7 +84,6 @@ github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMU
 github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
@@ -118,13 +111,11 @@ github.com/coocood/freecache v1.2.1/go.mod h1:RBUWa/Cy+OHdfTGFEhEuE1pMCMX51Ncizj
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
 github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
 github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
-github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -142,7 +133,6 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL
 github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
 github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
 github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
-github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
@@ -221,7 +211,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
 github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
-github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -249,14 +238,9 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
 github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
-github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
-github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
-github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
 github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
-github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
-github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
 github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
@@ -266,7 +250,6 @@ github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9
 github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
 github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
 github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
-github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
 github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
 github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
 github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
@@ -295,7 +278,6 @@ github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOn
 github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
 github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
 github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
-github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
 github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q=
 github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
 github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
@@ -329,11 +311,9 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
 github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
@@ -423,7 +403,6 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
 github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
 github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
-github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
 github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
 github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -450,7 +429,6 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqn
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
 github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
 github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -458,7 +436,6 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
 github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
 github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
-github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
 github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
@@ -520,12 +497,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
-go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
 go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
-go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
 go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
-go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU=
-go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -637,13 +610,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
 golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI=
-golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
+golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
+golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -661,9 +629,6 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ
 golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -675,7 +640,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -755,18 +719,11 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
-golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
+golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -778,8 +735,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
+golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -843,8 +801,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
 google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -878,14 +834,6 @@ google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdr
 google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
 google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
 google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
-google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
-google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
-google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
-google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
-google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
-google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
-google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
-google.golang.org/api v0.81.0/go.mod h1:FA6Mb/bZxj706H2j+j2d6mHEEaHBmbbWnkfvmorOCko=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -959,20 +907,7 @@ google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ6
 google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
-google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
 google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd h1:e0TwkXOdbnH/1x5rc5MZ/VYyiZ4v+RdVfrGMqEwT68I=
 google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
 google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
@@ -1005,7 +940,6 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K
 google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
 google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
 google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
-google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
 google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ=
 google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
@@ -1052,7 +986,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -1065,4 +998,3 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/openrtb_ext/bid_response_video.go b/openrtb_ext/bid_response_video.go
index 22661547..3d677772 100644
--- a/openrtb_ext/bid_response_video.go
+++ b/openrtb_ext/bid_response_video.go
@@ -17,4 +17,5 @@ type VideoTargeting struct {
 	HbPb       string `json:"hb_pb,omitempty"`
 	HbPbCatDur string `json:"hb_pb_cat_dur,omitempty"`
 	HbCacheID  string `json:"hb_cache_id,omitempty"`
+	HbDeal     string `json:"hb_deal,omitempty"`
 }
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 8f0fce6e..675beafc 100644
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -105,6 +105,7 @@ const (
 	BidderAdpone            BidderName = "adpone"
 	BidderAdprime           BidderName = "adprime"
 	BidderAdrino            BidderName = "adrino"
+	BidderAdsinteractive    BidderName = "adsinteractive"
 	BidderAdtarget          BidderName = "adtarget"
 	BidderAdtrgtme          BidderName = "adtrgtme"
 	BidderAdtelligent       BidderName = "adtelligent"
@@ -136,6 +137,7 @@ const (
 	BidderBlue              BidderName = "blue"
 	BidderBmtm              BidderName = "bmtm"
 	BidderBoldwin           BidderName = "boldwin"
+	BidderBrave             BidderName = "brave"
 	BidderBrightroll        BidderName = "brightroll"
 	BidderCcx               BidderName = "ccx"
 	BidderCoinzilla         BidderName = "coinzilla"
@@ -180,6 +182,7 @@ const (
 	BidderKargo             BidderName = "kargo"
 	BidderKayzen            BidderName = "kayzen"
 	BidderKidoz             BidderName = "kidoz"
+	BidderKiviads           BidderName = "kiviads"
 	BidderKrushmedia        BidderName = "krushmedia"
 	BidderKubient           BidderName = "kubient"
 	BidderLockerDome        BidderName = "lockerdome"
@@ -279,6 +282,7 @@ func CoreBidderNames() []BidderName {
 		BidderAdpone,
 		BidderAdprime,
 		BidderAdrino,
+		BidderAdsinteractive,
 		BidderAdtarget,
 		BidderAdtrgtme,
 		BidderAdtelligent,
@@ -310,6 +314,7 @@ func CoreBidderNames() []BidderName {
 		BidderBlue,
 		BidderBmtm,
 		BidderBoldwin,
+		BidderBrave,
 		BidderBrightroll,
 		BidderCcx,
 		BidderCoinzilla,
@@ -354,6 +359,7 @@ func CoreBidderNames() []BidderName {
 		BidderKargo,
 		BidderKayzen,
 		BidderKidoz,
+		BidderKiviads,
 		BidderKrushmedia,
 		BidderKubient,
 		BidderLockerDome,
diff --git a/openrtb_ext/imp_adsinteractive.go b/openrtb_ext/imp_adsinteractive.go
new file mode 100644
index 00000000..c382b2d6
--- /dev/null
+++ b/openrtb_ext/imp_adsinteractive.go
@@ -0,0 +1,5 @@
+package openrtb_ext
+
+type ImpExtAdsinteractive struct {
+	AdUnit string `json:"adUnit"`
+}
diff --git a/openrtb_ext/imp_brave.go b/openrtb_ext/imp_brave.go
new file mode 100644
index 00000000..2c7a0eaf
--- /dev/null
+++ b/openrtb_ext/imp_brave.go
@@ -0,0 +1,5 @@
+package openrtb_ext
+
+type ExtImpBrave struct {
+	PlacementID string `json:"placementId"`
+}
diff --git a/openrtb_ext/imp_kiviads.go b/openrtb_ext/imp_kiviads.go
new file mode 100644
index 00000000..b5e02a67
--- /dev/null
+++ b/openrtb_ext/imp_kiviads.go
@@ -0,0 +1,6 @@
+package openrtb_ext
+
+type ImpExtKiviads struct {
+	PlacementID string `json:"placementId"`
+	EndpointID  string `json:"endpointId"`
+}
diff --git a/openrtb_ext/response.go b/openrtb_ext/response.go
index e920ee58..9c76744f 100644
--- a/openrtb_ext/response.go
+++ b/openrtb_ext/response.go
@@ -39,10 +39,11 @@ type ExtResponseSyncData struct {
 
 // ExtResponsePrebid defines the contract for bidresponse.ext.prebid
 type ExtResponsePrebid struct {
-	AuctionTimestamp int64           `json:"auctiontimestamp,omitempty"`
-	Passthrough      json.RawMessage `json:"passthrough,omitempty"`
-	Modules          json.RawMessage `json:"modules,omitempty"`
-	Fledge           *Fledge         `json:"fledge,omitempty"`
+	AuctionTimestamp int64             `json:"auctiontimestamp,omitempty"`
+	Passthrough      json.RawMessage   `json:"passthrough,omitempty"`
+	Modules          json.RawMessage   `json:"modules,omitempty"`
+	Fledge           *Fledge           `json:"fledge,omitempty"`
+	Targeting        map[string]string `json:"targeting,omitempty"`
 }
 
 // FledgeResponse defines the contract for bidresponse.ext.fledge
diff --git a/static/bidder-info/adsinteractive.yaml b/static/bidder-info/adsinteractive.yaml
new file mode 100644
index 00000000..20a64bf2
--- /dev/null
+++ b/static/bidder-info/adsinteractive.yaml
@@ -0,0 +1,11 @@
+endpoint: "http://bid.adsinteractive.com/prebid"
+maintainer:
+  email: it@adsinteractive.com
+modifyingVastXmlAllowed: false
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+  site:
+    mediaTypes:
+      - banner
\ No newline at end of file
diff --git a/static/bidder-info/bliink.yaml b/static/bidder-info/bliink.yaml
index 8afacff1..bcdacc42 100644
--- a/static/bidder-info/bliink.yaml
+++ b/static/bidder-info/bliink.yaml
@@ -1,4 +1,4 @@
-endpoint: "http://engine.bliink.io/bid"
+endpoint: "https://engine.bliink.io/bid"
 maintainer:
   email: "support@bliink.io"
 gvlVendorID: 658
diff --git a/static/bidder-info/brave.yaml b/static/bidder-info/brave.yaml
new file mode 100644
index 00000000..1e4b7ced
--- /dev/null
+++ b/static/bidder-info/brave.yaml
@@ -0,0 +1,15 @@
+endpoint: "http://point.braveglobal.tv/?t=3&partner={{.PublisherID}}"
+maintainer:
+  email: "support@thebrave.io"
+gvlVendorID: 869
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+      - video
+      - native
+  site:
+    mediaTypes:
+      - banner
+      - video
+      - native
diff --git a/static/bidder-info/kiviads.yaml b/static/bidder-info/kiviads.yaml
new file mode 100644
index 00000000..6349060c
--- /dev/null
+++ b/static/bidder-info/kiviads.yaml
@@ -0,0 +1,18 @@
+endpoint: "http://lb.kiviads.com/pserver"
+maintainer:
+  email: "prebid@kiviads.com"
+capabilities:
+  site:
+    mediaTypes:
+    - banner
+    - video
+    - native
+  app:
+    mediaTypes:
+    - banner
+    - video
+    - native
+userSync:
+  redirect:
+    url: "https://sync.kiviads.com/pserver?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&ccpa={{.USPrivacy}}&redir={{.RedirectURL}}"
+    userMacro: "[UID]"
diff --git a/static/bidder-params/adsinteractive.json b/static/bidder-params/adsinteractive.json
new file mode 100644
index 00000000..662c7362
--- /dev/null
+++ b/static/bidder-params/adsinteractive.json
@@ -0,0 +1,13 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "Adsinteractive Adapter Params",
+  "description": "Adsinteractive Bidder Parameter Schema",
+  "type": "object",
+  "properties": {
+    "adUnit": {
+      "type": "string",
+      "description": "ad unit name"
+    }
+  },
+  "required": ["adUnit"]
+}
diff --git a/static/bidder-params/brave.json b/static/bidder-params/brave.json
new file mode 100644
index 00000000..8e913982
--- /dev/null
+++ b/static/bidder-params/brave.json
@@ -0,0 +1,13 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "Brave Adapter Params",
+  "description": "A schema which validates params accepted by the Brave adapter",
+  "type": "object",
+  "properties": {
+    "placementId": {
+      "type": "string",
+      "description": "Unique Placement ID of publisher"
+    }
+  },
+  "required": ["placementId"]
+}
\ No newline at end of file
diff --git a/static/bidder-params/kiviads.json b/static/bidder-params/kiviads.json
new file mode 100644
index 00000000..0ebe7eae
--- /dev/null
+++ b/static/bidder-params/kiviads.json
@@ -0,0 +1,22 @@
+{
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "title": "Kivi Adapter Params",
+    "description": "A schema which validates params accepted by the Kivi adapter",
+    "type": "object",
+    "properties": {
+      "placementId": {
+        "type": "string",
+        "minLength": 1,
+        "description": "Placement ID"
+      },
+      "endpointId": {
+        "type": "string",
+        "minLength": 1,
+        "description": "Endpoint ID"
+      }
+    },
+    "oneOf": [
+      { "required": ["placementId"] },
+      { "required": ["endpointId"] }
+    ]
+  }
\ No newline at end of file


Test patch:
diff --git a/adapters/adnuntius/adnuntius_test.go b/adapters/adnuntius/adnuntius_test.go
index 27e006e1..9c431c2a 100644
--- a/adapters/adnuntius/adnuntius_test.go
+++ b/adapters/adnuntius/adnuntius_test.go
@@ -13,7 +13,10 @@ import (
 
 func TestJsonSamples(t *testing.T) {
 	bidder, buildErr := Builder(openrtb_ext.BidderAdnuntius, config.Adapter{
-		Endpoint: "http://whatever.url"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
+		Endpoint:         "http://whatever.url",
+		ExtraAdapterInfo: "http://gdpr.url",
+	},
+		config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
 
 	if buildErr != nil {
 		t.Fatalf("Builder returned unexpected error %v", buildErr)
@@ -43,5 +46,4 @@ func AssignDefaultValues(bidder adapters.Bidder) {
 	bidderAdnuntius.time = &FakeTime{
 		time: time.Date(2016, 1, 1, 12, 30, 15, 0, time.UTC),
 	}
-	bidderAdnuntius.extraInfo = "http://gdpr.url"
 }
diff --git a/adapters/adsinteractive/adsinteractive_test.go b/adapters/adsinteractive/adsinteractive_test.go
new file mode 100644
index 00000000..9a1397b7
--- /dev/null
+++ b/adapters/adsinteractive/adsinteractive_test.go
@@ -0,0 +1,23 @@
+package adsinteractive
+
+import (
+	"testing"
+
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+const testsDir = "adsinteractivetest"
+const testsBidderEndpoint = "http://bid.adsinteractive.com/prebid"
+
+func TestJsonSamples(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderAdsinteractive, config.Adapter{
+		Endpoint: testsBidderEndpoint}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	adapterstest.RunJSONBidderTest(t, testsDir, bidder)
+}
diff --git a/adapters/adsinteractive/adsinteractivetest/exemplary/banner.json b/adapters/adsinteractive/adsinteractivetest/exemplary/banner.json
new file mode 100644
index 00000000..53b96fbe
--- /dev/null
+++ b/adapters/adsinteractive/adsinteractivetest/exemplary/banner.json
@@ -0,0 +1,89 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "site": {
+      "page": "https://good.site/url"
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "ext": {
+          "bidder": {
+            "adUnit": "fake-adunit-name"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://bid.adsinteractive.com/prebid",
+        "body": {
+          "id": "test-request-id",
+          "site": {
+            "page": "https://good.site/url"
+          },
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "ext": {
+                "bidder": {
+                  "adUnit": "fake-adunit-name"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "adsinteractive",
+              "bid": [
+                {
+                  "id": "randomid",
+                  "impid": "test-imp-id",
+                  "price": 0.72,
+                  "adid": "12345678",
+                  "adm": "some-test-ad",
+                  "cid": "987",
+                  "crid": "12345678",
+                  "h": 250,
+                  "w": 300
+                }
+              ]
+            }
+          ],
+          "cur": "EUR"
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "EUR",
+      "bids": [
+        {
+          "bid": {
+            "id": "randomid",
+            "impid": "test-imp-id",
+            "price": 0.72,
+            "adm": "some-test-ad",
+            "adid": "12345678",
+            "cid": "987",
+            "crid": "12345678",
+            "w": 300,
+            "h": 250
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/adsinteractive/adsinteractivetest/supplemental/bad-request-400.json b/adapters/adsinteractive/adsinteractivetest/supplemental/bad-request-400.json
new file mode 100644
index 00000000..695f2fb0
--- /dev/null
+++ b/adapters/adsinteractive/adsinteractivetest/supplemental/bad-request-400.json
@@ -0,0 +1,64 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "adUnit": "fake-adunit-name"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      
+      "expectedRequest": {
+        "uri": "http://bid.adsinteractive.com/prebid",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ]
+              },
+              "ext": {
+                "bidder": {
+                  "adUnit": "fake-adunit-name"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 400,
+        "body": {}
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adsinteractive/adsinteractivetest/supplemental/bad-response.json b/adapters/adsinteractive/adsinteractivetest/supplemental/bad-response.json
new file mode 100644
index 00000000..98acce17
--- /dev/null
+++ b/adapters/adsinteractive/adsinteractivetest/supplemental/bad-response.json
@@ -0,0 +1,63 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "adUnit": "fake-adunit-name"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://bid.adsinteractive.com/prebid",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ]
+              },
+              "ext": {
+                "bidder": {
+                  "adUnit": "fake-adunit-name"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": ""
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "json: cannot unmarshal string into Go value of type openrtb2.BidResponse",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adsinteractive/adsinteractivetest/supplemental/no-content-204.json b/adapters/adsinteractive/adsinteractivetest/supplemental/no-content-204.json
new file mode 100644
index 00000000..9b24dca0
--- /dev/null
+++ b/adapters/adsinteractive/adsinteractivetest/supplemental/no-content-204.json
@@ -0,0 +1,56 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "fake-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://bid.adsinteractive.com/prebid",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "fake-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ]
+              },
+              "ext": {
+                "bidder": {
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 204,
+        "body": {}
+      }
+    }
+  ],
+
+  "expectedBidResponses": []
+}
diff --git a/adapters/adsinteractive/adsinteractivetest/supplemental/service-unavailable-503.json b/adapters/adsinteractive/adsinteractivetest/supplemental/service-unavailable-503.json
new file mode 100644
index 00000000..42e259b8
--- /dev/null
+++ b/adapters/adsinteractive/adsinteractivetest/supplemental/service-unavailable-503.json
@@ -0,0 +1,63 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "adUnit": "fake-adunit-name"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://bid.adsinteractive.com/prebid",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ]
+              },
+              "ext": {
+                "bidder": {
+                  "adUnit": "fake-adunit-name"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 503,
+        "body": {}
+      }
+    }
+  ],
+
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 503. Run with request.debug = 1 for more info.",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/adsinteractive/params_test.go b/adapters/adsinteractive/params_test.go
new file mode 100644
index 00000000..2561fc86
--- /dev/null
+++ b/adapters/adsinteractive/params_test.go
@@ -0,0 +1,55 @@
+package adsinteractive
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+// This file actually intends to test static/bidder-params/adsinteractive.json
+
+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.BidderAdsinteractive, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected adsinteractive params: %s", validParam)
+		}
+	}
+}
+
+// TestInvalidParams makes sure that the Adsinteractive 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.BidderAdsinteractive, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"adUnit": "Example_ad_unit_1"}`,
+}
+
+var invalidParams = []string{
+	`{"adunit": "Example_ad_unit_1"}`,
+	`{"AdUnit": "Example_ad_unit_1"}`,
+	`{"ad_unit": Example_ad_unit_1}`,
+	``,
+	`null`,
+	`true`,
+	`[]`,
+	`{}`,
+	`nil`,
+	`53`,
+	`9.1`,
+}
diff --git a/adapters/brave/brave_test.go b/adapters/brave/brave_test.go
new file mode 100644
index 00000000..e8d0a474
--- /dev/null
+++ b/adapters/brave/brave_test.go
@@ -0,0 +1,30 @@
+package brave
+
+import (
+	"testing"
+
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/openrtb_ext"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestJsonSamples(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderBrave, config.Adapter{
+		Endpoint: "http://point.braveglobal.tv/?t=3&partner={{.PublisherID}}"},
+		config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	adapterstest.RunJSONBidderTest(t, "bravetest", bidder)
+}
+
+func TestEndpointTemplateMalformed(t *testing.T) {
+	_, buildErr := Builder(openrtb_ext.BidderBrave, config.Adapter{
+		Endpoint: "{{Malformed}}"},
+		config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
+
+	assert.Error(t, buildErr)
+}
diff --git a/adapters/brave/bravetest/exemplary/banner-app.json b/adapters/brave/bravetest/exemplary/banner-app.json
new file mode 100644
index 00000000..71a30978
--- /dev/null
+++ b/adapters/brave/bravetest/exemplary/banner-app.json
@@ -0,0 +1,140 @@
+{
+    "mockBidRequest": {
+      "id": "request-id",
+      "app": {
+        "publisher": {
+          "id": "123456789"
+        },
+        "cat": [
+          "IAB9-1"
+        ],
+        "bundle": "com.app.test",
+        "name": "Test App",
+        "id": "12345678"
+      },
+      "device": {
+        "ua": "useragent",
+        "ip": "100.100.100.100",
+        "language": "en"
+      },
+      "tmax": 1000,
+      "user": {
+        "id": "some-user"
+      },
+      "imp": [
+        {
+          "id": "impression-id",
+          "tagid": "tid",
+          "banner": {
+            "w":320,
+            "h":50
+          },
+          "ext": {
+            "bidder": {
+              "placementId": "f897beb0daba0253d8e59a098eef9311"
+            }
+          }
+        }
+      ]
+    },
+    "httpCalls": [
+    {
+        "expectedRequest": {
+          "headers": {
+            "Content-Type": [
+              "application/json;charset=utf-8"
+            ],
+            "Accept": [
+              "application/json"
+            ]
+          },
+          "uri": "http://point.braveglobal.tv/?t=3&partner=f897beb0daba0253d8e59a098eef9311",
+          "body": {
+            "id": "request-id",
+            "device": {
+              "ua": "useragent",
+              "ip": "100.100.100.100",
+              "language": "en"
+            },
+            "imp": [
+              {
+                "id": "impression-id",
+                "banner": {
+                    "w":320,
+                    "h":50
+                },
+                "tagid": "tid"
+              }
+            ],
+            "app": {
+              "publisher": {
+                "id": "123456789"
+              },
+              "cat": [
+                "IAB9-1"
+              ],
+              "bundle": "com.app.test",
+              "name": "Test App",
+              "id": "12345678"
+            },
+            "user": {
+              "id": "some-user"
+            },
+            "tmax": 1000
+          }
+        },
+        "mockResponse": {
+          "status": 200,
+          "body": {
+            "id": "resp-id",
+            "seatbid": [
+              {
+                "bid": [
+                  {
+                    "id": "123456789",
+                    "impid": "impression-id",
+                    "price": 2,
+                    "adm": "adm code",
+                    "adomain": [
+                      "testdomain.com"
+                    ],
+                    "crid": "100",
+                    "w":320,
+                    "h":50
+                  }
+                ],
+              "type": "banner",
+                "seat": "brave"
+              }
+            ],
+            "cur": "USD",
+            "ext": {
+              "responsetimemillis": {
+                "brave": 120
+              },
+              "tmaxrequest": 1000
+            }
+          }
+        }
+      }
+    ],
+    "expectedBidResponses": [
+      {
+        "bids": [{
+          "bid": {
+            "id": "123456789",
+            "impid": "impression-id",
+            "price": 2,
+            "adm": "adm code",
+            "adomain": [
+              "testdomain.com"
+            ],
+            "crid": "100",
+            "w":320,
+            "h":50
+          },
+          "type": "banner"
+        }]
+      }
+    ]
+  }
diff --git a/adapters/brave/bravetest/exemplary/banner-web.json b/adapters/brave/bravetest/exemplary/banner-web.json
new file mode 100644
index 00000000..0dd6dde0
--- /dev/null
+++ b/adapters/brave/bravetest/exemplary/banner-web.json
@@ -0,0 +1,138 @@
+{
+  "mockBidRequest": {
+    "id": "request-id",
+    "site": {
+      "page": "test.com/page",
+      "domain": "test.com",
+      "cat": [
+        "IAB9-1"
+      ],
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "device": {
+      "ua": "useragent",
+      "ip": "100.100.100.100",
+      "language": "en"
+    },
+    "tmax": 1000,
+    "user": {
+      "id": "some-user"
+    },
+    "imp": [
+      {
+        "id": "impression-id",
+        "tagid": "tid",
+        "banner": {
+          "w":320,
+          "h":50
+        },
+        "ext": {
+          "bidder": {
+            "placementId": "f897beb0daba0253d8e59a098eef9311"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ]
+        },
+        "uri": "http://point.braveglobal.tv/?t=3&partner=f897beb0daba0253d8e59a098eef9311",
+        "body": {
+          "id": "request-id",
+          "device": {
+            "ua": "useragent",
+            "ip": "100.100.100.100",
+            "language": "en"
+          },
+          "imp": [
+            {
+              "id": "impression-id",
+              "banner": {
+                  "w":320,
+                  "h":50
+              },
+              "tagid": "tid"
+            }
+          ],
+          "site": {
+            "page": "test.com/page",
+            "domain": "test.com",
+            "cat": [
+              "IAB9-1"
+            ],
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "id": "some-user"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "resp-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "123456789",
+                  "impid": "impression-id",
+                  "price": 2,
+                  "adm": "adm code",
+                  "adomain": [
+                    "testdomain.com"
+                  ],
+                  "crid": "100",
+                  "w":320,
+                  "h":50
+                }
+              ],
+            "type": "banner",
+              "seat": "brave"
+            }
+          ],
+          "cur": "USD",
+          "ext": {
+            "responsetimemillis": {
+              "brave": 120
+            },
+            "tmaxrequest": 1000
+          }
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "bids": [{
+        "bid": {
+          "id": "123456789",
+          "impid": "impression-id",
+          "price": 2,
+          "adm": "adm code",
+          "adomain": [
+            "testdomain.com"
+          ],
+          "crid": "100",
+          "w":320,
+          "h":50
+        },
+        "type": "banner"
+      }]
+    }
+  ]
+}
diff --git a/adapters/brave/bravetest/exemplary/native-app.json b/adapters/brave/bravetest/exemplary/native-app.json
new file mode 100644
index 00000000..05ac5aa8
--- /dev/null
+++ b/adapters/brave/bravetest/exemplary/native-app.json
@@ -0,0 +1,137 @@
+{
+    "mockBidRequest": {
+      "id": "request-id",
+      "app": {
+        "publisher": {
+          "id": "123456789"
+        },
+        "cat": [
+          "IAB9-1"
+        ],
+        "bundle": "com.app.test",
+        "name": "Test App",
+        "id": "12345678"
+      },
+      "device": {
+        "ua": "useragent",
+        "ip": "100.100.100.100",
+        "language": "en"
+      },
+      "tmax": 1000,
+      "user": {
+        "id": "some-user"
+      },
+      "imp": [
+        {
+          "id": "impression-id",
+          "tagid": "tid",
+          "native": {
+            "ver":"1.1",
+            "request":"{\"adunit\":2,\"assets\":[{\"id\":3,\"img\":{\"h\":120,\"hmin\":0,\"type\":3,\"w\":180,\"wmin\":0},\"required\":1},{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"data\":{\"len\":25,\"type\":1},\"id\":4,\"required\":1},{\"data\":{\"len\":140,\"type\":2},\"id\":6,\"required\":1}],\"context\":1,\"layout\":1,\"contextsubtype\":11,\"plcmtcnt\":1,\"plcmttype\":2,\"ver\":\"1.1\",\"ext\":{\"banner\":{\"w\":320,\"h\":50}}}"
+          },
+	        "ext": {
+            "bidder": {
+              "placementId": "f897beb0daba0253d8e59a098eef9311"
+            }
+          }
+        }
+      ]
+    },
+    "httpCalls": [
+    {
+        "expectedRequest": {
+            "headers": {
+              "Content-Type": [
+                "application/json;charset=utf-8"
+              ],
+              "Accept": [
+                "application/json"
+              ]
+            },
+            "uri": "http://point.braveglobal.tv/?t=3&partner=f897beb0daba0253d8e59a098eef9311",
+            "body": {
+              "id": "request-id",
+              "device": {
+                "ua": "useragent",
+                "ip": "100.100.100.100",
+                "language": "en"
+              },
+              "imp": [
+                {
+                  "id": "impression-id",
+                  "native": {
+                    "ver":"1.1",
+                    "request":"{\"adunit\":2,\"assets\":[{\"id\":3,\"img\":{\"h\":120,\"hmin\":0,\"type\":3,\"w\":180,\"wmin\":0},\"required\":1},{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"data\":{\"len\":25,\"type\":1},\"id\":4,\"required\":1},{\"data\":{\"len\":140,\"type\":2},\"id\":6,\"required\":1}],\"context\":1,\"layout\":1,\"contextsubtype\":11,\"plcmtcnt\":1,\"plcmttype\":2,\"ver\":\"1.1\",\"ext\":{\"banner\":{\"w\":320,\"h\":50}}}"
+                  },
+                  "tagid": "tid"
+                }
+              ],
+              "app": {
+                "publisher": {
+                  "id": "123456789"
+                },
+                "cat": [
+                  "IAB9-1"
+                ],
+                "bundle": "com.app.test",
+                "name": "Test App",
+                "id": "12345678"
+              },
+              "user": {
+                "id": "some-user"
+              },
+              "tmax": 1000
+            }
+        },
+        "mockResponse": {
+
+          "status": 200,
+          "body": {
+            "id": "resp-id",
+            "seatbid": [
+              {
+                "bid": [
+                  {
+                    "id": "123456789",
+                    "impid": "impression-id",
+                    "price": 2,
+                    "adm": "adm code",
+                    "adomain": [
+                      "testdomain.com"
+                    ],
+                    "crid": "100"
+                  }
+                ],
+                "type": "native",
+                "seat": "brave"
+              }
+            ],
+            "cur": "USD",
+            "ext": {
+              "responsetimemillis": {
+                "brave": 120
+              },
+              "tmaxrequest": 1000
+            }
+          }
+        }
+      }
+    ],
+    "expectedBidResponses": [
+      {
+        "bids": [{
+          "bid": {
+            "id": "123456789",
+            "impid": "impression-id",
+            "price": 2,
+            "adm": "adm code",
+            "adomain": [
+              "testdomain.com"
+            ],
+            "crid": "100"
+          },
+          "type": "native"
+        }]
+      }
+    ]
+  }
diff --git a/adapters/brave/bravetest/exemplary/native-web.json b/adapters/brave/bravetest/exemplary/native-web.json
new file mode 100644
index 00000000..01126e46
--- /dev/null
+++ b/adapters/brave/bravetest/exemplary/native-web.json
@@ -0,0 +1,135 @@
+{
+    "mockBidRequest": {
+      "id": "request-id",
+      "site": {
+        "page": "test.com/page",
+        "domain": "test.com",
+        "cat": [
+          "IAB9-1"
+        ],
+        "publisher": {
+          "id": "123456789"
+        }
+      },
+      "device": {
+        "ua": "useragent",
+        "ip": "100.100.100.100",
+        "language": "en"
+      },
+      "tmax": 1000,
+      "user": {
+        "id": "some-user"
+      },
+      "imp": [
+        {
+          "id": "impression-id",
+          "tagid": "tid",
+          "native": {
+            "ver":"1.1",
+            "request":"{\"adunit\":2,\"assets\":[{\"id\":3,\"img\":{\"h\":120,\"hmin\":0,\"type\":3,\"w\":180,\"wmin\":0},\"required\":1},{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"data\":{\"len\":25,\"type\":1},\"id\":4,\"required\":1},{\"data\":{\"len\":140,\"type\":2},\"id\":6,\"required\":1}],\"context\":1,\"layout\":1,\"contextsubtype\":11,\"plcmtcnt\":1,\"plcmttype\":2,\"ver\":\"1.1\",\"ext\":{\"banner\":{\"w\":320,\"h\":50}}}"
+          },
+	        "ext": {
+            "bidder": {
+              "placementId": "f897beb0daba0253d8e59a098eef9311"
+            }
+          }
+        }
+      ]
+    },
+    "httpCalls": [
+    {
+        "expectedRequest": {
+            "headers": {
+              "Content-Type": [
+                "application/json;charset=utf-8"
+              ],
+              "Accept": [
+                "application/json"
+              ]
+            },
+            "uri": "http://point.braveglobal.tv/?t=3&partner=f897beb0daba0253d8e59a098eef9311",
+            "body": {
+              "id": "request-id",
+              "device": {
+                "ua": "useragent",
+                "ip": "100.100.100.100",
+                "language": "en"
+              },
+              "imp": [
+                {
+                  "id": "impression-id",
+                  "native": {
+                    "ver":"1.1",
+                    "request":"{\"adunit\":2,\"assets\":[{\"id\":3,\"img\":{\"h\":120,\"hmin\":0,\"type\":3,\"w\":180,\"wmin\":0},\"required\":1},{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"data\":{\"len\":25,\"type\":1},\"id\":4,\"required\":1},{\"data\":{\"len\":140,\"type\":2},\"id\":6,\"required\":1}],\"context\":1,\"layout\":1,\"contextsubtype\":11,\"plcmtcnt\":1,\"plcmttype\":2,\"ver\":\"1.1\",\"ext\":{\"banner\":{\"w\":320,\"h\":50}}}"
+                  },
+                  "tagid": "tid"
+                }
+              ],
+              "site": {
+                "page": "test.com/page",
+                "domain": "test.com",
+                "cat": [
+                  "IAB9-1"
+                ],
+                "publisher": {
+                  "id": "123456789"
+                }
+              },
+              "user": {
+                "id": "some-user"
+              },
+              "tmax": 1000
+            }
+        },
+        "mockResponse": {
+
+          "status": 200,
+          "body": {
+            "id": "resp-id",
+            "seatbid": [
+              {
+                "bid": [
+                  {
+                    "id": "123456789",
+                    "impid": "impression-id",
+                    "price": 2,
+                    "adm": "adm code",
+                    "adomain": [
+                      "testdomain.com"
+                    ],
+                    "crid": "100"
+                  }
+                ],
+                "type": "native",
+                "seat": "brave"
+              }
+            ],
+            "cur": "USD",
+            "ext": {
+              "responsetimemillis": {
+                "brave": 120
+              },
+              "tmaxrequest": 1000
+            }
+          }
+        }
+      }
+    ],
+    "expectedBidResponses": [
+      {
+        "bids": [{
+          "bid": {
+            "id": "123456789",
+            "impid": "impression-id",
+            "price": 2,
+            "adm": "adm code",
+            "adomain": [
+              "testdomain.com"
+            ],
+            "crid": "100"
+          },
+          "type": "native"
+        }]
+      }
+    ]
+  }
diff --git a/adapters/brave/bravetest/exemplary/video-app.json b/adapters/brave/bravetest/exemplary/video-app.json
new file mode 100644
index 00000000..7f415109
--- /dev/null
+++ b/adapters/brave/bravetest/exemplary/video-app.json
@@ -0,0 +1,150 @@
+{
+  "mockBidRequest": {
+    "id": "request-id",
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB9-1"
+      ],
+      "bundle": "com.app.test",
+      "name": "Test App",
+      "id": "12345678"
+    },
+    "device": {
+      "ua": "useragent",
+      "ip": "100.100.100.100",
+      "language": "en"
+    },
+    "tmax": 1000,
+    "user": {
+      "id": "some-user"
+    },
+    "imp": [
+      {
+        "id": "impression-id",
+        "tagid": "tid",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 30,
+          "maxduration": 150
+        },
+	      "ext": {
+            "bidder": {
+              "placementId": "f897beb0daba0253d8e59a098eef9311"
+            }
+          }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ]
+        },
+        "uri": "http://point.braveglobal.tv/?t=3&partner=f897beb0daba0253d8e59a098eef9311",
+        "body": {
+          "id": "request-id",
+          "device": {
+            "ua": "useragent",
+            "ip": "100.100.100.100",
+            "language": "en"
+          },
+          "imp": [
+            {
+              "id": "impression-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 30,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              },
+              "tagid": "tid"
+            }
+          ],
+          "app": {
+            "publisher": {
+              "id": "123456789"
+            },
+            "cat": [
+              "IAB9-1"
+            ],
+            "bundle": "com.app.test",
+            "name": "Test App",
+            "id": "12345678"
+          },
+          "user": {
+            "id": "some-user"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "resp-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "123456789",
+                  "impid": "impression-id",
+                  "price": 2,
+                  "adm": "adm code",
+                  "adomain": [
+                    "testdomain.com"
+                  ],
+                  "crid": "100",
+                  "w": 1280,
+                  "h": 720
+                }
+              ],
+            "type": "video",
+            "seat": "brave"
+            }
+          ],
+          "cur": "USD",
+          "ext": {
+            "responsetimemillis": {
+              "brave": 120
+            },
+            "tmaxrequest": 1000
+          }
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "bids": [{
+        "bid": {
+          "id": "123456789",
+          "impid": "impression-id",
+          "price": 2,
+          "adm": "adm code",
+          "adomain": [
+            "testdomain.com"
+          ],
+          "crid": "100",
+          "w": 1280,
+          "h": 720
+        },
+        "type": "video"
+      }]
+    }
+  ]
+}
diff --git a/adapters/brave/bravetest/exemplary/video-web.json b/adapters/brave/bravetest/exemplary/video-web.json
new file mode 100644
index 00000000..5da8ff35
--- /dev/null
+++ b/adapters/brave/bravetest/exemplary/video-web.json
@@ -0,0 +1,148 @@
+{
+  "mockBidRequest": {
+    "id": "request-id",
+    "site": {
+      "page": "test.com/page",
+      "domain": "test.com",
+      "cat": [
+        "IAB9-1"
+      ],
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "device": {
+      "ua": "useragent",
+      "ip": "100.100.100.100",
+      "language": "en"
+    },
+    "tmax": 1000,
+    "user": {
+      "id": "some-user"
+    },
+    "imp": [
+      {
+        "id": "impression-id",
+        "tagid": "tid",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 30,
+          "maxduration": 150
+        },
+	      "ext": {
+            "bidder": {
+              "placementId": "f897beb0daba0253d8e59a098eef9311"
+            }
+          }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ]
+        },
+        "uri": "http://point.braveglobal.tv/?t=3&partner=f897beb0daba0253d8e59a098eef9311",
+        "body": {
+          "id": "request-id",
+          "device": {
+            "ua": "useragent",
+            "ip": "100.100.100.100",
+            "language": "en"
+          },
+          "imp": [
+            {
+              "id": "impression-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 30,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              },
+              "tagid": "tid"
+            }
+          ],
+          "site": {
+            "page": "test.com/page",
+            "domain": "test.com",
+            "cat": [
+              "IAB9-1"
+            ],
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "id": "some-user"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "resp-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "123456789",
+                  "impid": "impression-id",
+                  "price": 2,
+                  "adm": "adm code",
+                  "adomain": [
+                    "testdomain.com"
+                  ],
+                  "crid": "100",
+                  "w": 1280,
+                  "h": 720
+                }
+              ],
+            "type": "video",
+            "seat": "brave"
+            }
+          ],
+          "cur": "USD",
+          "ext": {
+            "responsetimemillis": {
+              "brave": 120
+            },
+            "tmaxrequest": 1000
+          }
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "bids": [{
+        "bid": {
+          "id": "123456789",
+          "impid": "impression-id",
+          "price": 2,
+          "adm": "adm code",
+          "adomain": [
+            "testdomain.com"
+          ],
+          "crid": "100",
+          "w": 1280,
+          "h": 720
+        },
+        "type": "video"
+      }]
+    }
+  ]
+}
diff --git a/adapters/brave/bravetest/supplemental/empty-seatbid-array.json b/adapters/brave/bravetest/supplemental/empty-seatbid-array.json
new file mode 100644
index 00000000..c407c822
--- /dev/null
+++ b/adapters/brave/bravetest/supplemental/empty-seatbid-array.json
@@ -0,0 +1,121 @@
+{
+  "mockBidRequest": {
+    "id": "request-id",
+    "site": {
+      "page": "test.com/page",
+      "domain": "test.com",
+      "cat": [
+        "IAB9-1"
+      ],
+      "publisher": {
+        "id": "123456789"
+      }
+    },
+    "device": {
+      "ua": "useragent",
+      "ip": "100.100.100.100",
+      "language": "en"
+    },
+    "tmax": 1000,
+    "user": {
+      "id": "some-user"
+    },
+    "imp": [
+      {
+        "id": "impression-id",
+        "tagid": "tid",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 30,
+          "maxduration": 150
+        },
+	      "ext": {
+            "bidder": {
+              "placementId": "f897beb0daba0253d8e59a098eef9311"
+            }
+          }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ]
+        },
+        "uri": "http://point.braveglobal.tv/?t=3&partner=f897beb0daba0253d8e59a098eef9311",
+        "body": {
+          "id": "request-id",
+          "device": {
+            "ua": "useragent",
+            "ip": "100.100.100.100",
+            "language": "en"
+          },
+          "imp": [
+            {
+              "id": "impression-id",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 30,
+                "maxduration": 150,
+                "w": 640,
+                "h": 480
+              },
+              "tagid": "tid"
+            }
+          ],
+          "site": {
+            "page": "test.com/page",
+            "domain": "test.com",
+            "cat": [
+              "IAB9-1"
+            ],
+            "publisher": {
+              "id": "123456789"
+            }
+          },
+          "user": {
+            "id": "some-user"
+          },
+          "tmax": 1000
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "resp-id",
+          "seatbid": [
+          ],
+          "cur": "USD",
+          "ext": {
+            "responsetimemillis": {
+              "brave": 120
+            },
+            "tmaxrequest": 1000
+          }
+        }
+      }
+    }
+  ],
+    "mockResponse": {
+      "status": 200,
+      "body": "invalid response"
+    },
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Empty SeatBid array",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/brave/bravetest/supplemental/invalid-brave-ext-object.json b/adapters/brave/bravetest/supplemental/invalid-brave-ext-object.json
new file mode 100644
index 00000000..899834e6
--- /dev/null
+++ b/adapters/brave/bravetest/supplemental/invalid-brave-ext-object.json
@@ -0,0 +1,29 @@
+{
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "ext.bidder not provided",
+      "comparison": "literal"
+    }
+  ],
+  "mockBidRequest": {
+    "id": "request-id",
+    "imp": [
+      {
+        "id": "impression-id",
+        "tagid": "tid",
+        "video": {
+          "mimes": ["video/mp4"],
+          "w": 640,
+          "h": 480,
+          "minduration": 30,
+          "maxduration": 150
+        },
+        "ext": "invalid data"
+      }
+    ],
+    "site": {
+      "page": "test.com"
+    }
+  },
+  "httpCalls": []
+}
diff --git a/adapters/brave/bravetest/supplemental/invalid-response.json b/adapters/brave/bravetest/supplemental/invalid-response.json
new file mode 100644
index 00000000..972c2b30
--- /dev/null
+++ b/adapters/brave/bravetest/supplemental/invalid-response.json
@@ -0,0 +1,97 @@
+{
+  "mockBidRequest": {
+    "id": "request-id",
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB9-1"
+      ],
+      "bundle": "com.app.test",
+      "name": "Test App",
+      "id": "12345678"
+    },
+    "device": {
+      "ua": "useragent",
+      "ip": "100.100.100.100",
+      "language": "en"
+    },
+    "tmax": 1000,
+    "user": {
+      "id": "some-user"
+    },
+    "imp": [
+      {
+        "id": "impression-id",
+        "tagid": "tid",
+        "banner": {
+          "w":320,
+          "h":50
+        },
+        "ext": {
+          "bidder": {
+            "placementId": "f897beb0daba0253d8e59a098eef9311"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "headers": {
+        "Content-Type": [
+          "application/json;charset=utf-8"
+        ],
+        "Accept": [
+          "application/json"
+        ]
+      },
+      "uri": "http://point.braveglobal.tv/?t=3&partner=f897beb0daba0253d8e59a098eef9311",
+      "body": {
+        "id": "request-id",
+        "device": {
+          "ua": "useragent",
+          "ip": "100.100.100.100",
+          "language": "en"
+        },
+        "imp": [
+          {
+            "id": "impression-id",
+            "banner": {
+                "w":320,
+                "h":50
+            },
+            "tagid": "tid"
+          }
+        ],
+        "app": {
+          "publisher": {
+            "id": "123456789"
+          },
+          "cat": [
+            "IAB9-1"
+          ],
+          "bundle": "com.app.test",
+          "name": "Test App",
+          "id": "12345678"
+        },
+        "user": {
+          "id": "some-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 200,
+      "body": "invalid response"
+    }
+  }],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Bad Server Response",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/brave/bravetest/supplemental/status-code-bad-request.json b/adapters/brave/bravetest/supplemental/status-code-bad-request.json
new file mode 100644
index 00000000..e80273a7
--- /dev/null
+++ b/adapters/brave/bravetest/supplemental/status-code-bad-request.json
@@ -0,0 +1,108 @@
+
+{
+  "mockBidRequest": {
+    "id": "request-id",
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB9-1"
+      ],
+      "bundle": "com.app.test",
+      "name": "Test App",
+      "id": "12345678"
+    },
+    "device": {
+      "ua": "useragent",
+      "ip": "100.100.100.100",
+      "language": "en"
+    },
+    "tmax": 1000,
+    "user": {
+      "id": "some-user"
+    },
+    "imp": [
+      {
+        "id": "impression-id",
+        "tagid": "tid",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 30,
+          "maxduration": 150
+        },
+	      "ext": {
+            "bidder": {
+              "placementId": "f897beb0daba0253d8e59a098eef9311"
+            }
+          }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "headers": {
+        "Content-Type": [
+          "application/json;charset=utf-8"
+        ],
+        "Accept": [
+          "application/json"
+        ]
+      },
+      "uri": "http://point.braveglobal.tv/?t=3&partner=f897beb0daba0253d8e59a098eef9311",
+      "body": {
+        "id": "request-id",
+        "device": {
+          "ua": "useragent",
+          "ip": "100.100.100.100",
+          "language": "en"
+        },
+        "imp": [
+          {
+            "id": "impression-id",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 30,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "tagid": "tid"
+          }
+        ],
+        "app": {
+          "publisher": {
+            "id": "123456789"
+          },
+          "cat": [
+            "IAB9-1"
+          ],
+          "bundle": "com.app.test",
+          "name": "Test App",
+          "id": "12345678"
+        },
+        "user": {
+          "id": "some-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 400
+    }
+  }],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 400. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/brave/bravetest/supplemental/status-code-no-content.json b/adapters/brave/bravetest/supplemental/status-code-no-content.json
new file mode 100644
index 00000000..eb369bd8
--- /dev/null
+++ b/adapters/brave/bravetest/supplemental/status-code-no-content.json
@@ -0,0 +1,108 @@
+
+{
+  "mockBidRequest": {
+    "id": "request-id",
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB9-1"
+      ],
+      "bundle": "com.app.test",
+      "name": "Test App",
+      "id": "12345678"
+    },
+    "device": {
+      "ua": "useragent",
+      "ip": "100.100.100.100",
+      "language": "en"
+    },
+    "tmax": 1000,
+    "user": {
+      "id": "some-user"
+    },
+    "imp": [
+      {
+        "id": "impression-id",
+        "tagid": "tid",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 30,
+          "maxduration": 150
+        },
+	      "ext": {
+            "bidder": {
+              "placementId": "f897beb0daba0253d8e59a098eef9311"
+            }
+          }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "headers": {
+        "Content-Type": [
+          "application/json;charset=utf-8"
+        ],
+        "Accept": [
+          "application/json"
+        ]
+      },
+      "uri": "http://point.braveglobal.tv/?t=3&partner=f897beb0daba0253d8e59a098eef9311",
+      "body": {
+        "id": "request-id",
+        "device": {
+          "ua": "useragent",
+          "ip": "100.100.100.100",
+          "language": "en"
+        },
+        "imp": [
+          {
+            "id": "impression-id",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 30,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "tagid": "tid"
+          }
+        ],
+        "app": {
+          "publisher": {
+            "id": "123456789"
+          },
+          "cat": [
+            "IAB9-1"
+          ],
+          "bundle": "com.app.test",
+          "name": "Test App",
+          "id": "12345678"
+        },
+        "user": {
+          "id": "some-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 204
+    }
+  }],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "No bid",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/brave/bravetest/supplemental/status-code-other-error.json b/adapters/brave/bravetest/supplemental/status-code-other-error.json
new file mode 100644
index 00000000..bd68ee85
--- /dev/null
+++ b/adapters/brave/bravetest/supplemental/status-code-other-error.json
@@ -0,0 +1,108 @@
+
+{
+  "mockBidRequest": {
+    "id": "request-id",
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB9-1"
+      ],
+      "bundle": "com.app.test",
+      "name": "Test App",
+      "id": "12345678"
+    },
+    "device": {
+      "ua": "useragent",
+      "ip": "100.100.100.100",
+      "language": "en"
+    },
+    "tmax": 1000,
+    "user": {
+      "id": "some-user"
+    },
+    "imp": [
+      {
+        "id": "impression-id",
+        "tagid": "tid",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 30,
+          "maxduration": 150
+        },
+	      "ext": {
+            "bidder": {
+              "placementId": "f897beb0daba0253d8e59a098eef9311"
+            }
+          }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "headers": {
+        "Content-Type": [
+          "application/json;charset=utf-8"
+        ],
+        "Accept": [
+          "application/json"
+        ]
+      },
+      "uri": "http://point.braveglobal.tv/?t=3&partner=f897beb0daba0253d8e59a098eef9311",
+      "body": {
+        "id": "request-id",
+        "device": {
+          "ua": "useragent",
+          "ip": "100.100.100.100",
+          "language": "en"
+        },
+        "imp": [
+          {
+            "id": "impression-id",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 30,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "tagid": "tid"
+          }
+        ],
+        "app": {
+          "publisher": {
+            "id": "123456789"
+          },
+          "cat": [
+            "IAB9-1"
+          ],
+          "bundle": "com.app.test",
+          "name": "Test App",
+          "id": "12345678"
+        },
+        "user": {
+          "id": "some-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 306
+    }
+  }],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Something went wrong, please contact your Account Manager. Status Code: [ 306 ] ",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/brave/bravetest/supplemental/status-code-service-unavailable.json b/adapters/brave/bravetest/supplemental/status-code-service-unavailable.json
new file mode 100644
index 00000000..f66347d8
--- /dev/null
+++ b/adapters/brave/bravetest/supplemental/status-code-service-unavailable.json
@@ -0,0 +1,107 @@
+{
+  "mockBidRequest": {
+    "id": "request-id",
+    "app": {
+      "publisher": {
+        "id": "123456789"
+      },
+      "cat": [
+        "IAB9-1"
+      ],
+      "bundle": "com.app.test",
+      "name": "Test App",
+      "id": "12345678"
+    },
+    "device": {
+      "ua": "useragent",
+      "ip": "100.100.100.100",
+      "language": "en"
+    },
+    "tmax": 1000,
+    "user": {
+      "id": "some-user"
+    },
+    "imp": [
+      {
+        "id": "impression-id",
+        "tagid": "tid",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "w": 640,
+          "h": 480,
+          "minduration": 30,
+          "maxduration": 150
+        },
+	      "ext": {
+            "bidder": {
+              "placementId": "f897beb0daba0253d8e59a098eef9311"
+            }
+          }
+      }
+    ]
+  },
+
+  "httpCalls": [{
+    "expectedRequest": {
+      "headers": {
+        "Content-Type": [
+          "application/json;charset=utf-8"
+        ],
+        "Accept": [
+          "application/json"
+        ]
+      },
+      "uri": "http://point.braveglobal.tv/?t=3&partner=f897beb0daba0253d8e59a098eef9311",
+      "body": {
+        "id": "request-id",
+        "device": {
+          "ua": "useragent",
+          "ip": "100.100.100.100",
+          "language": "en"
+        },
+        "imp": [
+          {
+            "id": "impression-id",
+            "video": {
+              "mimes": [
+                "video/mp4"
+              ],
+              "minduration": 30,
+              "maxduration": 150,
+              "w": 640,
+              "h": 480
+            },
+            "tagid": "tid"
+          }
+        ],
+        "app": {
+          "publisher": {
+            "id": "123456789"
+          },
+          "cat": [
+            "IAB9-1"
+          ],
+          "bundle": "com.app.test",
+          "name": "Test App",
+          "id": "12345678"
+        },
+        "user": {
+          "id": "some-user"
+        },
+        "tmax": 1000
+      }
+    },
+    "mockResponse": {
+      "status": 503
+    }
+  }],
+  "expectedBidResponses": [],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Service Unavailable. Status Code: [ 503 ] ",
+      "comparison": "literal"
+    }
+  ]
+}
diff --git a/adapters/brave/params_test.go b/adapters/brave/params_test.go
new file mode 100644
index 00000000..1120a13c
--- /dev/null
+++ b/adapters/brave/params_test.go
@@ -0,0 +1,51 @@
+package brave
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+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.BidderBrave, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected Brave params: %s", validParam)
+		}
+	}
+}
+
+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.BidderBrave, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{ "placementId": "f897beb0daba0253d8e59a098eef9311" }`,
+}
+
+var invalidParams = []string{
+	``,
+	`null`,
+	`true`,
+	`5`,
+	`4.2`,
+	`[]`,
+	`{}`,
+	`{"adCode": "string", "seatCode": 5, "originalPublisherid": "string"}`,
+	`{ "placementid": "f897beb0daba0253d8e59a098eef9311" }`,
+	`{ "PlacementId": "f897beb0daba0253d8e59a098eef9311" }`,
+}
diff --git a/adapters/kiviads/kiviads_test.go b/adapters/kiviads/kiviads_test.go
new file mode 100644
index 00000000..41e9bcbc
--- /dev/null
+++ b/adapters/kiviads/kiviads_test.go
@@ -0,0 +1,20 @@
+package kiviads
+
+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.BidderKiviads, config.Adapter{
+		Endpoint: "http://endpoint1.kiviads.com/pserver"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	adapterstest.RunJSONBidderTest(t, "kiviadstest", bidder)
+}
diff --git a/adapters/kiviads/kiviadstest/exemplary/endpointId.json b/adapters/kiviads/kiviadstest/exemplary/endpointId.json
new file mode 100644
index 00000000..85e66896
--- /dev/null
+++ b/adapters/kiviads/kiviadstest/exemplary/endpointId.json
@@ -0,0 +1,123 @@
+{
+    "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",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "endpointId": "test"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://endpoint1.kiviads.com/pserver",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "tagid": "test",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    },
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "endpointId": "test",
+                                    "type": "network"
+                                }
+                            }
+                        }
+                    ],
+                    "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": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://endpoint1.kiviads.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                                    "cid": "test_cid",
+                                    "crid": "test_crid",
+                                    "dealid": "test_dealid",
+                                    "w": 300,
+                                    "h": 250
+                                }
+                            ],
+                            "seat": "kiviads"
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test_bid_id",
+                        "impid": "test-imp-id",
+                        "price": 0.27543,
+                        "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://endpoint1.kiviads.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                        "cid": "test_cid",
+                        "crid": "test_crid",
+                        "dealid": "test_dealid",
+                        "w": 300,
+                        "h": 250
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/kiviads/kiviadstest/exemplary/simple-banner.json b/adapters/kiviads/kiviadstest/exemplary/simple-banner.json
new file mode 100644
index 00000000..b80f0c5f
--- /dev/null
+++ b/adapters/kiviads/kiviadstest/exemplary/simple-banner.json
@@ -0,0 +1,123 @@
+{
+    "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",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://endpoint1.kiviads.com/pserver",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "tagid": "test",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    },
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": "test",
+                                    "type": "publisher"
+                                }
+                            }
+                        }
+                    ],
+                    "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": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://endpoint1.kiviads.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                                    "cid": "test_cid",
+                                    "crid": "test_crid",
+                                    "dealid": "test_dealid",
+                                    "w": 300,
+                                    "h": 250
+                                }
+                            ],
+                            "seat": "kiviads"
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test_bid_id",
+                        "impid": "test-imp-id",
+                        "price": 0.27543,
+                        "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://endpoint1.kiviads.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                        "cid": "test_cid",
+                        "crid": "test_crid",
+                        "dealid": "test_dealid",
+                        "w": 300,
+                        "h": 250
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/kiviads/kiviadstest/exemplary/simple-native.json b/adapters/kiviads/kiviadstest/exemplary/simple-native.json
new file mode 100644
index 00000000..043bfeeb
--- /dev/null
+++ b/adapters/kiviads/kiviadstest/exemplary/simple-native.json
@@ -0,0 +1,107 @@
+{
+    "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": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://endpoint1.kiviads.com/pserver",
+                "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"
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": "test",
+                                    "type": "publisher"
+                                }
+                            }
+                        }
+                    ],
+                    "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": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://endpoint1.kiviads.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                                    "cid": "test_cid",
+                                    "crid": "test_crid",
+                                    "dealid": "test_dealid",
+                                    "w": 300,
+                                    "h": 250
+                                }
+                            ],
+                            "seat": "kiviads"
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test_bid_id",
+                        "impid": "test-imp-id",
+                        "price": 0.27543,
+                        "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://endpoint1.kiviads.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                        "cid": "test_cid",
+                        "crid": "test_crid",
+                        "dealid": "test_dealid",
+                        "w": 300,
+                        "h": 250
+                    },
+                    "type": "native"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/kiviads/kiviadstest/exemplary/simple-video.json b/adapters/kiviads/kiviadstest/exemplary/simple-video.json
new file mode 100644
index 00000000..c14df358
--- /dev/null
+++ b/adapters/kiviads/kiviadstest/exemplary/simple-video.json
@@ -0,0 +1,118 @@
+{
+    "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",
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "protocols": [
+                        2,
+                        5
+                    ],
+                    "w": 1024,
+                    "h": 576
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://endpoint1.kiviads.com/pserver",
+                "body": {
+                    "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",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "protocols": [
+                                    2,
+                                    5
+                                ],
+                                "w": 1024,
+                                "h": 576
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": "test",
+                                    "type": "publisher"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "bid": [
+                                {
+                                    "id": "test_bid_id",
+                                    "impid": "test-imp-id",
+                                    "price": 0.27543,
+                                    "adm": "<VAST version=\"3.0\"><Ad id=\"20001\" sequence=\"1\"><InLine><AdSystem version=\"4.0\"><![CDATA[iabtechlab]]></AdSystem><AdTitle><![CDATA[Inline Simple Ad]]></AdTitle><Impression><![CDATA[]]></Impression><Creatives><Creative id=\"5480\" sequence=\"1\"><Linear><Duration>00:01:00</Duration><MediaFiles><MediaFile id=\"5246\" delivery=\"progressive\" type=\"video/mp4\" bitrate=\"600\" width=\"640\" height=\"360\" minBitrate=\"500\" maxBitrate=\"700\" scalable=\"1\" maintainAspectRatio=\"1\" codec=\"0\"><![CDATA[https://s0.2mdn.net/4253510/google_ddm_animation_480P.mp4]]></MediaFile></MediaFiles><VideoClicks><ClickThrough id=\"blog\"><![CDATA[https://example.com]]></ClickThrough></VideoClicks></Linear></Creative></Creatives></InLine></Ad></VAST>",
+                                    "cid": "test_cid",
+                                    "crid": "test_crid",
+                                    "dealid": "test_dealid"
+                                }
+                            ],
+                            "seat": "kiviads"
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test_bid_id",
+                        "impid": "test-imp-id",
+                        "price": 0.27543,
+                        "adm": "<VAST version=\"3.0\"><Ad id=\"20001\" sequence=\"1\"><InLine><AdSystem version=\"4.0\"><![CDATA[iabtechlab]]></AdSystem><AdTitle><![CDATA[Inline Simple Ad]]></AdTitle><Impression><![CDATA[]]></Impression><Creatives><Creative id=\"5480\" sequence=\"1\"><Linear><Duration>00:01:00</Duration><MediaFiles><MediaFile id=\"5246\" delivery=\"progressive\" type=\"video/mp4\" bitrate=\"600\" width=\"640\" height=\"360\" minBitrate=\"500\" maxBitrate=\"700\" scalable=\"1\" maintainAspectRatio=\"1\" codec=\"0\"><![CDATA[https://s0.2mdn.net/4253510/google_ddm_animation_480P.mp4]]></MediaFile></MediaFiles><VideoClicks><ClickThrough id=\"blog\"><![CDATA[https://example.com]]></ClickThrough></VideoClicks></Linear></Creative></Creatives></InLine></Ad></VAST>",
+                        "cid": "test_cid",
+                        "crid": "test_crid",
+                        "dealid": "test_dealid"
+                    },
+                    "type": "video"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/kiviads/kiviadstest/exemplary/simple-web-banner.json b/adapters/kiviads/kiviadstest/exemplary/simple-web-banner.json
new file mode 100644
index 00000000..7396dd99
--- /dev/null
+++ b/adapters/kiviads/kiviadstest/exemplary/simple-web-banner.json
@@ -0,0 +1,123 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "tagid": "test",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ],
+        "site": {
+            "id": "1",
+            "domain": "test.com"
+        },
+        "device": {
+            "ip": "123.123.123.123",
+            "ua": "Ubuntu"
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://endpoint1.kiviads.com/pserver",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "tagid": "test",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    },
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": "test",
+                                    "type": "publisher"
+                                }
+                            }
+                        }
+                    ],
+                    "site": {
+                        "id": "1",
+                        "domain": "test.com"
+                    },
+                    "device": {
+                        "ip": "123.123.123.123",
+                        "ua": "Ubuntu"
+                    }
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "bid": [
+                                {
+                                    "id": "test_bid_id",
+                                    "impid": "test-imp-id",
+                                    "price": 0.27543,
+                                    "adm": "<iframe id=\"adm-banner-1\" width=\"468\" height=\"60\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://endpoint1.kiviads.com/pserver&k=bc2d316f39931a07d9a8dd249bf85fc0\"></iframe>",
+                                    "cid": "test_cid",
+                                    "crid": "test_crid",
+                                    "dealid": "test_dealid",
+                                    "w": 468,
+                                    "h": 60
+                                }
+                            ],
+                            "seat": "kiviads"
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test_bid_id",
+                        "impid": "test-imp-id",
+                        "price": 0.27543,
+                        "adm": "<iframe id=\"adm-banner-1\" width=\"468\" height=\"60\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://endpoint1.kiviads.com/pserver&k=bc2d316f39931a07d9a8dd249bf85fc0\"></iframe>",
+                        "cid": "test_cid",
+                        "crid": "test_crid",
+                        "dealid": "test_dealid",
+                        "w": 468,
+                        "h": 60
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/kiviads/kiviadstest/supplemental/bad_media_type.json b/adapters/kiviads/kiviadstest/supplemental/bad_media_type.json
new file mode 100644
index 00000000..9a204eab
--- /dev/null
+++ b/adapters/kiviads/kiviadstest/supplemental/bad_media_type.json
@@ -0,0 +1,81 @@
+{
+	"mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ],
+        "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+        },
+        "device": {
+            "ip": "123.123.123.123",
+            "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+        }
+    },
+	"httpCalls": [{
+		"expectedRequest": {
+			"uri": "http://endpoint1.kiviads.com/pserver",
+			"body": {
+                "id": "test-request-id",
+                "imp": [
+                    {
+                        "id": "test-imp-id",
+                        "ext": {
+                            "bidder": {
+                                "placementId": "test",
+                                "type": "publisher"
+                            }
+                        }
+                    }
+                ],
+                "app": {
+                    "id": "1",
+                    "bundle": "com.wls.testwlsapplication"
+                },
+                "device": {
+                    "ip": "123.123.123.123",
+                    "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+                }
+            }
+		},
+		"mockResponse": {
+			"status": 200,
+			"body": {
+                "id": "test-request-id",
+                "seatbid": [
+                    {
+                        "bid": [
+                            {
+                                "id": "test_bid_id",
+                                "impid": "test-imp-id",
+                                "price": 0.27543,
+                                "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://endpoint1.kiviads.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                                "cid": "test_cid",
+                                "crid": "test_crid",
+                                "dealid": "test_dealid",
+                                "w": 300,
+                                "h": 250
+                            }
+                        ],
+                        "seat": "kiviads"
+                    }
+                ],
+                "cur": "USD"
+            }
+        }
+    }],
+    "expectedMakeBidsErrors": [
+        {
+          "value": "Failed to find impression \"test-imp-id\"",
+          "comparison": "literal"
+        }
+    ]
+}
diff --git a/adapters/kiviads/kiviadstest/supplemental/bad_response.json b/adapters/kiviads/kiviadstest/supplemental/bad_response.json
new file mode 100644
index 00000000..e9671824
--- /dev/null
+++ b/adapters/kiviads/kiviadstest/supplemental/bad_response.json
@@ -0,0 +1,84 @@
+{
+	"mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ],
+        "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+        },
+        "device": {
+            "ip": "123.123.123.123",
+            "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+        }
+    },
+	"httpCalls": [{
+		"expectedRequest": {
+			"uri": "http://endpoint1.kiviads.com/pserver",
+			"body": {
+                "id": "test-request-id",
+                "imp": [
+                    {
+                        "id": "test-imp-id",
+                        "banner": {
+                            "format": [
+                                {
+                                    "w": 300,
+                                    "h": 250
+                                },
+                                {
+                                    "w": 300,
+                                    "h": 600
+                                }
+                            ]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": "test",
+                                "type": "publisher"
+                            }
+                        }
+                    }
+                ],
+                "app": {
+                    "id": "1",
+                    "bundle": "com.wls.testwlsapplication"
+                },
+                "device": {
+                    "ip": "123.123.123.123",
+                    "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+                }
+            }
+		},
+		"mockResponse": {
+			"status": 200,
+			"body": ""
+        }
+    }],
+    "expectedMakeBidsErrors": [
+        {
+          "value": "json: cannot unmarshal string into Go value of type openrtb2.BidResponse",
+          "comparison": "literal"
+        }
+    ]
+}
diff --git a/adapters/kiviads/kiviadstest/supplemental/status-204.json b/adapters/kiviads/kiviadstest/supplemental/status-204.json
new file mode 100644
index 00000000..71229f88
--- /dev/null
+++ b/adapters/kiviads/kiviadstest/supplemental/status-204.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
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ],
+        "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+        },
+        "device": {
+            "ip": "123.123.123.123",
+            "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+        }
+    },
+	"httpCalls": [{
+		"expectedRequest": {
+			"uri": "http://endpoint1.kiviads.com/pserver",
+			"body": {
+                "id": "test-request-id",
+                "imp": [
+                    {
+                        "id": "test-imp-id",
+                        "banner": {
+                            "format": [
+                                {
+                                    "w": 300,
+                                    "h": 250
+                                },
+                                {
+                                    "w": 300,
+                                    "h": 600
+                                }
+                            ]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": "test",
+                                "type": "publisher"
+                            }
+                        }
+                    }
+                ],
+                "app": {
+                    "id": "1",
+                    "bundle": "com.wls.testwlsapplication"
+                },
+                "device": {
+                    "ip": "123.123.123.123",
+                    "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+                }
+            }
+		},
+		"mockResponse": {
+			"status": 204,
+			"body": {}
+		}
+    }],
+    "expectedBidResponses": []
+}
diff --git a/adapters/kiviads/kiviadstest/supplemental/status-not-200.json b/adapters/kiviads/kiviadstest/supplemental/status-not-200.json
new file mode 100644
index 00000000..16d2db48
--- /dev/null
+++ b/adapters/kiviads/kiviadstest/supplemental/status-not-200.json
@@ -0,0 +1,84 @@
+{
+	"mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ],
+        "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+        },
+        "device": {
+            "ip": "123.123.123.123",
+            "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+        }
+    },
+	"httpCalls": [{
+		"expectedRequest": {
+			"uri": "http://endpoint1.kiviads.com/pserver",
+			"body": {
+                "id": "test-request-id",
+                "imp": [
+                    {
+                        "id": "test-imp-id",
+                        "banner": {
+                            "format": [
+                                {
+                                    "w": 300,
+                                    "h": 250
+                                },
+                                {
+                                    "w": 300,
+                                    "h": 600
+                                }
+                            ]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": "test",
+                                "type": "publisher"
+                            }
+                        }
+                    }
+                ],
+                "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/adapters/kiviads/params_test.go b/adapters/kiviads/params_test.go
new file mode 100644
index 00000000..177e2f14
--- /dev/null
+++ b/adapters/kiviads/params_test.go
@@ -0,0 +1,47 @@
+package kiviads
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestValidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json schema. %v", err)
+	}
+
+	for _, p := range validParams {
+		if err := validator.Validate(openrtb_ext.BidderKiviads, json.RawMessage(p)); err != nil {
+			t.Errorf("Schema rejected valid params: %s", p)
+		}
+	}
+}
+
+func TestInvalidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json schema. %v", err)
+	}
+
+	for _, p := range invalidParams {
+		if err := validator.Validate(openrtb_ext.BidderKiviads, json.RawMessage(p)); err == nil {
+			t.Errorf("Schema allowed invalid params: %s", p)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"placementId": "test"}`,
+	`{"placementId": "1"}`,
+	`{"endpointId": "test"}`,
+	`{"endpointId": "1"}`,
+}
+
+var invalidParams = []string{
+	`{"placementId": 42}`,
+	`{"endpointId": 42}`,
+	`{"placementId": "1", "endpointId": "1"}`,
+}
diff --git a/adapters/openx/openxtest/exemplary/fledge-no-bids.json b/adapters/openx/openxtest/exemplary/fledge-no-bids.json
new file mode 100644
index 00000000..5c09b9ae
--- /dev/null
+++ b/adapters/openx/openxtest/exemplary/fledge-no-bids.json
@@ -0,0 +1,88 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 90}]
+        },
+        "ext": {
+          "ae": 1,
+          "bidder": {
+            "unit": "539439964",
+            "delDomain": "se-demo-d.openx.net"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://rtb.openx.net/prebid",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [{"w": 728, "h": 90}]
+              },
+              "tagid": "539439964",
+              "ext": {
+                "ae": 1
+              }
+            }
+          ],
+          "ext": {
+            "bc": "hb_pbs_1.0.0",
+            "delDomain": "se-demo-d.openx.net"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "cur": "USD",
+          "nbr": 1,
+          "ext": {
+            "fledge_auction_configs": {
+              "test-request-id": {
+                "seller": "openx.com",
+                "interestGroupBuyers": ["buyer1.com"],
+                "sellerTimeout": 0,
+                "perBuyerSignals": {
+                  "buyer1.com": [1,"two",3,4, {}]
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [],
+      "fledgeauctionconfigs": [
+        {
+          "impid": "test-request-id",
+          "bidder": "openx",
+          "config": {
+            "seller": "openx.com",
+            "interestGroupBuyers": ["buyer1.com"],
+            "sellerTimeout": 0,
+            "perBuyerSignals": {
+              "buyer1.com": [1,"two",3,4, {}]
+            }
+          }
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/openx/openxtest/exemplary/fledge.json b/adapters/openx/openxtest/exemplary/fledge.json
new file mode 100644
index 00000000..9c8074b3
--- /dev/null
+++ b/adapters/openx/openxtest/exemplary/fledge.json
@@ -0,0 +1,114 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 90}]
+        },
+        "ext": {
+          "ae": 1,
+          "bidder": {
+            "unit": "539439964",
+            "delDomain": "se-demo-d.openx.net"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://rtb.openx.net/prebid",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [{"w": 728, "h": 90}]
+              },
+              "tagid": "539439964",
+              "ext": {
+                "ae": 1
+              }
+            }
+          ],
+          "ext": {
+            "bc": "hb_pbs_1.0.0",
+            "delDomain": "se-demo-d.openx.net"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "openx",
+              "bid": [{
+                "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+                "impid": "test-imp-id",
+                "price": 0.500000,
+                "adm": "some-test-ad",
+                "crid": "crid_10",
+                "h": 90,
+                "w": 728
+              }]
+            }
+          ],
+          "cur": "USD",
+          "ext": {
+            "fledge_auction_configs": {
+              "test-request-id": {
+                "seller": "openx.com",
+                "interestGroupBuyers": ["buyer1.com"],
+                "sellerTimeout": 0,
+                "perBuyerSignals": {
+                  "buyer1.com": [1,"two",3,4, {}]
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adm": "some-test-ad",
+            "crid": "crid_10",
+            "w": 728,
+            "h": 90
+          },
+          "type": "banner"
+        }
+      ],
+      "fledgeauctionconfigs": [
+        {
+          "impid": "test-request-id",
+          "bidder": "openx",
+          "config": {
+            "seller": "openx.com",
+            "interestGroupBuyers": ["buyer1.com"],
+            "sellerTimeout": 0,
+            "perBuyerSignals": {
+              "buyer1.com": [1,"two",3,4, {}]
+            }
+          }
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/rubicon/rubicontest/exemplary/simple-native.json b/adapters/rubicon/rubicontest/exemplary/simple-native.json
index da970486..976d05c1 100644
--- a/adapters/rubicon/rubicontest/exemplary/simple-native.json
+++ b/adapters/rubicon/rubicontest/exemplary/simple-native.json
@@ -335,7 +335,7 @@
                   "cid": "test_cid",
                   "crid": "test_crid",
                   "dealid": "test_dealid",
-                  "admobject": {
+                  "adm_native": {
                     "property1": "value1"
                   },
                   "ext": {
diff --git a/endpoints/openrtb2/amp_auction_test.go b/endpoints/openrtb2/amp_auction_test.go
index 58c13963..80544874 100644
--- a/endpoints/openrtb2/amp_auction_test.go
+++ b/endpoints/openrtb2/amp_auction_test.go
@@ -1345,6 +1345,7 @@ func (s formatOverrideSpec) execute(t *testing.T) {
 
 type mockAmpExchange struct {
 	lastRequest *openrtb2.BidRequest
+	requestExt  json.RawMessage
 }
 
 var expectedErrorsFromHoldAuction map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage = map[openrtb_ext.BidderName][]openrtb_ext.ExtBidderMessage{
@@ -1369,6 +1370,10 @@ func (m *mockAmpExchange) HoldAuction(ctx context.Context, auctionRequest exchan
 		}},
 		Ext: json.RawMessage(`{ "errors": {"openx":[ { "code": 1, "message": "The request exceeded the timeout allocated" } ] } }`),
 	}
+
+	if m.requestExt != nil {
+		response.Ext = m.requestExt
+	}
 	if len(auctionRequest.StoredAuctionResponses) > 0 {
 		var seatBids []openrtb2.SeatBid
 
@@ -1588,6 +1593,7 @@ func TestBuildAmpObject(t *testing.T) {
 	testCases := []struct {
 		description       string
 		inTagId           string
+		exchange          *mockAmpExchange
 		inStoredRequest   json.RawMessage
 		expectedAmpObject *analytics.AmpObject
 	}{
@@ -1671,6 +1677,61 @@ func TestBuildAmpObject(t *testing.T) {
 				Origin: "",
 			},
 		},
+		{
+			description:     "Global targeting from bid response should be applied for Amp",
+			inTagId:         "test",
+			inStoredRequest: json.RawMessage(`{"id":"some-request-id","site":{"page":"prebid.org"},"imp":[{"id":"some-impression-id","banner":{"format":[{"w":300,"h":250}]},"ext":{"prebid":{"bidder":{"appnexus":{"placementId":12883451}}}}}],"tmax":500}`),
+			exchange:        &mockAmpExchange{requestExt: json.RawMessage(`{ "prebid": {"targeting": { "test_key": "test_value", "hb_appnexus_pb": "9999" } }, "errors": {"openx":[ { "code": 1, "message": "The request exceeded the timeout allocated" } ] } }`)},
+			expectedAmpObject: &analytics.AmpObject{
+				Status: http.StatusOK,
+				Errors: nil,
+				Request: &openrtb2.BidRequest{
+					ID: "some-request-id",
+					Device: &openrtb2.Device{
+						IP: "192.0.2.1",
+					},
+					Site: &openrtb2.Site{
+						Page: "prebid.org",
+						Ext:  json.RawMessage(`{"amp":1}`),
+					},
+					Imp: []openrtb2.Imp{
+						{
+							ID: "some-impression-id",
+							Banner: &openrtb2.Banner{
+								Format: []openrtb2.Format{
+									{
+										W: 300,
+										H: 250,
+									},
+								},
+							},
+							Secure: func(val int8) *int8 { return &val }(1), //(*int8)(1),
+							Ext:    json.RawMessage(`{"prebid":{"bidder":{"appnexus":{"placementId":12883451}}}}`),
+						},
+					},
+					AT:   1,
+					TMax: 500,
+					Ext:  json.RawMessage(`{"prebid":{"cache":{"bids":{"returnCreative":null},"vastxml":null},"channel":{"name":"amp","version":""},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":20,"increment":0.1}]},"includewinners":true,"includebidderkeys":true,"includebrandcategory":null,"includeformat":false,"durationrangesec":null,"preferdeals":false}}}`),
+				},
+				AuctionResponse: &openrtb2.BidResponse{
+					SeatBid: []openrtb2.SeatBid{{
+						Bid: []openrtb2.Bid{{
+							AdM: "<script></script>",
+							Ext: json.RawMessage(`{ "prebid": {"targeting": { "hb_pb": "1.20", "hb_appnexus_pb": "1.20", "hb_cache_id": "some_id"}}}`),
+						}},
+						Seat: "",
+					}},
+					Ext: json.RawMessage(`{ "prebid": {"targeting": { "test_key": "test_value", "hb_appnexus_pb": "9999" } }, "errors": {"openx":[ { "code": 1, "message": "The request exceeded the timeout allocated" } ] } }`),
+				},
+				AmpTargetingValues: map[string]string{
+					"hb_appnexus_pb": "1.20", // Bid level has higher priority than global
+					"hb_cache_id":    "some_id",
+					"hb_pb":          "1.20",
+					"test_key":       "test_value", // New global key added
+				},
+				Origin: "",
+			},
+		},
 	}
 
 	request := httptest.NewRequest("GET", "/openrtb2/auction/amp?tag_id=test", nil)
@@ -1678,7 +1739,11 @@ func TestBuildAmpObject(t *testing.T) {
 
 	for _, test := range testCases {
 		// Set up test, declare a new mock logger every time
-		actualAmpObject, endpoint := ampObjectTestSetup(t, test.inTagId, test.inStoredRequest, false)
+		exchange := test.exchange
+		if exchange == nil {
+			exchange = &mockAmpExchange{}
+		}
+		actualAmpObject, endpoint := ampObjectTestSetup(t, test.inTagId, test.inStoredRequest, false, exchange)
 		// Run test
 		endpoint(recorder, request, nil)
 
@@ -1744,13 +1809,13 @@ func TestIdGeneration(t *testing.T) {
 
 	for _, test := range testCases {
 		// Set up and run test
-		actualAmpObject, endpoint := ampObjectTestSetup(t, "test", test.givenInStoredRequest, test.givenGenerateRequestID)
+		actualAmpObject, endpoint := ampObjectTestSetup(t, "test", test.givenInStoredRequest, test.givenGenerateRequestID, &mockAmpExchange{})
 		endpoint(recorder, request, nil)
 		assert.Equalf(t, test.expectedID, actualAmpObject.Request.ID, "Bid Request ID is incorrect: %s\n", test.description)
 	}
 }
 
-func ampObjectTestSetup(t *testing.T, inTagId string, inStoredRequest json.RawMessage, generateRequestID bool) (*analytics.AmpObject, httprouter.Handle) {
+func ampObjectTestSetup(t *testing.T, inTagId string, inStoredRequest json.RawMessage, generateRequestID bool, exchange *mockAmpExchange) (*analytics.AmpObject, httprouter.Handle) {
 	actualAmpObject := analytics.AmpObject{}
 	logger := newMockLogger(&actualAmpObject, nil)
 
@@ -1762,7 +1827,7 @@ func ampObjectTestSetup(t *testing.T, inTagId string, inStoredRequest json.RawMe
 
 	endpoint, _ := NewAmpEndpoint(
 		fakeUUIDGenerator{id: "foo", err: nil},
-		&mockAmpExchange{},
+		exchange,
 		newParamsValidator(t),
 		mockAmpFetcher,
 		empty_fetcher.EmptyFetcher{},
diff --git a/endpoints/openrtb2/video_auction_test.go b/endpoints/openrtb2/video_auction_test.go
index c9cd0aff..4e8fe2f7 100644
--- a/endpoints/openrtb2/video_auction_test.go
+++ b/endpoints/openrtb2/video_auction_test.go
@@ -60,6 +60,7 @@ func TestVideoEndpointImpressionsNumber(t *testing.T) {
 	assert.Len(t, resp.AdPods[4].Targeting, 3, "Incorrect Targeting data in response")
 
 	assert.Equal(t, resp.AdPods[4].Targeting[0].HbPbCatDur, "20.00_395_30s", "Incorrect number of Ad Pods in response")
+	assert.Equal(t, resp.AdPods[0].Targeting[0].HbDeal, "ABC_123", "If DealID exists in bid response, hb_deal targeting needs to be added to resp")
 }
 
 func TestVideoEndpointImpressionsDuration(t *testing.T) {
@@ -1372,7 +1373,7 @@ func (m *mockExchangeVideo) HoldAuction(ctx context.Context, r exchange.AuctionR
 	if debugLog != nil && debugLog.Enabled {
 		m.cache.called = true
 	}
-	ext := []byte(`{"prebid":{"targeting":{"hb_bidder_appnexus":"appnexus","hb_pb_appnexus":"20.00","hb_pb_cat_dur_appnex":"20.00_395_30s","hb_size":"1x1", "hb_uuid_appnexus":"837ea3b7-5598-4958-8c45-8e9ef2bf7cc1"},"type":"video","dealpriority":0,"dealtiersatisfied":false},"bidder":{"appnexus":{"brand_id":1,"auction_id":7840037870526938650,"bidder_id":2,"bid_ad_type":1,"creative_info":{"video":{"duration":30,"mimes":["video\/mp4"]}}}}}`)
+	ext := []byte(`{"prebid":{"targeting":{"hb_bidder_appnexus":"appnexus","hb_pb_appnexus":"20.00","hb_pb_cat_dur_appnex":"20.00_395_30s","hb_size":"1x1", "hb_uuid_appnexus":"837ea3b7-5598-4958-8c45-8e9ef2bf7cc1", "hb_deal_appnexus": "ABC_123"},"type":"video","dealpriority":0,"dealtiersatisfied":false},"bidder":{"appnexus":{"brand_id":1,"auction_id":7840037870526938650,"bidder_id":2,"bid_ad_type":1,"creative_info":{"video":{"duration":30,"mimes":["video\/mp4"]}}}}}`)
 	return &openrtb2.BidResponse{
 		SeatBid: []openrtb2.SeatBid{{
 			Seat: "appnexus",
diff --git a/exchange/price_granularity_test.go b/exchange/price_granularity_test.go
index 13840838..6349713e 100644
--- a/exchange/price_granularity_test.go
+++ b/exchange/price_granularity_test.go
@@ -30,6 +30,22 @@ func TestGetPriceBucketString(t *testing.T) {
 		},
 	}
 
+	custom2 := openrtb_ext.PriceGranularity{
+		Precision: 2,
+		Ranges: []openrtb_ext.GranularityRange{
+			{
+				Min:       0.0,
+				Max:       1.5,
+				Increment: 1.0,
+			},
+			{
+				Min:       1.5,
+				Max:       10.0,
+				Increment: 1.2,
+			},
+		},
+	}
+
 	// Define test cases
 	type aTest struct {
 		granularityId       string
@@ -51,6 +67,7 @@ func TestGetPriceBucketString(t *testing.T) {
 				{"auto", auto, "1.85"},
 				{"dense", dense, "1.87"},
 				{"custom1", custom1, "1.86"},
+				{"custom2", custom2, "1.50"},
 			},
 		},
 		{
@@ -63,6 +80,15 @@ func TestGetPriceBucketString(t *testing.T) {
 				{"auto", auto, "5.70"},
 				{"dense", dense, "5.70"},
 				{"custom1", custom1, "5.70"},
+				{"custom2", custom2, "5.10"},
+			},
+		},
+		{
+			groupDesc: "cpm equal the max for custom granularity",
+			cpm:       10,
+			testCases: []aTest{
+				{"custom1", custom1, "10.00"},
+				{"custom2", custom2, "9.90"},
 			},
 		},
 		{
diff --git a/exchange/targeting_test.go b/exchange/targeting_test.go
index dc91177a..12257ff4 100644
--- a/exchange/targeting_test.go
+++ b/exchange/targeting_test.go
@@ -439,6 +439,32 @@ var TargetingTests []TargetingTestData = []TargetingTestData{
 		},
 		TruncateTargetAttr: nil,
 	},
+	{
+		Description: "bidder with no dealID should not have deal targeting",
+		TargetData: targetData{
+			priceGranularity:  openrtb_ext.PriceGranularityFromString("med"),
+			includeBidderKeys: true,
+		},
+		Auction: auction{
+			winningBidsByBidder: map[string]map[openrtb_ext.BidderName]*entities.PbsOrtbBid{
+				"ImpId-1": {
+					openrtb_ext.BidderAppnexus: {
+						Bid:     bid123,
+						BidType: openrtb_ext.BidTypeBanner,
+					},
+				},
+			},
+		},
+		ExpectedBidTargetsByBidder: map[string]map[openrtb_ext.BidderName]map[string]string{
+			"ImpId-1": {
+				openrtb_ext.BidderAppnexus: {
+					"hb_bidder_appnexus": "appnexus",
+					"hb_pb_appnexus":     "1.20",
+				},
+			},
+		},
+		TruncateTargetAttr: nil,
+	},
 	{
 		Description: "Truncate Targeting Attribute value is given and is less than const MaxKeyLength",
 		TargetData: targetData{