Ad Exchange Marketplace

Ad Exchange Marketplace offers a way for you to quickly and easily discover inventory opportunities and make deals programmatically with Ad Exchange publishers.

The Marketplace API resources are a subset of the resources available in the AdX Buyer API:

Terms used

PRODUCT (aka Offer) A pre-packaged segment of inventory that a seller has made available in the marketplace. A product typically has a description of the inventory and any associated terms (such as desired cpm, targeting information).
PROPOSAL (aka Order) This is the unit of negotiation between the buyer and the seller. A Proposal contains a collection of deals which are negotiated together as one entity. The process of negotiation may change the specified terms of an included deal. Once a proposal is "finalized", each included deal is ready for serving.
DEAL Deals start out as copies of products. The terms of the deal are used to serve ads. A deal can be any supported deal type on AdX preferred deals, private auctions, and (in the future) programmatic guaranteed. A deal is ready to serve when the proposal containing it is finalized.
BUYER / BIDDER The DSP that is buying the inventory.
SELLER The publisher that wishes to sell the inventory.
CHILD SEAT Account that bids via a bidder.
CLIENT ACCOUNT Agency or advertiser account.

Sample workflow

To get started with Marketplace, just follow this workflow example.

  • A buyer starts by querying for all products visible to the buyer. Once the desired products are found, the buyer creates a proposal that contains one or more products from the same seller.

  • The buyer can make desired changes to the terms of the product and send the proposal to the seller. For Preferred Deals, the buyer and seller then go back and forth negotiating the terms of the deal. For Private Auction deals the buyer directly accepts the proposal. For both deal types, the buyer will periodically have to poll the list of proposals to see if there has been a seller update.

  • Once the seller responds, the buyer can either accept the Proposal or propose more changes (for Preferred Deals). Once both sides have accepted a Proposal, the Proposal is deemed Finalized and the deals are ready for serving.

Buyer discovers available products

To discover products available to the buyer, the buyer issues an HTTP GET request and gets a list of Products in return.

Request:

GET https://www.googleapis.com/adexchangebuyer/v1.4/products/search

Response:

{
  "products": [
    {
      "kind": "adexchangebuyer#product",
      "terms": {
        "nonGuaranteedFixedPriceTerms": {
          "fixedPrices": [
            {
              "price": {
                "currencyCode": "USD",
                "amountMicros": 500000000.0
              }
            }
          ]
        }
      },
      "name": "TestOffer_PD_0001",
      "flightEndTimeMs": "1428530848286",
      "sharedTargetings": [
        {
          "inclusions": [
            {
              "creativeSizeValue": {
                "creativeSizeType": "regular",
                "size": {
                  "width": 728,
                  "height": 90
                }
              }
            }
          ],
          "key": "GOOG_CREATIVE_SIZE"
        }
      ],
      "productId": "MP111111",
      "seller": {
        "accountId": "<sellerAccountId>"
      },
      "webPropertyCode": "ca-pub-1111111111111111",
      "state": "published",
      "flightStartTimeMs": "1427900814806",
      "hasCreatorSignedOff": false,
      "creationTimeMs": "1452278371399",
      "lastUpdateTimeMs": "1452278371399",
      "revisionNumber": "1"
    }, ….
}

Each product has targeting parameters specified in the sharedTargetings field and pricing terms included in terms. For Preferred Deals, nonGuaranteedFixedPriceTerms will be populated and for Private Auctions nonGuaranteedAuctionTerms will be populated.

Buyer creates proposal based on products from a publisher

Once the buyer likes product(s) from a given publisher, they can create and send a new proposal to the seller. For the running example, let's say the buyer likes the product listed in the HTTP response above. Creating a proposal is a two step process. First, the buyer creates the proposal and then adds copies of the products to the proposal.

Create the proposal

Request:

POST /adexchangebuyer/v1.4/proposals/insert HTTP/1.1
Content-type: application/json

{
  "proposals": [
    {
      "seller": {
        "accountId": "<sellerAccountId>"
      },
      "name": "Test_PD_Proposal_001",
      "orderState": "proposed",
      "buyer": {
        "accountId": "<buyerAccountId>"
      }
    }
  ]
}

Response:

{
  "proposals": [
    {
      "proposalId": "MP12345",
      "kind": "adexchangebuyer#proposal",
      "name": "Test_PD_Proposal_001",
      "revisionTimeMs": "1452280426065",
      "billedBuyer": {
        "accountId": "<buyerAccountId>"
      },
      "originatorRole": "buyer",
      "seller": {
        "accountId": "<sellerAccountId>"
      },
      "lastUpdaterRole": "buyer",
      "proposalState": "proposed",
      "hasSellerSignedOff": false,
      "isRenegotiating": false,
      "buyer": {
        "accountId": "<buyerAccountId>"
      },
      "hasBuyerSignedOff": false,
      "isSetupComplete": false,
      "revisionNumber": "1",
      "lastUpdaterOrCommentorRole": "buyer"
    }
  ]
}

The set of fields specified in this request is the minimum required to create a proposal. More fields may be specified as desired. Once the proposal is successfully created, the response contains the newly created proposal along with the assigned orderId. The response also contains the revisionNumber of the proposal which must be used in subsequent requests to update the proposal.

It is possible to specify multiple proposals in the create request (targeting different sellers). The response will only contain the proposals that were successfully created, so it's a good idea to specify a reference number in buyerPrivateData. This reference number can be used to match successful proposals to those that were requested.

Add a copy of the product to the proposal.

Request:

POST /adexchangebuyer/v1.4/proposals/MP12345/deals/insert HTTP/1.1
Content-type: application/json

{
  "proposalId": "MP12345",
  "proposalRevisionNumber": 1,
  "deals": [
    {
      "terms": {
        "nonGuaranteedFixedPriceTerms": {
          "fixedPrices": [
            {
              "price": {
                "currencyCode": "USD",
                "amountMicros": 500000000.0
              }
            }
          ]
        }
      },
      "name": "TestOffer_PD_001",
      "sharedTargetings": [
        {
          "inclusions": [
            {
              "creativeSizeValue": {
                "creativeSizeType": "regular",
                "size": {
                  "width": 728,
                  "height": 90
                }
              }
            }
          ],
          "key": "GOOG_CREATIVE_SIZE"
        }
      ],
      "productId": "MP111111",
      "webPropertyCode": "ca-pub-1111111111111111",
      "flightEndTimeMs": "1428530848286",
      "flightStartTimeMs": "1427900814806"
    }
  ]
}

Response:

{
  "deals": [
    {
      "proposalId": "MP12345",
      "kind": "adexchangebuyer#marketplaceDeal",
      "terms": {
        "nonGuaranteedFixedPriceTerms": {
          "fixedPrices": [
            {
              "price": {
                "currencyCode": "USD",
                "amountMicros": 500000000.0
              }
            }
          ]
        }
      },
      "name": "TestOffer_PD_001",
      "flightEndTimeMs": "1428530848286",
      "sharedTargetings": [
        {
          "inclusions": [
            {
              "creativeSizeValue": {
                "creativeSizeType": "regular",
                "size": {
                  "width": 728,
                  "height": 90
                }
              }
            }
          ],
          "key": "GOOG_CREATIVE_SIZE"
        }
      ],
      "productId": "MP111111",
      "dealId": "MP29432",
      "webPropertyCode": "ca-pub-1111111111111111",
      "flightStartTimeMs": "1427900814806",
      "creationTimeMs": "1452283226128",
      "lastUpdateTimeMs": "1452283226128",
      "externalDealId": "8898",
      "inventoryDescription": ""
    }
  ]
}

The deals field in the request is mostly a copy of the fields from the product. Similarly the response simply echoes back the successfully created deal. The externalDealId field is the dealId to provide to trafficking so that ads can be served against it. This ID won't be usable until the deal is finalized (as shown below).

The revision number helps ensure that the buyer and the seller don't step on each other's changes. The API will return with an error if the revision number specified in the request is not the same as the latest revision number on the proposal in marketplace.

{
  "error": {
    "code": 500,
    "message": "Revision mismatch: current revision: 2, requested revision: 1",
    "errors": [
      {
        "message": "Revision mismatch: current revision: 2, requested revision: 1"
      }
    ]
  }
}

In this case, the buyer should reload the proposal as shown below, before retrying the operation.

Request:

GET /adexchangebuyer/v1.4/proposals/MP12345 HTTP/1.1

Buyer polls proposal to see if the seller has updated it

Using the endpoint below, the buyer can periodically poll to see if the seller has updated the proposal. Once the seller updates the proposal, the revisionNumber will change. The lastUpdaterRole in the response will tell the buyer if it was the buyer or the seller that made the last update.

Request:

GET /adexchangebuyer/v1.4/proposals/MP12345 HTTP/1.1

Buyer updates terms of the deal

Let's say the buyer is now synced to the latest revision of the proposal and wants to propose some changes to the terms of a deal. Say the buyer wants to update the CPM in our example deal from $500 to $400. The buyer would issue the following request:

Request:

POST /adexchangebuyer/v1.4/proposals/MP12345/deals/update HTTP/1.1
Content-type: application/json

{
  "proposalId": "MP12345",
  "orderRevisionNumber": 2,
  "deals": [
    {
      "terms": {
        "nonGuaranteedFixedPriceTerms": {
          "fixedPrices": [
            {
              "price": {
                "currencyCode": "USD",
                "amountMicros": 400000000.0
              }
            }
          ]
        }
      },
      "name": "TestOffer_PD_001",
      "sharedTargetings": [
        {
          "inclusions": [
            {
              "creativeSizeValue": {
                "creativeSizeType": "regular",
                "size": {
                  "width": 728,
                  "height": 90
                }
              }
            }
          ],
          "key": "GOOG_CREATIVE_SIZE"
        }
      ],
      "productId": "MP111111",
      "webPropertyCode": "ca-pub-11111111111111111",
      "flightEndTimeMs": "1428530848286",
      "flightStartTimeMs": "1427900814806"
    }
  ]
}

Response:

{
  "deals": [
    {
      "proposalId": "MP12345",
      "kind": "adexchangebuyer#marketplaceDeal",
      "terms": {
        "nonGuaranteedFixedPriceTerms": {
          "fixedPrices": [
            {
              "price": {
                "currencyCode": "USD",
                "amountMicros": 400000000.0
              }
            }
          ]
        }
      },
      "name": "TestOffer_PD_001",
      "flightEndTimeMs": "1428530848286",
      "sharedTargetings": [
        {
          "inclusions": [
            {
              "creativeSizeValue": {
                "creativeSizeType": "regular",
                "size": {
                  "width": 728,
                  "height": 90
                }
              }
            }
          ],
          "key": "GOOG_CREATIVE_SIZE"
        }
      ],
      "productId": "MP111111",
      "dealId": "MP49974",
      "webPropertyCode": "ca-pub-1111111111111111",
      "flightStartTimeMs": "1427900814806",
      "creationTimeMs": "1452284573597",
      "lastUpdateTimeMs": "1452284573597",
      "externalDealId": "8552",
      "inventoryDescription": ""
    }
  ]
}

The request contains all the buyer-updatable fields of a deal, even though we just wanted to update the CPM. This allows the buyer to change/remove fields of a deal with ease. The request is very similar to the request for adding a deal to a proposal.

Buyer accepts the deal

Either the buyer or the seller can first accept the terms of a proposal. Once the seller accepts the proposal, the hasSellerSignedOff bit on the proposal is set to true. Once the buyer accepts the proposal, the hasBuyerSignedOff bit is set to true. Once both parties accept the proposal, the proposal is FINALIZED and the deals are ready for serving.

Let's say for our example, the seller first accepts the proposal.

Seller accepts the proposal

Querying for the proposal will return a response similar to the following:

Request:

GET /adexchangebuyer/v1.4/proposals/MP12345 HTTP/1.1

Response:

{
  "proposalId": "MP12345",
  "kind": "adexchangebuyer#proposal",
  "name": "Test_PD_001_offer",
  "revisionTimeMs": "1452284971992",
  "billedBuyer": {
    "accountId": "53780044"
  },
  "originatorRole": "buyer",
  "seller": {
    "accountId": "70649306"
  },
  "lastUpdaterRole": "seller",
  "proposalState": "accepted",
  "hasSellerSignedOff": true,
  "isRenegotiating": false,
  "buyer": {
    "accountId": "53780044"
  },
  "hasBuyerSignedOff": false,
  "isSetupComplete": false,
  "revisionNumber": "4",
  "lastUpdaterOrCommentorRole": "seller"
}

Buyer accepts the proposal.

The orderState is now ACCEPTED and the hasSellerSignedOff bit is true. In order to accept the proposal, the buyer now issues the following command.

Request:

PATCH /adexchangebuyer/v1.4/proposals/MP12345/4/ACCEPT HTTP/1.1
Content-type: application/json

{
  "name":  "Test_PD_001_offer",
  "proposalState": "accepted"
}

Response:

{
  "proposalId": "MP12345",
  "kind": "adexchangebuyer#proposal",
  "name": "Test_PD_001_offer",
  "revisionTimeMs": "1452285407620",
  "billedBuyer": {
    "accountId": "53780044"
  },
  "originatorRole": "buyer",
  "seller": {
    "accountId": "70649306"
  },
  "lastUpdaterRole": "buyer",
  "proposalState": "finalized",
  "hasSellerSignedOff": true,
  "isRenegotiating": false,
  "buyer": {
    "accountId": "53780044"
  },
  "hasBuyerSignedOff": true,
  "isSetupComplete": false,
  "revisionNumber": "5",
  "lastUpdaterOrCommentorRole": "buyer"
}

The proposal ID, revision number, and update action (ACCEPT) are all specified as part of the URL path. The body of the PATCH request contains just the name and existing state of the order.

The response shows that the offer was signed off on by both parties and the offer is now finalized and ready for serving (once creatives are uploaded).

Buyer uploads creative and calls setupcomplete

Request:

POST /adexchangebuyer/v1.4/proposals/MP12345/setupcomplete HTTP/1.1

This method is called with an empty post body.

Searching for finalized deals

Searching for finalized deals is a two step process. First you need to run a PQL query to search for all of the proposals in a finalized state, then for all the deals associated with these proposals.

List of finalized proposals

Request:

GET
/adexchangebuyer/v1.4/proposals/search?pqlQuery=where+proposalState+%3D+'finalized'
HTTP/1.1

This returns only those proposals that are finalized. To get the list of all the deals for a proposal, issue the following request:

Finalized deals for a proposal

Request:

GET /adexchangebuyer/v1.4/proposals/MP12345/deals HTTP/1.1

This returns all the deals for a given proposal.

Send feedback about...

Buyer REST API
Buyer REST API