更新交易

您可以使用以下方法逐个批量更新交易。您可以在协商期间更新交易,也可以开始重新协商先前接受的提案

修补交易

您可以使用 buyers.proposals.deals.patch 方法更新与您的买方帐号或某个客户提案关联的指定交易。

您可以使用 patch 在提案的初始协商期间对其进行更改,然后重新协商已敲定的交易。

以下示例演示了如何使用 patch 方法更新交易。

REST

请求

PATCH https://authorizedbuyersmarketplace.googleapis.com/v1/buyers/12345678/proposals/MP21673270/deals/52404updateMask=flightStartTime%2CflightEndTime%2CprogrammaticGuaranteedTerms.fixedPrice.amount.units%2CprogrammaticGuaranteedTerms.fixedPrice.amount.nanos&alt=json
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json

{
 "proposalRevision": "4",
 "flightStartTime": "2037-04-02T20:15:59.584739+00:00",
 "flightEndTime": "2037-04-03T20:15:59.584739+00:00",
 "programmaticGuaranteedTerms": {
   "fixedPrice": {
     "amount": {
       "units": 1,
       "nanos": 500000000
     }
   }
 }
}

响应

{
 "name": "buyers/12345678/proposals/MP21673270/deals/52404",
 "createTime": "2036-12-27T04:02:39.731Z",
 "updateTime": "2037-03-31T20:12:40.875Z",
 "proposalRevision": "5",
 "displayName": "test_deal_7435251",
 "buyer": "buyers/12345678",
 "publisherProfile": "buyers/12345678/publisherProfiles/PP54321",
 "flightStartTime": "2037-04-02T20:12:39.038Z",
 "flightEndTime": "2037-04-03T20:12:39.038Z",
 "targeting": {
   "inventorySizeTargeting": {
     "targetedInventorySizes": [
       {
         "width": "1024",
         "height": "768",
         "type": "PIXEL"
       }
     ]
   }
 },
 "creativeRequirements": {
   "creativePreApprovalPolicy": "SELLER_PRE_APPROVAL_NOT_REQUIRED",
   "creativeSafeFrameCompatibility": "COMPATIBLE",
   "programmaticCreativeSource": "ADVERTISER",
   "creativeFormat": "DISPLAY"
 },
 "deliveryControl": {
   "deliveryRateType": "EVENLY"
 },
 "billedBuyer": "buyers/12345678",
 "dealType": "PROGRAMMATIC_GUARANTEED",
 "programmaticGuaranteedTerms": {
   "guaranteedLooks": "100",
   "fixedPrice": {
     "type": "CPM",
     "amount": {
       "currencyCode": "CNY",
       "units": "1",
       "nanos": 500000000
     }
   },
   "reservationType": "STANDARD"
 },
 "sellerTimeZone": {
   "id": "Asia/Shanghai"
 }
}

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.Deals
{
    /// <summary>
    /// Patches a programmatic guaranteed deal at the given revision number.
    ///
    /// This will modify the deal's flightStartTime, flightEndTime, and
    /// programmaticGuaranteedDealTerms.
    ///
    /// Note: If the revision number is lower than what is stored for the deal server-side, the
    /// operation will be deemed obsolete and an error will be returned.
    /// </summary>
    public class PatchProgrammaticGuaranteedDeals : ExampleBase
    {
        private AuthorizedBuyersMarketplaceService mkService;

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

        /// <summary>
        /// Returns a description about the code example.
        /// </summary>
        public override string Description
        {
            get => "This code example patches a programmatic guaranteed deal at the given " +
                "revision number.";
        }

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

            string accountId = null;
            string dealId = null;
            string proposalId = null;
            long? proposalRevision = null;
            long? fixedPriceUnits = null;
            int? fixedPriceNanos = null;
            OptionSet options = new OptionSet {
                "Patches a programmatic guaranteed deal at the given revision number.",
                {
                    "h|help",
                    "Show help message and exit.",
                    h => showHelp = h != null
                },
                {
                    "a|account_id=",
                    ("[Required] The resource ID of the buyers resource under which the deal is " +
                     "being patched. This will be used to construct the name used as a path " +
                     "parameter for the deals.patch request."),
                    a => accountId = a
                },
                {
                    "d|deal_id=",
                    ("[Required] The resource ID of the buyers.proposals.deals resource that is " +
                     "being patched. This will be used to construct the name used as a path " +
                     "parameter for the deals.patch request."),
                    d => dealId = d
                },
                {
                    "p|proposal_id=",
                    ("[Required] The resource ID of the buyers.proposals resource under which " +
                     "the deal is being patched. This will be used to construct the name used " +
                     "as a path parameter for the deals.patch request."),
                    p => proposalId = p
                },
                {
                    "r|proposal_revision=",
                    ("[Required] The revision number for the corresponding proposal of the deal " +
                     "being modified. Each update to the proposal or its deals causes the " +
                     "number to increment. The revision number specified must match the value " +
                     "stored server-side in order for the operation to be performed."),
                    (long? r) => proposalRevision = r
                },
                {
                    "u|fixed_price_units=",
                    "Whole units of the currency specified for the programmatic guaranteed deal.",
                    (long? u) => fixedPriceUnits = u
                },
                {
                    "n|fixed_price_nanos=",
                    ("Number of nano units of the currency specified for the programmatic " +
                     "guaranteed deal."),
                    (int? u) => fixedPriceNanos = u
                },
            };

            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["deal_id"] = dealId;
            parsedArgs["proposal_id"] = proposalId;
            parsedArgs["proposal_revision"] = proposalRevision;
            parsedArgs["fixed_price_units"] = fixedPriceUnits ?? 1L;
            parsedArgs["fixed_price_nanos"] = fixedPriceNanos ?? 500000000;

            // 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 dealId = (string) parsedArgs["deal_id"];
            string proposalId = (string) parsedArgs["proposal_id"];
            string name = $"buyers/{accountId}/proposals/{proposalId}/deals/{dealId}";
            long? proposalRevision = (long?) parsedArgs["proposal_revision"];
            DateTime startTime = DateTime.Now.AddDays(1);

            Deal programmaticGuaranteedDeal = new Deal()
            {
                ProposalRevision = proposalRevision,
                // Patch new start and end flight times in RFC3339 UTC "Zulu" format.
                FlightStartTime = startTime.ToUniversalTime().ToString("o"),
                FlightEndTime = startTime.AddDays(1).ToUniversalTime().ToString("o"),
                ProgrammaticGuaranteedTerms = new ProgrammaticGuaranteedTerms()
                {
                    FixedPrice = new Price()
                    {
                        Amount = new Money()
                        {
                            Units = (long?) parsedArgs["fixed_price_units"],
                            Nanos = (int?) parsedArgs["fixed_price_nanos"]
                        }
                    }
                }
            };

            string updateMask = "flightStartTime,flightEndTime," +
                "programmaticGuaranteedTerms.fixedPrice.amount.units," +
                "programmaticGuaranteedTerms.fixedPrice.amount.nanos";

            BuyersResource.ProposalsResource.DealsResource.PatchRequest request =
                mkService.Buyers.Proposals.Deals.Patch(programmaticGuaranteedDeal, name);
            request.UpdateMask = updateMask;
            Deal response = null;

            Console.WriteLine("Patching deal with name: {0}", name);

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

            Utilities.PrintDeal(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.deals;

import com.google.api.services.authorizedbuyersmarketplace.v1.AuthorizedBuyersMarketplace;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.Deal;
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.samples.authorizedbuyers.marketplace.Utils;
import java.io.IOException;
import java.security.GeneralSecurityException;
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;

/**
 * Patches a programmatic guaranteed deal at the given revision number.
 *
 * <p>This will modify the deal's flightStartTime, flightEndTime, and programmaticGuaranteedTerms.
 *
 * <p>Note: If the revision number is lower than what is stored for the deal server-side, the
 * operation will be deemed obsolete and an error will be returned.
 */
public class PatchProgrammaticGuaranteedDeals {

  public static void execute(AuthorizedBuyersMarketplace marketplaceClient, Namespace parsedArgs) {
    Long accountId = parsedArgs.getLong("account_id");
    String proposalId = parsedArgs.getString("proposal_id");
    Long dealId = parsedArgs.getLong("deal_id");
    String name = String.format("buyers/%d/proposals/%s/deals/%d", accountId, proposalId, dealId);
    Long proposalRevision = parsedArgs.getLong("proposal_revision");

    Deal patchedProgrammaticGuaranteedDeal = new Deal();
    patchedProgrammaticGuaranteedDeal.setProposalRevision(proposalRevision);

    // Patch new start and end flight times in RFC3339 UTC "Zulu" format.
    DateTime startTime = DateTime.now().plusDays(1);
    DateTime endTime = startTime.plusDays(1);
    patchedProgrammaticGuaranteedDeal.setFlightStartTime(
        startTime.toString(ISODateTimeFormat.dateTime()));
    patchedProgrammaticGuaranteedDeal.setFlightEndTime(
        endTime.toString(ISODateTimeFormat.dateTime()));

    Money fixedPriceAmount = new Money();
    fixedPriceAmount.setUnits(parsedArgs.getLong("fixed_price_units"));
    fixedPriceAmount.setNanos(parsedArgs.getInt("fixed_price_nanos"));

    Price fixedPrice = new Price();
    fixedPrice.setAmount(fixedPriceAmount);

    ProgrammaticGuaranteedTerms programmaticGuaranteedTerms = new ProgrammaticGuaranteedTerms();
    programmaticGuaranteedTerms.setFixedPrice(fixedPrice);
    patchedProgrammaticGuaranteedDeal.setProgrammaticGuaranteedTerms(programmaticGuaranteedTerms);

    String updateMask =
        "flightStartTime,flightEndTime,"
            + "programmaticGuaranteedTerms.fixedPrice.amount.units,"
            + "programmaticGuaranteedTerms.fixedPrice.amount.nanos";

    Deal deal = null;
    try {
      deal =
          marketplaceClient
              .buyers()
              .proposals()
              .deals()
              .patch(name, patchedProgrammaticGuaranteedDeal)
              .setUpdateMask(updateMask)
              .execute();
    } catch (IOException ex) {
      System.out.printf("Marketplace API returned error response:%n%s", ex);
      System.exit(1);
    }

    System.out.printf("Patching deal with name \"%s\":%n", name);
    Utils.printDeal(deal);
  }

  public static void main(String[] args) {
    ArgumentParser parser =
        ArgumentParsers.newFor("PatchProgrammaticGuaranteedDeals")
            .build()
            .defaultHelp(true)
            .description(("Patches a programmatic guaranteed deal at the given revision number."));
    parser
        .addArgument("-a", "--account_id")
        .help(
            "The resource ID of the buyers resource under which the deal is being patched. "
                + "This will be used to construct the name used as a path parameter for the "
                + "deals.patch request.")
        .required(true)
        .type(Long.class);
    parser
        .addArgument("-d", "--deal_id")
        .help(
            "The resource ID of the buyers.proposals.deals resource that is being patched. "
                + "This will be used to construct the name used as a path parameter for the "
                + "deals.patch request.")
        .required(true)
        .type(Long.class);
    parser
        .addArgument("-p", "--proposal_id")
        .help(
            "The resource ID of the buyers.proposals resource under which the deal is being"
                + " patched. This will be used to construct the name used as a path parameter for"
                + " the deals.patch request.")
        .required(true)
        .type(String.class);
    parser
        .addArgument("-r", "--proposal_revision")
        .help(
            "The revision number for the proposal being modified. Each update to the proposal "
                + "or its deals causes the number to increment. The revision number specified must "
                + "match the value stored server-side in order for the operation to be performed.")
        .required(true)
        .type(Long.class);
    parser
        .addArgument("-u", "--fixed_price_units")
        .help("Whole units of the currency specified for the programmatic guaranteed deal.")
        .type(Long.class)
        .setDefault(1L);
    parser
        .addArgument("-n", "--fixed_price_nanos")
        .help(
            "Number of nano units of the currency specified for the programmatic guaranteed "
                + "deal.")
        .type(Integer.class)
        .setDefault(500000000);

    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.

"""Patches a programmatic guaranteed deal at the given revision number.

This will modify the deal's flightStartTime, flightEndTime, and
programmaticGuaranteedDealTerms.

Note: if the revision number is lower than what is stored for the proposal
server-side, the operation will be deemed obsolete and an error will be
returned. The revision number can be found at the proposal level.
"""


import argparse
import datetime
import os
import pprint
import sys

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

from googleapiclient.errors import HttpError

import util


_DEALS_NAME_TEMPLATE = 'buyers/%s/proposals/%s/deals/%s'

DEFAULT_BUYER_RESOURCE_ID = 'ENTER_BUYER_RESOURCE_ID_HERE'
DEFAULT_PROPOSAL_RESOURCE_ID = 'ENTER_PROPOSAL_RESOURCE_ID_HERE'
DEFAULT_DEAL_RESOURCE_ID = 'ENTER_DEAL_RESOURCE_ID_HERE'


def main(marketplace, args):
    deal_name = _DEALS_NAME_TEMPLATE % (
        args.account_id, args.proposal_id, args.deal_id)

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

    body = {
        'proposalRevision': args.proposal_revision,
        'flightStartTime': flight_start_time.isoformat(),
        'flightEndTime': flight_end_time.isoformat(),
        'programmaticGuaranteedTerms': {
            'fixedPrice': {
                'amount': {
                    'units': args.fixed_price_units,
                    'nanos': args.fixed_price_nanos
                }
            }
        }
    }

    update_mask = ('flightStartTime,flightEndTime,'
                   'programmaticGuaranteedTerms.fixedPrice.amount.units,'
                   'programmaticGuaranteedTerms.fixedPrice.amount.nanos')

    print(f'Patching programmatic guaranteed deal with name "{deal_name}":')
    try:
        # Construct and execute the request.
        response = marketplace.buyers().proposals().deals().patch(
            name=deal_name, body=body, updateMask=update_mask).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=('Patch a programmatic guaranteed deal at the given '
                     'revision number.'))
    # Required fields.
    parser.add_argument(
        '-a', '--account_id', default=DEFAULT_BUYER_RESOURCE_ID,
        help=('The resource ID of the buyers resource under which the parent '
              'proposal was created. This will be used to construct the '
              'name used as a path parameter for the deals.patch request.'))
    parser.add_argument(
        '-p', '--proposal_id', default=DEFAULT_PROPOSAL_RESOURCE_ID,
        help=('The resource ID of the buyers.proposals resource for which the '
              'deal was created. This will be used to construct the '
              'name used as a path parameter for the deals.patch request.'))
    parser.add_argument(
        '-d', '--deal_id', default=DEFAULT_DEAL_RESOURCE_ID,
        help=('The resource ID of the buyers.proposals.deals resource that is '
              'being patched. This will be used to construct the name used as '
              'a path parameter for the deals.patch request.'))
    parser.add_argument(
        '-r', '--proposal_revision', required=True,
        help=('The revision number for the proposal associated with the deal '
              'being modified. Each update to the proposal or its deals causes '
              'the number to increment. The revision number specified must '
              'match the value stored server-side in order for the operation '
              'to be performed.'))
    # Optional fields.
    parser.add_argument(
        '-u', '--fixed_price_units', default=1,
        help=('Whole units of the currency specified for the programmatic '
              'guaranteed deal.'))
    parser.add_argument(
        '-n', '--fixed_price_nanos', default=500000000,
        help=('Number of nano units of the currency specified for the '
              'programmatic guaranteed deal.'))
    main(service, parser.parse_args())

批量更新交易

您可以使用 buyers.proposals.deals.batchUpdate 方法为您的买方帐号或某个客户更新与提案关联的一项或多项交易。

例如,您可以在一次 API 调用中更新提案中包含的多个交易,从而开始重新协商。

batchUpdate 方法正文中包含的交易必须具有相同的父级提案。

以下示例演示了如何使用 batchUpdate 方法更新一个或多个提案的交易。

REST

请求

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

{
 "requests": [
   {
     "deal": {
       "name": "buyers/12345678/proposals/MP21673270/deals/52404",
       "proposalRevision": "6",
       "targeting": {
         "userListTargeting": {
           "targetedCriteriaIds": [
             "111111"
           ]
         }
       }
     },
     "updateMask": "targeting.userListTargeting.targetedCriteriaIds"
   }
 ]
}

响应

{
 "deals": [
   {
     "name": "buyers/12345678/proposals/MP21673270/deals/52404",
     "createTime": "2036-12-27T04:02:39.731Z",
     "updateTime": "2037-03-31T20:33:04.773Z",
     "proposalRevision": "7",
     "displayName": "test_deal_7435251",
     "buyer": "buyers/12345678",
     "publisherProfile": "buyers/12345678/publisherProfiles/PP54321",
     "flightStartTime": "2037-04-02T20:12:39.038Z",
     "flightEndTime": "2037-04-03T20:12:39.038Z",
     "targeting": {
       "inventorySizeTargeting": {
         "targetedInventorySizes": [
           {
             "width": "1024",
             "height": "768",
             "type": "PIXEL"
           }
         ]
       },
        "userListTargeting": {
         "targetedCriteriaIds": [
           "111111"
         ]
       }
     },
     "creativeRequirements": {
       "creativePreApprovalPolicy": "SELLER_PRE_APPROVAL_NOT_REQUIRED",
       "creativeSafeFrameCompatibility": "COMPATIBLE",
       "programmaticCreativeSource": "ADVERTISER",
       "creativeFormat": "DISPLAY"
     },
     "deliveryControl": {
         "deliveryRateType": "EVENLY"
     },
     "billedBuyer": "buyers/12345678",
     "dealType": "PROGRAMMATIC_GUARANTEED",
     "programmaticGuaranteedTerms": {
       "guaranteedLooks": "100",
       "fixedPrice": {
         "type": "CPM",
         "amount": {
           "currencyCode": "CNY",
           "units": "1",
           "nanos": 500000000
         }
       },
       "reservationType": "STANDARD"
     },
     "sellerTimeZone": {
       "id": "Asia/Shanghai"
     }
   }
 ]
}

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.Deals
{
    /// <summary>
    /// Patches the user list targeting of one or more deals for the given buyer's proposal.
    ///
    /// This operation requires that the deals all exist under the same proposal.
    ///
    /// The user list targeting of the given deals will be modified to target the specified
    /// user lists. User lists can be retrieved via the Real-time Bidding API's
    /// buyers.userLists resource. You can learn more about buyers.userLists in the reference
    /// documentation:
    /// https://developers.google.com/authorized-buyers/apis/realtimebidding/reference/rest/v1/buyers.userLists
    ///
    /// Note: Only preferred and programmatic guaranteed deals can be modified by the buyer;
    /// attempting to modify a private auction deal will result in an error response.
    /// </summary>
    public class BatchUpdateDeals : ExampleBase
    {
        private AuthorizedBuyersMarketplaceService mkService;

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

        /// <summary>
        /// Returns a description about the code example.
        /// </summary>
        public override string Description
        {
            get => "This code example patches the user list targeting of one or more deals for " +
                "the given buyer's proposal.";
        }

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

            string accountId = null;
            IList<string> dealIds = new List<string>();
            string proposalId = null;
            long? proposalRevision = null;
            IList<long?> userListIds = new List<long?>();

            OptionSet options = new OptionSet {
                "Patches the user list targeting of one or more deals for the given buyer's " +
                "proposal.",
                {
                    "h|help",
                    "Show help message and exit.",
                    h => showHelp = h != null
                },
                {
                    "a|account_id=",
                    ("[Required] The resource ID of the buyers resource under which one or more " +
                     "deals are being patched. This will be used to construct the proposal " +
                     "name used as a path parameter for the deals.batchUpdate request, and each " +
                     "deal name included in the request body."),
                    a => accountId = a
                },
                {
                    "d|deal_id=",
                    ("[Required] The resource ID of one or more buyers.proposals.deals " +
                     "resources that will be patch in a batch update operation. These will be " +
                     "used to construct the deal names included in the request body. Specify " +
                     "this argument for each deal you intend to patch with this example."),
                    d => dealIds.Add(d)
                },
                {
                    "p|proposal_id=",
                    ("[Required] The resource ID of the buyers.proposals resource under which " +
                     "one or more deals are being patched. This will be used to construct the " +
                     "name used as a path parameter for the deals.batchUpdate request, and each " +
                     "deal name included in the request body."),
                    p => proposalId = p
                },
                {
                    "r|proposal_revision=",
                    ("[Required] The revision number for the corresponding proposal of the " +
                     "deals being modified. Each update to the proposal or its deals causes the " +
                     "number to increment. The revision number specified must match the value " +
                     "stored server-side in order for the operation to be performed."),
                    (long? r) => proposalRevision = r
                },
                {
                    "u|user_list_id=",
                    ("[Required] The resource ID of one or more buyers.userLists resources that " +
                     "are to be targeted by the given deals. Specify this argument for each " +
                     "user list you intend to target."),
                    (long? u) => userListIds.Add(u)
                },
            };

            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["deal_ids"] = dealIds;
            parsedArgs["proposal_id"] = proposalId;
            parsedArgs["proposal_revision"] = proposalRevision;
            parsedArgs["user_list_ids"] = userListIds.Count > 0 ? userListIds : null;

            // 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"];
            IList<string> dealIds = (List<string>) parsedArgs["deal_ids"];
            string proposalId = (string) parsedArgs["proposal_id"];
            string parent = $"buyers/{accountId}/proposals/{proposalId}";
            long? proposalRevision = (long?) parsedArgs["proposal_revision"];
            IList<long?> userListIds = (List<long?>) parsedArgs["user_list_ids"];

            IList<UpdateDealRequest> updateDealRequests = new List<UpdateDealRequest>();

            // Populate the request body based on the deals specified.
            foreach (string dealId in dealIds)
            {
                UpdateDealRequest updateDealRequest = new UpdateDealRequest()
                {
                    Deal = new Deal()
                    {
                        Name = $"buyers/{accountId}/proposals/{proposalId}/deals/{dealId}",
                        ProposalRevision = proposalRevision,
                        Targeting = new MarketplaceTargeting()
                        {
                            UserListTargeting = new CriteriaTargeting()
                            {
                                TargetedCriteriaIds = userListIds
                            }
                        }
                    },
                    UpdateMask = "targeting.userListTargeting.targetedCriteriaIds"
                };

                updateDealRequests.Add(updateDealRequest);
            }

            BatchUpdateDealsRequest batchUpdateDealsRequest = new BatchUpdateDealsRequest()
            {
                Requests = updateDealRequests
            };

            BuyersResource.ProposalsResource.DealsResource.BatchUpdateRequest request =
                mkService.Buyers.Proposals.Deals.BatchUpdate(batchUpdateDealsRequest, parent);
            BatchUpdateDealsResponse response = null;

            Console.WriteLine("Batch updating deals for proposal with name: {0}", parent);

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

            foreach (Deal deal in response.Deals)
            {
                Utilities.PrintDeal(deal);
            }
        }
    }
}

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.deals;

import com.google.api.services.authorizedbuyersmarketplace.v1.AuthorizedBuyersMarketplace;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.BatchUpdateDealsRequest;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.BatchUpdateDealsResponse;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.CriteriaTargeting;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.Deal;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.MarketplaceTargeting;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.UpdateDealRequest;
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 net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;

/**
 * Patches the user list targeting of one or more deals for the given buyer's proposal.
 *
 * <p>This operation requires that the deals all exist under the same proposal.
 *
 * <p>The user list targeting of the given deals will be modified to target the specified user
 * lists. User lists can be retrieved via the Real-time Bidding API's buyers.userLists resource. You
 * can learn more about buyers.userLists in the reference documentation:
 * https://developers.google.com/authorized-buyers/apis/realtimebidding/reference/rest/v1/buyers.userLists
 *
 * <p>Note: Only preferred and programmatic guaranteed deals can be modified by the buyer;
 * attempting to modify a private auction deal will result in an error response.
 */
public class BatchUpdateDeals {

  public static void execute(AuthorizedBuyersMarketplace marketplaceClient, Namespace parsedArgs) {
    Long accountId = parsedArgs.getLong("account_id");
    List<Long> dealIds = parsedArgs.getList("deal_ids");
    String proposalId = parsedArgs.getString("proposal_id");
    String parent = String.format("buyers/%d/proposals/%s", accountId, proposalId);
    Long proposalRevision = parsedArgs.getLong("proposal_revision");
    List<Long> userListIds = parsedArgs.getList("user_list_ids");

    List<UpdateDealRequest> updateDealRequests = new ArrayList<>();

    // Populate the request body based on the deals specified.
    for (Long dealId : dealIds) {
      Deal deal = new Deal();
      deal.setName(String.format("buyers/%d/proposals/%s/deals/%d", accountId, proposalId, dealId));
      deal.setProposalRevision(proposalRevision);

      CriteriaTargeting userListTargeting = new CriteriaTargeting();
      userListTargeting.setTargetedCriteriaIds(userListIds);

      MarketplaceTargeting marketplaceTargeting = new MarketplaceTargeting();
      marketplaceTargeting.setUserListTargeting(userListTargeting);
      deal.setTargeting(marketplaceTargeting);

      UpdateDealRequest updateDealRequest = new UpdateDealRequest();
      updateDealRequest.setDeal(deal);
      updateDealRequest.setUpdateMask("targeting.userListTargeting.targetedCriteriaIds");

      updateDealRequests.add(updateDealRequest);
    }

    BatchUpdateDealsRequest batchUpdateDealsRequest = new BatchUpdateDealsRequest();
    batchUpdateDealsRequest.setRequests(updateDealRequests);

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

    System.out.printf("Batch updating deals for proposal with name \"%s\":%n", parent);

    for (Deal deal : response.getDeals()) {
      Utils.printDeal(deal);
    }
  }

  public static void main(String[] args) {
    ArgumentParser parser =
        ArgumentParsers.newFor("BatchUpdateDeals")
            .build()
            .defaultHelp(true)
            .description(
                ("Patches the user list targeting of one or more deals for the given "
                    + "buyer's proposal."));
    parser
        .addArgument("-a", "--account_id")
        .help(
            "The resource ID of the buyers resource under which one or more deals are being"
                + " patched. This will be used to construct the proposal name used as a path"
                + " parameter for the deals.batchUpdate request, and each deal name included in the"
                + " request body.")
        .required(true)
        .type(Long.class);
    parser
        .addArgument("-d", "--deal_ids")
        .help(
            "The resource ID of one or more buyers.proposals.deals resources that will be patched"
                + " in a batch update operation. These will be used to construct the deal names"
                + " included in the request body. Specify each client ID separated by a space.")
        .required(true)
        .type(Long.class)
        .nargs("+");
    parser
        .addArgument("-p", "--proposal_id")
        .help(
            "The resource ID of the buyers.proposals resource under which one or more deals is"
                + " being patched. This will be used to construct the name used as a path parameter"
                + " for the deals.batchUpdate request, and each deal name included in the request"
                + " body")
        .required(true);
    parser
        .addArgument("-r", "--proposal_revision")
        .help(
            "The revision number for the corresponding proposal of the deals being modified. Each"
                + " update to the proposal or its deals causes the number to increment. The"
                + " revision number specified must match the value stored server-side in order for"
                + " the operation to be performed.")
        .required(true)
        .type(Long.class);
    parser
        .addArgument("-u", "--user_list_ids")
        .help(
            "The resource ID of one or more buyers.userLists resources that are to be targeted "
                + "by the given deals. Specify each client ID separated by a space.")
        .required(true)
        .type(Long.class)
        .nargs("+");

    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.

"""Patch the user list targeting of one or more deals for the given proposal.

This operation requires that the deals all exist under the same proposal.

The user list targeting of the given deals will be modified to target the
specified user lists. User lists can be retrieved via the Real-time Bidding
API's buyers.userLists resource. You can learn more about buyers.userLists in
the reference documentation:
https://developers.google.com/authorized-buyers/apis/realtimebidding/reference/rest/v1/buyers.userLists

Note: Only preferred and programmatic guaranteed deals an be modified by the
buyer; attempting to modify a private auction deal will result in an error
response.
"""


import argparse
import os
import pprint
import sys

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

from googleapiclient.errors import HttpError

import util


_PROPOSALS_NAME_TEMPLATE = 'buyers/%s/proposals/%s'
_DEALS_NAME_TEMPLATE = 'buyers/%s/proposals/%s/deals/%s'


DEFAULT_BUYER_RESOURCE_ID = 'ENTER_BUYER_RESOURCE_ID_HERE'
DEFAULT_PROPOSAL_RESOURCE_ID = 'ENTER_PROPOSAL_RESOURCE_ID_HERE'


def main(marketplace, args):
    account_id = args.account_id
    proposal_id = args.proposal_id
    proposal_name = _PROPOSALS_NAME_TEMPLATE % (account_id, proposal_id)

    # This will create a update deal request for each given deal for the
    # specified proposal revision. Each request will patch userListTargeting
    # for the deal such that the given user list IDs are targeted.
    body = {
        'requests': [{
            'deal': {
                'name': _DEALS_NAME_TEMPLATE % (
                    account_id, proposal_id, deal_id),
                'proposalRevision': args.proposal_revision,
                'targeting': {
                    'userListTargeting': {
                        'targetedCriteriaIds': [
                            user_list_id for user_list_id in args.user_list_ids]
                    }
                },
            },
            'updateMask': 'targeting.userListTargeting.targetedCriteriaIds'
        } for deal_id in args.deal_ids],
    }

    print(f'Batch updating deals for proposal "{proposal_name}":')
    try:
        # Construct and execute the request.
        response = marketplace.buyers().proposals().deals().batchUpdate(
            parent=proposal_name, 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=('Batch update user list targeting for multiple deals '
                     'associated with a given buyer\'s proposal.'))
    # Required fields.
    parser.add_argument(
        '-a', '--account_id', default=DEFAULT_BUYER_RESOURCE_ID,
        help=('The resource ID of the buyers resource under which the '
              'proposal was created. This will be used to construct the '
              'name used as a path parameter for the deals.batchUpdate '
              'request.'))
    parser.add_argument(
        '-p', '--proposal_id', default=DEFAULT_PROPOSAL_RESOURCE_ID,
        help=('The resource ID of the buyers.proposals resource under which '
              'one or more deals were created. This will be used to construct '
              'the name used as a path parameter for the deals.batchUpdate '
              'request.'))
    parser.add_argument(
        '-d', '--deal_ids', required=True, nargs='+',
        help=('One or more resource IDs for the buyers.proposals.deals '
              'resource that will be patched in a batch update operation. This '
              'will be used to construct the deal name that is included in the '
              'update request for each deal in the deals.batchUpdate request.'))
    parser.add_argument(
        '-r', '--proposal_revision', required=True,
        help=('The revision number for the proposal associated with the deals '
              'being modified. Each update to the proposal or its deals causes '
              'the number to increment. The revision number specified must '
              'match the value stored server-side in order for the operation '
              'to be performed.'))
    parser.add_argument(
        '-u', '--user_list_ids', nargs='+',
        help=('One or more resource IDs for the buyers.userLists resources '
              'that are to be targeted by the given deals. Specify each user '
              'list ID separated by a space.'))

    main(service, parser.parse_args())