Send a proposal

Stay organized with collections Save and categorize content based on your preferences.

Buyers can send a request for proposal (RFP) for the following deal types to start negotiations:

Only publishers can initiate private auction deals.

You can use the buyers.proposals.sendRfp method to send an RFP to a publisher.

To send a RFP, you must refer to a publisher by their PublisherProfile.

You must specify the deal type as preferredDealTerms or programmaticGuaranteedTerms in the request body. These deal types require the flightStartTime and flightEndTime fields.

Sending a RFP to a publisher creates a Proposal and starts negotiations with a publisher.

The following sample demonstrates how you can send a RFP to a publisher with the sendRfp method.

REST

Request

POST https://authorizedbuyersmarketplace.googleapis.com/v1/buyers/12345678/proposals:sendRfp?alt=json
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json

{
 "displayName": "Test PG Proposal #0ce643e9-5518-4e8e-b352-0cb45cc2eeb2",
 "publisherProfile": "buyers/12345678/publisherProfiles/PP111111",
 "buyerContacts": {
   "email": "testemail89319783@test.com",
   "displayName": "Joe"
 },
 "note": "Test programmatic guaranteed deal proposal.",
 "geoTargeting": {
   "targetedCriteriaIds": [
     "1023191"
   ]
 },
 "inventorySizeTargeting": {
   "targetedInventorySizes": [
     {
       "width": "300",
       "height": "260",
       "type": "PIXEL"
     }
   ]
 },
  "programmaticGuaranteedTerms": {
   "guaranteedLooks": 0,
   "fixedPrice": {
     "type": "CPM",
     "amount": {
       "currencyCode": "USD",
       "units": "1",
       "nanos": "500000"
     }
   },
   "minimumDailyLooks": 10000,
   "reservationType": "STANDARD",
   "impressionCap": 500000,
   "percentShareOfVoice": 40
 },
 "flightStartTime": "2022-03-27T04:03:18.939985+00:00",
 "flightEndTime": "2022-03-28T04:03:18.939985+00:00"
}

Response

{
 "name": "buyers/12345678/proposals/MP49876074",
 "updateTime": "2022-03-26T04:03:19.282Z",
 "proposalRevision": "1",
 "dealType": "PROGRAMMATIC_GUARANTEED",
 "displayName": "Test PG Proposal #0ce643e9-5518-4e8e-b352-0cb45cc2eeb2",
 "state": "SELLER_REVIEW_REQUESTED",
 "originatorRole": "BUYER",
 "publisherProfile": "buyers/12345678/publisherProfiles/PP111111",
 "buyer": "buyers/12345678",
 "billedBuyer": "buyers/12345678",
 "sellerContacts": [
   {
     "email": "jeff@hypersonicmedia.com"
   },
   {
     "email": "alex@hypersonicmedia.com"
   },
 ],
 "buyerContacts": [
   {
     "email": "testemail89319783@test.com",
     "displayName": "Joe"
   }
 ],
 "lastUpdaterOrCommentorRole": "BUYER",
  "notes": [
   {
     "createTime": "2022-03-26T04:03:19.548Z",
     "creatorRole": "BUYER",
     "note": "Test programmatic guaranteed deal proposal."
   }
 ]
}

C#

/* Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using Google.Apis.AuthorizedBuyersMarketplace.v1;
using Google.Apis.AuthorizedBuyersMarketplace.v1.Data;
using Mono.Options;

using System;
using System.Collections.Generic;

namespace Google.Apis.AuthorizedBuyersMarketplace.Examples.v1.Buyers.Proposals
{
    /// <summary>
    /// Sends a request for proposal to a publisher for a programmatic guaranteed deal.
    ///
    /// The publisher will be sent an RFP that will initiate negotiation for a programmatic
    /// guaranteed deal. For the buyer, this will create a corresponding proposal.
    ///
    /// You must refer to the publisher using their publisher profile. These can be found with the
    /// buyers.publisherProfiles resource.
    /// </summary>
    public class SendRfpForProgrammaticGuaranteedDealProposals : ExampleBase
    {
        private AuthorizedBuyersMarketplaceService mkService;

        /// <summary>
        /// Constructor.
        /// </summary>
        public SendRfpForProgrammaticGuaranteedDealProposals()
        {
            mkService = Utilities.GetAuthorizedBuyersMarketplaceService();
        }

        /// <summary>
        /// Returns a description about the code example.
        /// </summary>
        public override string Description
        {
            get => "This code example sends a request for proposal for a programmatic " +
                "guaranteed deal to a publisher for a given buyer account ID.";
        }

        /// <summary>
        /// Parse specified arguments.
        /// </summary>
        protected override Dictionary<string, object> ParseArguments(List<string> exampleArgs) {
            string[] requiredOptions = new string[] {"account_id", "buyer_contacts_display_name",
                "buyer_contacts_email", "publisher_profile_id"};
            bool showHelp = false;

            string accountId = null;
            string buyerContactsDisplayName = null;
            string buyerContactsEmail = null;
            string displayName = null;
            string publisherProfileId = null;

            OptionSet options = new OptionSet {
                "Sends a request for proposal to a publisher for the given buyer account ID.",
                {
                    "h|help",
                    "Show help message and exit.",
                    h => showHelp = h != null
                },
                {
                    "a|account_id=",
                    ("[Required] The resource ID of the buyers resource for which the RFP is " +
                     "being sent to the publisher. This will be used to construct the name used " +
                     "as a path parameter for the proposals.sendRfp request."),
                    a => accountId = a
                },
                {
                    "d|buyer_contacts_display_name=",
                    ("[Required] The display name of the buyer's contact, which will be visible " +
                     "to the publisher."),
                    d => buyerContactsDisplayName = d
                },
                {
                    "e|buyer_contacts_email=",
                    ("[Required] Email address for the buyer's contact, which will be visible " +
                     "to the publisher."),
                    e => buyerContactsEmail = e
                },
                {
                    "p|publisher_profile_id=",
                    ("[Required] The resource ID of the publisher profiles resource " +
                     "representing the publisher that the buyer wants to send the RFP."),
                    p => publisherProfileId = p
                },
                {
                    "n|display_name=",
                    ("The display name of the proposal being created by the RFP."),
                    n => displayName = n
                },
            };

            List<string> extras = options.Parse(exampleArgs);
            var parsedArgs = new Dictionary<string, object>();

            // Show help message.
            if (showHelp == true)
            {
                options.WriteOptionDescriptions(Console.Out);
                Environment.Exit(0);
            }
            // Set arguments.
            parsedArgs["account_id"] = accountId;
            parsedArgs["buyer_contacts_display_name"] = buyerContactsDisplayName;
            parsedArgs["buyer_contacts_email"] = buyerContactsEmail;
            parsedArgs["publisher_profile_id"] = publisherProfileId;
            parsedArgs["display_name"] = displayName ?? String.Format(
                "Test PG Proposal {0}",
                System.Guid.NewGuid());

            // Validate that options were set correctly.
            Utilities.ValidateOptions(options, parsedArgs, requiredOptions, extras);

            return parsedArgs;
        }

        /// <summary>
        /// Run the example.
        /// </summary>
        /// <param name="parsedArgs">Parsed arguments for the example.</param>
        protected override void Run(Dictionary<string, object> parsedArgs)
        {
            string accountId = (string) parsedArgs["account_id"];
            string publisherProfileId = (string) parsedArgs["publisher_profile_id"];
            string parent = $"buyers/{accountId}";
            string publisherProfileName =
                $"buyers/{accountId}/publisherProfiles/{publisherProfileId}";
            DateTime startTime = DateTime.Now.AddDays(1);

            SendRfpRequest rfp = new SendRfpRequest()
            {
                DisplayName = (string) parsedArgs["display_name"],
                PublisherProfile = publisherProfileName,
                Note = "Test preferred deal proposal created by C# sample.",
                // Specify start and end flight times in RFC3339 UTC "Zulu" format.
                FlightStartTime = startTime.ToUniversalTime().ToString("o"),
                FlightEndTime = startTime.AddDays(1).ToUniversalTime().ToString("o"),
                BuyerContacts = new List<Contact>()
                {
                     new Contact()
                     {
                         Email = (string) parsedArgs["buyer_contacts_email"],
                         DisplayName = (string) parsedArgs["buyer_contacts_display_name"]
                     }
                },
                GeoTargeting = new CriteriaTargeting()
                {
                    TargetedCriteriaIds = new List<long?>()
                    {
                        // Target New York, NY
                        1023191L
                    }
                },
                InventorySizeTargeting = new InventorySizeTargeting()
                {
                    TargetedInventorySizes = new List<AdSize>()
                    {
                        new AdSize()
                        {
                            Width = 300L,
                            Height = 260L,
                            Type = "PIXEL"
                        }
                    }
                },
                ProgrammaticGuaranteedTerms = new ProgrammaticGuaranteedTerms()
                {

                    GuaranteedLooks = 0,
                    MinimumDailyLooks = 0,
                    ReservationType = "STANDARD",
                    ImpressionCap = 0,
                    PercentShareOfVoice = 0,
                    FixedPrice = new Price()
                    {
                        Type = "CPM",
                        Amount = new Money()
                        {
                            CurrencyCode = "USD",
                            Units = 1,
                            Nanos = 1
                        }
                    },
                }
            };

            BuyersResource.ProposalsResource.SendRfpRequest request =
                mkService.Buyers.Proposals.SendRfp(rfp, parent);
            Proposal response = null;

            Console.WriteLine("Sending programmatic guaranteed deal RFP for buyer: {0}", parent);

            try
            {
                response = request.Execute();
            }
            catch (Exception exception)
            {
                throw new ApplicationException(
                    $"Real-time Bidding API returned error response:\n{exception.Message}");
            }

            Utilities.PrintProposal(response);
        }
    }
}

Java

/*
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.api.services.samples.authorizedbuyers.marketplace.v1.buyers.proposals;

import com.google.api.services.authorizedbuyersmarketplace.v1.AuthorizedBuyersMarketplace;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.AdSize;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.Contact;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.CriteriaTargeting;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.InventorySizeTargeting;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.Money;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.Price;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.ProgrammaticGuaranteedTerms;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.Proposal;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.SendRfpRequest;
import com.google.api.services.samples.authorizedbuyers.marketplace.Utils;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;
import org.joda.time.DateTime;
import org.joda.time.format.ISODateTimeFormat;

/**
 * Sends a request for proposal to a publisher for a programmatic guaranteed deal.
 *
 * <p>The publisher will be sent an RFP that will initiate negotiation for a programmatic guaranteed
 * deal. For the buyer, this will create a corresponding proposal.
 *
 * <p>You must refer to the publisher using their publisher profile. These can be found with the
 * buyers.publisherProfiles resource.
 */
public class SendRfpForProgrammaticGuaranteedDealProposals {

  public static void execute(AuthorizedBuyersMarketplace marketplaceClient, Namespace parsedArgs) {
    Integer accountId = parsedArgs.getInt("account_id");
    String publisherProfileId = parsedArgs.getString(("publisher_profile_id"));
    String parent = String.format("buyers/%d", accountId);
    String publisherProfileName =
        String.format("buyers/%d/publisherProfiles/%s", accountId, publisherProfileId);

    SendRfpRequest rfp = new SendRfpRequest();
    rfp.setDisplayName(parsedArgs.getString("display_name"));
    rfp.setPublisherProfile(publisherProfileName);
    rfp.setNote("Test preferred deal proposal created by Java sample.");
    // Specify the start and end flight times in RFC3339 UTC "Zulu" format.
    DateTime startTime = DateTime.now().plusDays(1);
    DateTime endTime = startTime.plusDays(1);
    rfp.setFlightStartTime(startTime.toString(ISODateTimeFormat.dateTime()));
    rfp.setFlightEndTime(endTime.toString(ISODateTimeFormat.dateTime()));

    Contact buyerContact = new Contact();
    buyerContact.setEmail(parsedArgs.getString("buyer_contacts_email"));
    buyerContact.setDisplayName((parsedArgs.getString("buyer_contacts_display_name")));
    List<Contact> buyerContacts = new ArrayList<>();
    buyerContacts.add(buyerContact);
    rfp.setBuyerContacts(buyerContacts);

    CriteriaTargeting geoTargeting = new CriteriaTargeting();
    List<Long> targetedCriteriaIds = new ArrayList<>();
    // Target New York, NY
    targetedCriteriaIds.add(1023191L);
    geoTargeting.setTargetedCriteriaIds(targetedCriteriaIds);
    rfp.setGeoTargeting(geoTargeting);

    AdSize adSize = new AdSize();
    adSize.setWidth(300L);
    adSize.setHeight(260L);
    adSize.setType("PIXEL");
    List<AdSize> targetedInventorySizes = new ArrayList<>();
    targetedInventorySizes.add(adSize);
    InventorySizeTargeting inventorySizeTargeting = new InventorySizeTargeting();
    inventorySizeTargeting.setTargetedInventorySizes(targetedInventorySizes);
    rfp.setInventorySizeTargeting(inventorySizeTargeting);

    Money fixedPriceAmount = new Money();
    fixedPriceAmount.setCurrencyCode("USD");
    fixedPriceAmount.setUnits(1L);
    fixedPriceAmount.setNanos(0);

    Price fixedPrice = new Price();
    fixedPrice.setType("CPM");
    fixedPrice.setAmount(fixedPriceAmount);

    ProgrammaticGuaranteedTerms programmaticGuaranteedTerms = new ProgrammaticGuaranteedTerms();
    programmaticGuaranteedTerms.setGuaranteedLooks(0L);
    programmaticGuaranteedTerms.setMinimumDailyLooks(0L);
    programmaticGuaranteedTerms.setReservationType("STANDARD");
    programmaticGuaranteedTerms.setImpressionCap(0L);
    programmaticGuaranteedTerms.setPercentShareOfVoice(0L);
    programmaticGuaranteedTerms.setFixedPrice(fixedPrice);
    rfp.setProgrammaticGuaranteedTerms(programmaticGuaranteedTerms);

    Proposal proposal = null;
    try {
      proposal = marketplaceClient.buyers().proposals().sendRfp(parent, rfp).execute();
    } catch (IOException ex) {
      System.out.printf("Marketplace API returned error response:%n%s", ex);
      System.exit(1);
    }

    System.out.printf(
        "Sending programmatic guaranteed deal RFP for buyer Account ID '%d':%n", accountId);
    Utils.printProposal(proposal);
  }

  public static void main(String[] args) {
    ArgumentParser parser =
        ArgumentParsers.newFor("SendRfpForProgrammaticGuaranteedDealProposals")
            .build()
            .defaultHelp(true)
            .description(
                ("Sends a request for proposal for a programmatic guaranteed deal to a "
                    + "publisher for the given buyer account ID."));
    parser
        .addArgument("-a", "--account_id")
        .help(
            "The resource ID of the buyers resource for which the RFP is being sent to the"
                + " publisher. This will be used to construct the name used as a path parameter for"
                + " the proposals.sendRfp request.")
        .required(true)
        .type(Integer.class);
    parser
        .addArgument("-d", "--buyer_contacts_display_name")
        .help("The display name of the buyer's contact, which will be visible to the publisher.")
        .required(true)
        .type(String.class);
    parser
        .addArgument("-e", "--buyer_contacts_email")
        .help("Email address for the buyer's contact, which will be visible to the publisher.")
        .required(true)
        .type(String.class);
    parser
        .addArgument("-p", "--publisher_profile_id")
        .help(
            "The resource ID of the publisher profiles resource representing the publisher "
                + "that the buyer wants to send the RFP.")
        .required(true)
        .type(String.class);
    parser
        .addArgument("-n", "--display_name")
        .help("The display name of the proposal being created by the RFP.")
        .type(String.class)
        .setDefault(String.format("Test PG Proposal %s", UUID.randomUUID()));

    Namespace parsedArgs = null;
    try {
      parsedArgs = parser.parseArgs(args);
    } catch (ArgumentParserException ex) {
      parser.handleError(ex);
      System.exit(1);
    }

    AuthorizedBuyersMarketplace client = null;
    try {
      client = Utils.getMarketplaceClient();
    } catch (IOException ex) {
      System.out.printf("Unable to create Marketplace API service:%n%s", ex);
      System.out.println("Did you specify a valid path to a service account key file?");
      System.exit(1);
    } catch (GeneralSecurityException ex) {
      System.out.printf("Unable to establish secure HttpTransport:%n%s", ex);
      System.exit(1);
    }

    execute(client, parsedArgs);
  }
}

Python

#!/usr/bin/python
#
# Copyright 2021 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Send request for proposal to a publisher for a programmatic guaranteed deal.

The publisher will be sent an RFP that will initiate negotiation for a
programmatic guaranteed deal. For the buyer, this will create a corresponding
proposal.

You must refer to the publisher using their publisher profile. These can be
found with the buyers.publisherProfiles resource.
"""


import argparse
import datetime
import os
import pprint
import sys
import uuid

sys.path.insert(0, os.path.abspath('../../..'))

from googleapiclient.errors import HttpError
import util


_BUYER_NAME_TEMPLATE = 'buyers/%s'
_PUBLISHER_PROFILE_NAME_TEMPLATE = 'buyers/%s/publisherProfiles/%s'

DEFAULT_BUYER_CONTACTS_EMAIL = 'ENTER_BUYER_CONTACTS_EMAIL_HERE'
DEFAULT_BUYER_CONTACTS_DISPLAY_NAME = 'ENTER_BUYER_CONTACTS_DISPLAY_NAME_HERE'
DEFAULT_BUYER_RESOURCE_ID = 'ENTER_BUYER_RESOURCE_ID_HERE'
DEFAULT_PUB_PROFILE_RESOURCE_ID = 'ENTER_PUB_PROFILE_RESOURCE_ID_HERE'


def main(marketplace, args):
    account_id = args.account_id
    publisher_profile_name = _PUBLISHER_PROFILE_NAME_TEMPLATE % (
        account_id, args.publisher_profile_id)

    flight_start_time = (datetime.datetime.now(datetime.timezone.utc)
                         + datetime.timedelta(days=1))
    flight_end_time = flight_start_time + datetime.timedelta(days=1)

    body = {
        'displayName': args.display_name,
        'publisherProfile': publisher_profile_name,
        'buyerContacts': {
            'email': args.buyer_contacts_email,
            'displayName': args.buyer_contacts_display_name
        },
        'note': ('Test programmatic guaranteed deal proposal created by Python '
                 'sample.'),
        'geoTargeting': {
            # New York, NY
            'targetedCriteriaIds': ['1023191']
        },
        'inventorySizeTargeting': {
            'targetedInventorySizes': [{
                'width': '300',
                'height': '260',
                'type': 'PIXEL'
            }],
        },
        'programmaticGuaranteedTerms': {
            'guaranteedLooks': 0,
            'fixedPrice': {
                'type': 'CPM',
                'amount': {
                    'currencyCode': 'USD',
                    'units': '1',
                    'nanos': '0'
                }
            },
            'minimumDailyLooks': 0,
            'reservationType': 'STANDARD',
            'impressionCap': 0,
            'percentShareOfVoice': 0
        },
        'flightStartTime': flight_start_time.isoformat(),
        'flightEndTime': flight_end_time.isoformat()
    }

    print('Sending programmatic guaranteed deal RFP on behalf of buyer account '
          f'"{account_id}" to publisher profile with name '
          f'"{publisher_profile_name}":')
    try:
        # Construct and execute the request.
        response = (marketplace.buyers().proposals().sendRfp(
            buyer=_BUYER_NAME_TEMPLATE % account_id, body=body).execute())
    except HttpError as e:
        print(e)
        sys.exit(1)

    pprint.pprint(response)


if __name__ == '__main__':
    try:
        service = util.get_service(version='v1')
    except IOError as ex:
        print(f'Unable to create marketplace service - {ex}')
        print('Did you specify the key file in util.py?')
        sys.exit(1)

    parser = argparse.ArgumentParser(
        description=('Sends a programmatic guaranteed deal RFP from a given '
                     'buyer to the specified publisher.'))
    # Required fields.
    parser.add_argument(
        '-a', '--account_id', default=DEFAULT_BUYER_RESOURCE_ID,
        help=('The resource ID of the buyers resource on behalf of which the '
              'RFP is being sent.'))
    parser.add_argument(
        '--buyer_contacts_email', default=DEFAULT_BUYER_CONTACTS_EMAIL,
        help=('Email address for the buyer\'s contact, which will be visible '
              'to the publisher.'))
    parser.add_argument(
       '--buyer_contacts_display_name',
        default=DEFAULT_BUYER_CONTACTS_DISPLAY_NAME,
        help=('The display name of the buyer\'s contact, which will be visible '
              'to the publisher.'))
    parser.add_argument(
        '-p', '--publisher_profile_id', default=DEFAULT_PUB_PROFILE_RESOURCE_ID,
        help=('The resource ID of the publisher profiles resource representing '
              'the publisher that the buyer wants to send the RFP.'))
    # Optional fields.
    parser.add_argument(
        '-n', '--display_name', default='Test PG Proposal #%s' % uuid.uuid4(),
        help='The display name of the proposal being created by the RFP.')


    main(service, parser.parse_args())