Edit proposals

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

You can use the following methods to edit existing proposals for your buyer account and any of your clients.

Patch

You can use the buyers.proposals.patch method to update a given proposal.

You can use this method to make changes to a proposal during negotiation, or to begin renegotiation of a finalized proposal.

You can't change proposal’s state with patch.

See the following for more ways to modify a proposal:

The following sample demonstrates how you can update a proposal with the patch method.

REST

Request

PATCH https://authorizedbuyersmarketplace.googleapis.com/v1/buyers/12345678/proposals/MP49876074?updateMask=buyerPrivateData.referenceId&alt=json
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json

{
 "proposalRevision": "1",
 "buyerPrivateData": {
   "referenceId": "2f5e9550-8d22-495e-ba38-9b9496347a3b"
 }
}

Response

{
 "name": "buyers/12345678/proposals/MP49876074",
 "updateTime": "2022-03-26T04:03:19.282Z",
 "proposalRevision": "2",
 "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",
 "buyerPrivateData": {
   "referenceId": "2f5e9550-8d22-495e-ba38-9b9496347a3b"
 },
 "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>
    /// Patches a specified proposal at the given revision number.
    ///
    /// Fields that can be patched for this resource can be found in the reference documentation:
    /// https://developers.google.com/authorized-buyers/apis/marketplace/reference/rest/v1/buyers.proposals
    ///
    /// 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.
    ///
    /// Only proposals for preferred and programmatic guaranteed deals can be modified by buyers.
    /// </summary>
    public class PatchProposals : ExampleBase
    {
        private AuthorizedBuyersMarketplaceService mkService;

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

        /// <summary>
        /// Returns a description about the code example.
        /// </summary>
        public override string Description
        {
            get => "This code example patches a proposal 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",
                "proposal_revision"};
            bool showHelp = false;

            string accountId = null;
            string proposalId = null;
            long? proposalRevision = null;
            OptionSet options = new OptionSet {
                "Patches a proposal 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 for which the RFP is " +
                     "being patched. This will be used to construct the name used as a path " +
                     "parameter for the proposals.patch request."),
                    a => accountId = a
                },
                {
                    "p|proposal_id=",
                    ("[Required] The resource ID of the proposals resource that is being " +
                     "patched. This will be used to construct the name used as a path parameter " +
                     "for the proposals.patch request."),
                    d => proposalId = d
                },
                {
                    "r|proposal_revision=",
                    ("[Required] 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."),
                    (long? r) => proposalRevision = r
                },
            };

            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["proposal_id"] = proposalId;
            parsedArgs["proposal_revision"] = proposalRevision;

            // 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 proposalId = (string) parsedArgs["proposal_id"];
            string name = $"buyers/{accountId}/proposals/{proposalId}";
            long? proposalRevision = (long?) parsedArgs["proposal_revision"];

            Proposal proposal = new Proposal()
            {
                ProposalRevision = proposalRevision,
                BuyerPrivateData = new PrivateData
                {
                    ReferenceId = $"Marketplace-C#-Sample-Reference-{System.Guid.NewGuid()}"
                }
            };

            string updateMask = "buyerPrivateData.referenceId";

            BuyersResource.ProposalsResource.PatchRequest request =
                mkService.Buyers.Proposals.Patch(proposal, name);
            request.UpdateMask = updateMask;
            Proposal response = null;

            Console.WriteLine("Patching proposal 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.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.PrivateData;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.Proposal;
import com.google.api.services.samples.authorizedbuyers.marketplace.Utils;
import java.io.IOException;
import java.security.GeneralSecurityException;
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;

/**
 * Patches a specified proposal at the given revision number.
 *
 * <p>Fields that can be patched for this resource can be found in the reference documentation:
 * https://developers.google.com/authorized-buyers/apis/marketplace/reference/rest/v1/buyers.proposals
 *
 * <p>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.
 *
 * <p>Only proposals for preferred and programmatic guaranteed deals can be modified by buyers.
 */
public class PatchProposals {

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

    PrivateData buyerPrivateData = new PrivateData();
    buyerPrivateData.setReferenceId(
        String.format("Marketplace-Java-Sample-Reference-%s", UUID.randomUUID()));

    Proposal patchedProposal = new Proposal();
    patchedProposal.setProposalRevision(proposalRevision);
    patchedProposal.setBuyerPrivateData(buyerPrivateData);

    String updateMask = "buyerPrivateData.referenceId";

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

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

  public static void main(String[] args) {
    ArgumentParser parser =
        ArgumentParsers.newFor("PatchProposals")
            .build()
            .defaultHelp(true)
            .description(("Patches a proposal at the given revision number."));
    parser
        .addArgument("-a", "--account_id")
        .help(
            "The resource ID of the buyers resource for which the RFP is being patched. This "
                + "will be used to construct the name used as a path parameter for the "
                + "proposals.patch request.")
        .required(true)
        .type(Integer.class);
    parser
        .addArgument("-p", "--proposal_id")
        .help(
            "The resource ID of the proposals resource that is being patched. This will be used to"
                + " construct the name used as a path parameter for the proposals.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);

    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 specified proposal at the given revision number.

Fields that can be patched for this resource can be found in the reference
documentation:
https://developers.google.com/authorized-buyers/apis/marketplace/reference/rest/v1/buyers.proposals

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.

Only proposals for preferred and programmatic guaranteed deals can be modified
by buyers.
"""


import argparse
import os
import pprint
import sys
import uuid

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

from googleapiclient.errors import HttpError

import util


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

DEFAULT_BUYER_RESOURCE_ID = 'ENTER_BUYER_RESOURCE_ID_HERE'
DEFAULT_PROPOSAL_RESOURCE_ID = 'ENTER_PROPOSAL_RESOURCE_ID_HERE'


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

    body = {
        'proposalRevision': args.proposal_revision,
        'buyerPrivateData': {
            'referenceId': f'Marketplace-Python-Sample-Reference-{uuid.uuid4()}'
        }
    }

    update_mask = 'buyerPrivateData.referenceId'

    print(f'Patching proposal with name "{proposal_name}":')
    try:
        # Construct and execute the request.
        response = marketplace.buyers().proposals().patch(
            name=proposal_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 specified proposal 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 proposal '
              'was created. This will be used to construct the name used as a '
              'path parameter for the proposals.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 '
              'proposal was created. This will be used to construct the name '
              'used as a path parameter for the proposals.patch request.'))
    parser.add_argument(
        '-r', '--proposal_revision', required=True,
        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.'))

    main(service, parser.parse_args())

Add a note

You can use buyers.proposals.addNote to add a note to a proposal.

When you add notes to a proposal, they’re stored in the proposal’s notes field. Notes are visible to the publisher. We recommend using the notes field to communicate with the publisher during negotiations.

The following sample demonstrates how you can add a note to a proposal with the addNote method.

REST

Request

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

{
 "note": {
   "note": "Test note."
 }
}

Response

{
 "name": "buyers/12345678/proposals/MP49876074",
 "updateTime": "2022-03-26T04:03:19.282Z",
 "proposalRevision": "2",
 "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",
 "buyerPrivateData": {
   "referenceId": "2f5e9550-8d22-495e-ba38-9b9496347a3b"
 },
 "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."
   },
   {
     "createTime": "2022-03-26T05:36:23.406Z",
     "creatorRole": "BUYER",
     "note": "Test note."
   }
 ]
}

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>
    /// Adds a note to a given proposal.
    /// </summary>
    public class AddNoteToProposals : ExampleBase
    {
        private AuthorizedBuyersMarketplaceService mkService;

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

        /// <summary>
        /// Returns a description about the code example.
        /// </summary>
        public override string Description
        {
            get => "This code example adds a note to a given proposal.";
        }

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

            string accountId = null;
            string proposalId = null;
            string note = null;

            OptionSet options = new OptionSet {
                "Adds a note to a given 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 the " +
                     "proposal is being accessed. This will be used to construct the " +
                     "proposal name used as a path parameter for the proposals.addNote request."),
                    a => accountId = a
                },
                {
                    "p|proposal_id=",
                    ("[Required] The resource ID of the buyers.proposals resource that a note " +
                     "is being added to. This will be used to construct the proposal name " +
                     "used as a path parameter for the proposals.addNote request."),
                    p => proposalId = p
                },
                {
                    "n|note=",
                    ("The note to be added to the proposal. "),
                    n => note = 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 optional arguments.
            parsedArgs["account_id"] = accountId;
            parsedArgs["proposal_id"] = proposalId;
            parsedArgs["note"] = note ?? "Created note from C# sample.";
            // 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 proposalId = (string) parsedArgs["proposal_id"];
            string noteValue = (string) parsedArgs["note"];
            string proposalName = $"buyers/{accountId}/proposals/{proposalId}";

            Note note = new Note();
            note.NoteValue = noteValue;

            AddNoteRequest addNoteRequest = new AddNoteRequest()
            {
                Note = note
            };

            Console.WriteLine("Adding note to proposal with name \"{0}\":", proposalName);

            BuyersResource.ProposalsResource.AddNoteRequest request =
                mkService.Buyers.Proposals.AddNote(addNoteRequest, proposalName);
            Proposal response = null;

            try
            {
                response = request.Execute();
            }
            catch (Exception exception)
            {
                throw new ApplicationException(
                    $"Marketplace 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.AddNoteRequest;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.Note;
import com.google.api.services.authorizedbuyersmarketplace.v1.model.Proposal;
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;

/** Adds a note to a given proposal. */
public class AddNoteToProposals {

  public static void execute(AuthorizedBuyersMarketplace marketplaceClient, Namespace parsedArgs) {
    Integer accountId = parsedArgs.getInt("account_id");
    String proposalId = parsedArgs.getString(("proposal_id"));
    String proposalName = String.format("buyers/%d/proposals/%s", accountId, proposalId);
    String noteValue = parsedArgs.getString("note");

    Note note = new Note();
    note.setNote(noteValue);

    AddNoteRequest addNoteRequest = new AddNoteRequest();
    addNoteRequest.setNote(note);

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

    System.out.printf("Adding note to proposal with name \"%s\":%n", proposalName);
    Utils.printProposal(proposal);
  }

  public static void main(String[] args) {
    ArgumentParser parser =
        ArgumentParsers.newFor("AddNoteToProposals")
            .build()
            .defaultHelp(true)
            .description(("Adds a note to a given proposal."));
    parser
        .addArgument("-a", "--account_id")
        .help(
            "The resource ID of the buyers resource under which the proposal is being "
                + "accessed. This will be used to construct the proposal name used as a path "
                + "parameter for the proposals.addNote request.")
        .required(true)
        .type(Integer.class);
    parser
        .addArgument("-p", "--proposal_id")
        .help(
            "The resource ID of the proposals resource that a note is being added to. This "
                + "will be used to construct the name used as a path parameter for the "
                + "proposals.addNote request.")
        .required(true)
        .type(String.class);
    parser
        .addArgument("-n", "--note")
        .help("The note to be added to the proposal.")
        .type(String.class)
        .setDefault("Created note from Java sample.");

    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.

"""Adds a note to a proposal for the given account and proposal IDs.

This note will be visible to the seller and can be used to facilitate the
negotiation process.
"""


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'

DEFAULT_BUYER_RESOURCE_ID = 'ENTER_BUYER_RESOURCE_ID_HERE'
DEFAULT_PROPOSAL_RESOURCE_ID = 'ENTER_PROPOSAL_RESOURCE_ID_HERE'


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

    body = {
        'note': {
            'note': args.note
        }
    }

    print('Sending note to publisher for proposal with name '
          f'"{proposal_name}":')
    try:
        # Construct and execute the request.
        response = marketplace.buyers().proposals().addNote(
            proposal=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='Send a note to the publisher for a specified 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 proposals.addNote '
              'request.'))
    parser.add_argument(
        '-p', '--proposal_id', default=DEFAULT_PROPOSAL_RESOURCE_ID,
        help=('The resource ID of the buyers.proposals resource for which the '
              'proposal was created. This will be used to construct the '
              'name used as a path parameter for the proposals.addNote '
              'request.'))
    # Optional fields.
    parser.add_argument(
        '-n', '--note', default='Created note from Python sample.',
        help='The note to be added to the proposal.')

    main(service, parser.parse_args())