In the Content API for Shopping, a batch request could have multiple entries, and each entry can be any method (insert, update, delete, or custom) defined on the resource.
Merchant API does not offer custom batch methods. Instead, you can arrange parallel execution of individual requests.
With the client library
The following example shows asynchronous calls (or batching in Content API for Shopping) for product insertion. You can apply this example to other resources and sub-APIs (such as inventories, accounts, and so on). We have also provided code samples covering all examples.
If using the client library, consider this Content API for Shopping code.
package
shopping.content.v2_1.samples.products
;
import
com.google.api.services.content.model.ProductsCustomBatchResponse
;
import
java.io.IOException
;
import
shopping.content.v2_1.samples.ContentSample
;
/** Sample that shows batching product inserts. */
public
class
ProductsBatchInsertSample
extends
ContentSample
{
public
ProductsBatchInsertSample
(
String
[]
args
)
throws
IOException
{
super
(
args
);
}
@Override
public
void
execute
()
throws
IOException
{
checkNonMCA
();
ProductsCustomBatchResponse
batchResponse
=
content
.
products
().
custombatch
(
ExampleProductFactory
.
createBatch
(
config
,
"book"
)).
execute
();
ProductUtils
.
printProductBatchResults
(
batchResponse
);
}
public
static
void
main
(
String
[]
args
)
throws
IOException
{
new
ProductsBatchInsertSample
(
args
).
execute
();
}
}
Write the Merchant API equivalent as follows.
Java
// Copyright 2024 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
shopping.merchant.samples.products.v1
;
import
com.google.api.core.ApiFuture
;
import
com.google.api.core.ApiFutureCallback
;
import
com.google.api.core.ApiFutures
;
import
com.google.api.gax.core.FixedCredentialsProvider
;
import
com.google.auth.oauth2.GoogleCredentials
;
import
com.google.common.util.concurrent.MoreExecutors
;
import
com.google.shopping.merchant.products.v1.Availability
;
import
com.google.shopping.merchant.products.v1.Condition
;
import
com.google.shopping.merchant.products.v1.InsertProductInputRequest
;
import
com.google.shopping.merchant.products.v1.ProductAttributes
;
import
com.google.shopping.merchant.products.v1.ProductInput
;
import
com.google.shopping.merchant.products.v1.ProductInputsServiceClient
;
import
com.google.shopping.merchant.products.v1.ProductInputsServiceSettings
;
import
com.google.shopping.merchant.products.v1.Shipping
;
import
com.google.shopping.type.Price
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Random
;
import
java.util.stream.Collectors
;
import
shopping.merchant.samples.utils.Authenticator
;
import
shopping.merchant.samples.utils.Config
;
/** This class demonstrates how to insert a product input */
public
class
InsertProductInputAsyncSample
{
private
static
String
getParent
(
String
accountId
)
{
return
String
.
format
(
"accounts/%s"
,
accountId
);
}
private
static
String
generateRandomString
()
{
String
characters
=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
;
Random
random
=
new
Random
();
StringBuilder
sb
=
new
StringBuilder
(
8
);
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
sb
.
append
(
characters
.
charAt
(
random
.
nextInt
(
characters
.
length
())));
}
return
sb
.
toString
();
}
private
static
ProductInput
createRandomProduct
()
{
Price
price
=
Price
.
newBuilder
().
setAmountMicros
(
33_450_000
).
setCurrencyCode
(
"USD"
).
build
();
Shipping
shipping
=
Shipping
.
newBuilder
().
setPrice
(
price
).
setCountry
(
"GB"
).
setService
(
"1st class post"
).
build
();
Shipping
shipping2
=
Shipping
.
newBuilder
().
setPrice
(
price
).
setCountry
(
"FR"
).
setService
(
"1st class post"
).
build
();
ProductAttributes
attributes
=
ProductAttributes
.
newBuilder
()
.
setTitle
(
"A Tale of Two Cities"
)
.
setDescription
(
"A classic novel about the French Revolution"
)
.
setLink
(
"https://exampleWebsite.com/tale-of-two-cities.html"
)
.
setImageLink
(
"https://exampleWebsite.com/tale-of-two-cities.jpg"
)
.
setAvailability
(
Availability
.
IN_STOCK
)
.
setCondition
(
Condition
.
NEW
)
.
setGoogleProductCategory
(
"Media > Books"
)
.
addGtins
(
"9780007350896"
)
.
addShipping
(
shipping
)
.
addShipping
(
shipping2
)
.
build
();
return
ProductInput
.
newBuilder
()
.
setContentLanguage
(
"en"
)
.
setFeedLabel
(
"CH"
)
.
setOfferId
(
generateRandomString
())
.
setProductAttributes
(
attributes
)
.
build
();
}
public
static
void
asyncInsertProductInput
(
Config
config
,
String
dataSource
)
throws
Exception
{
// Obtains OAuth token based on the user's configuration.
GoogleCredentials
credential
=
new
Authenticator
().
authenticate
();
// Creates service settings using the credentials retrieved above.
ProductInputsServiceSettings
productInputsServiceSettings
=
ProductInputsServiceSettings
.
newBuilder
()
.
setCredentialsProvider
(
FixedCredentialsProvider
.
create
(
credential
))
.
build
();
// Creates parent to identify where to insert the product.
String
parent
=
getParent
(
config
.
getAccountId
().
toString
());
// Calls the API and catches and prints any network failures/errors.
try
(
ProductInputsServiceClient
productInputsServiceClient
=
ProductInputsServiceClient
.
create
(
productInputsServiceSettings
))
{
// Creates five insert product input requests with random product IDs.
List<InsertProductInputRequest>
requests
=
new
ArrayList
<> (
5
);
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
InsertProductInputRequest
request
=
InsertProductInputRequest
.
newBuilder
()
.
setParent
(
parent
)
// You can only insert products into datasource types of Input "API", and of Type
// "Primary" or "Supplemental."
// This field takes the `name` field of the datasource.
.
setDataSource
(
dataSource
)
// If this product is already owned by another datasource, when re-inserting, the
// new datasource will take ownership of the product.
.
setProductInput
(
createRandomProduct
())
.
build
();
requests
.
add
(
request
);
}
System
.
out
.
println
(
"Sending insert product input requests"
);
List<ApiFuture<ProductInput>
>
futures
=
requests
.
stream
()
.
map
(
request
-
>
productInputsServiceClient
.
insertProductInputCallable
().
futureCall
(
request
))
.
collect
(
Collectors
.
toList
());
// Creates callback to handle the responses when all are ready.
ApiFuture<List<ProductInput>
>
responses
=
ApiFutures
.
allAsList
(
futures
);
ApiFutures
.
addCallback
(
responses
,
new
ApiFutureCallback<List<ProductInput>
> ()
{
@Override
public
void
onSuccess
(
List<ProductInput>
results
)
{
System
.
out
.
println
(
"Inserted products below"
);
System
.
out
.
println
(
results
);
}
@Override
public
void
onFailure
(
Throwable
throwable
)
{
System
.
out
.
println
(
throwable
);
}
},
MoreExecutors
.
directExecutor
());
}
catch
(
Exception
e
)
{
System
.
out
.
println
(
e
);
}
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
Config
config
=
Config
.
load
();
// Identifies the data source that will own the product input.
String
dataSource
=
"accounts/"
+
config
.
getAccountId
()
+
"/dataSources/{datasourceId}"
;
asyncInsertProductInput
(
config
,
dataSource
);
}
}
Node.js
// Copyright 2025 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.
'use strict'
;
const
fs
=
require
(
'fs'
);
const
authUtils
=
require
(
'../../authentication/authenticate.js'
);
const
{
ProductInputsServiceClient
,
}
=
require
(
'@google-shopping/products'
).
v1
;
const
{
protos
,
}
=
require
(
'@google-shopping/products'
);
const
Availability
=
protos
.
google
.
shopping
.
merchant
.
products
.
v1
.
Availability
;
const
Condition
=
protos
.
google
.
shopping
.
merchant
.
products
.
v1
.
Condition
;
/**
* This class demonstrates how to insert a product input asynchronously.
*/
/**
* Helper function to generate a random string for offerId
* @returns {string} A sample offerId.
*/
function
generateRandomString
()
{
const
characters
=
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
;
let
result
=
''
;
const
length
=
8
;
for
(
let
i
=
0
;
i
<
length
;
i
++
)
{
result
+=
characters
.
charAt
(
Math
.
floor
(
Math
.
random
()
*
characters
.
length
));
}
return
result
;
}
/**
* Helper function to create a sample ProductInput object
* @returns {!object} A sample ProductInput object.
*/
function
createRandomProduct
()
{
const
shippingPrice
=
{
amountMicros
:
3000000
,
// 3 USD
currencyCode
:
'USD'
,
};
const
price
=
{
amountMicros
:
33450000
,
// 33.45 USD
currency_code
:
'USD'
,
};
const
shipping
=
{
price
:
shippingPrice
,
country
:
'GB'
,
service
:
'1st class post'
,
};
const
shipping2
=
{
price
:
shippingPrice
,
country
:
'FR'
,
service
:
'1st class post'
,
};
const
attributes
=
{
title
:
'A Tale of Two Cities'
,
description
:
'A classic novel about the French Revolution'
,
link
:
'https://exampleWebsite.com/tale-of-two-cities.html'
,
image_link
:
'https://exampleWebsite.com/tale-of-two-cities.jpg'
,
availability
:
Availability
.
IN_STOCK
,
condition
:
Condition
.
NEW
,
google_product_category
:
'Media > Books'
,
gtins
:
[
'9780007350896'
],
shipping
:
[
shipping
,
shipping2
],
price
:
price
,
};
// Construct the ProductInput object
const
productInput
=
{
contentLanguage
:
'en'
,
feedLabel
:
'CH'
,
offerId
:
generateRandomString
(),
productAttributes
:
attributes
,
};
return
productInput
;
}
/**
* Inserts multiple product inputs asynchronously.
* @param {!object} config - Configuration object.
* @param {string} dataSource - The data source name.
*/
async
function
asyncInsertProductInput
(
config
,
dataSource
)
{
// Read merchant_id from the configuration file.
const
merchantInfo
=
JSON
.
parse
(
fs
.
readFileSync
(
config
.
merchantInfoFile
,
'utf8'
)
);
const
merchantId
=
merchantInfo
.
merchantId
;
// Construct the parent resource name string.
const
parent
=
`accounts/
${
merchantId
}
`
;
// Get OAuth2 credentials.
const
authClient
=
await
authUtils
.
getOrGenerateUserCredentials
();
// Create client options with authentication.
const
options
=
{
authClient
:
authClient
};
// Create the ProductInputsServiceClient.
const
productInputsServiceClient
=
new
ProductInputsServiceClient
(
options
);
// Create five insert product input requests with random product details.
const
requests
=
[];
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
const
request
=
{
parent
:
parent
,
// You can only insert products into datasource types of Input "API" and "FILE", and
// of Type "Primary" or "Supplemental."
// This field takes the `name` field of the datasource, e.g.,
// accounts/123/dataSources/456
dataSource
:
dataSource
,
// If this product is already owned by another datasource, when re-inserting, the
// new datasource will take ownership of the product.
productInput
:
createRandomProduct
(),
};
requests
.
push
(
request
);
}
console
.
log
(
'Sending insert product input requests...'
);
// Create an array of promises by calling the insertProductInput method for each request.
const
insertPromises
=
requests
.
map
(
request
=
>
productInputsServiceClient
.
insertProductInput
(
request
)
);
// Wait for all insert operations to complete.
// Promise.all returns an array of results, where each result is the response
// from the corresponding insertProductInput call (which is the inserted ProductInput).
// The response from insertProductInput is an array where the first element is the ProductInput.
const
results
=
await
Promise
.
all
(
insertPromises
);
const
insertedProducts
=
results
.
map
(
result
=
>
result
[
0
]);
// Extract ProductInput from each response array
console
.
log
(
'Inserted products below:'
);
console
.
log
(
JSON
.
stringify
(
insertedProducts
,
null
,
2
));
}
/**
* Main function to call the async insert product input method.
*/
async
function
main
()
{
// Get configuration settings.
const
config
=
authUtils
.
getConfig
();
// Define the data source ID. Replace {datasourceId} with your actual data source ID.
// The format is accounts/{account_id}/dataSources/{datasource_id}.
const
merchantInfo
=
JSON
.
parse
(
fs
.
readFileSync
(
config
.
merchantInfoFile
,
'utf8'
)
);
const
merchantId
=
merchantInfo
.
merchantId
;
const
dataSource
=
`accounts/
${
merchantId
}
/dataSources/{datasourceId}`
;
// Replace {datasourceId}
try
{
await
asyncInsertProductInput
(
config
,
dataSource
);
}
catch
(
error
)
{
console
.
error
(
`An error occurred:
${
error
.
message
||
error
}
`
);
// Log details if available (e.g., for gRPC errors)
if
(
error
.
details
)
{
console
.
error
(
`Details:
${
error
.
details
}
`
);
}
}
}
main
();
PHP
< ?php
/**
* Copyright 2025 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.
*/
require_once __DIR__ . '/../../../vendor/autoload.php';
require_once __DIR__ . '/../../Authentication/Authentication.php';
require_once __DIR__ . '/../../Authentication/Config.php';
use Google\ApiCore\ApiException;
use Google\Shopping\Merchant\Products\V1\Availability;
use Google\Shopping\Merchant\Products\V1\Condition;
use Google\Shopping\Merchant\Products\V1\ProductAttributes;
use Google\Shopping\Merchant\Products\V1\InsertProductInputRequest;
use Google\Shopping\Merchant\Products\V1\ProductInput;
use Google\Shopping\Merchant\Products\V1\Client\ProductInputsServiceClient;
use Google\Shopping\Merchant\Products\V1\Shipping;
use Google\Shopping\Type\Price;
use React\EventLoop\Loop;
use React\Promise\Promise;
use function React\Promise\all;
/**
* This class demonstrates how to insert multiple product inputs asynchronously.
*/
class InsertProductInputAsyncSample
{
/**
* A helper function to create the parent string for product input operations.
*
* @param string $accountId The Merchant Center account ID.
* @return string The parent resource name format: `accounts/{account_id}`.
*/
private static function getParent(string $accountId): string
{
return sprintf("accounts/%s", $accountId);
}
/**
* Generates a random string of 8 characters.
*
* @return string A random alphanumeric string.
*/
private static function generateRandomString(): string
{
$characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$randomString = '';
$charactersLength = strlen($characters);
for ($i = 0; $i < 8; $i++) {
$randomString .= $characters[random_int(0, $charactersLength - 1)];
}
return $randomString;
}
/**
* Creates a ProductInput object with randomized offer ID and sample attributes.
*
* @return ProductInput A new ProductInput object.
*/
private static function createRandomProduct(): ProductInput
{
// Create a price object for shipping. Amount is in micros.
// e.g., 33,450,000 micros = $33.45 USD
$price = new Price([
'amount_micros' => 33450000,
'currency_code' => 'USD'
]);
// Create shipping details.
$shipping = new Shipping([
'price' => $price,
'country' => 'GB',
'service' => '1st class post'
]);
$shipping2 = new Shipping([
'price' => $price,
'country' => 'FR',
'service' => '1st class post'
]);
// Create product attributes.
$attributes = new ProductAttributes([
'title' => 'A Tale of Two Cities',
'description' => 'A classic novel about the French Revolution',
'link' => 'https://exampleWebsite.com/tale-of-two-cities.html',
'image_link' => 'https://exampleWebsite.com/tale-of-two-cities.jpg',
'availability' => Availability::IN_STOCK,
'condition' => Condition::PBNEW,
'google_product_category' => 'Media > Books',
'gtins' => ['9780007350896'],
'shipping' => [$shipping, $shipping2]
]);
// Create the product input object.
return new ProductInput([
'content_language' => 'en',
'feed_label' => 'LABEL',
'offer_id' => self::generateRandomString(), // Random offer ID for uniqueness
'product_attributes' => $attributes
]);
}
/**
* Inserts multiple product inputs into the specified account and data source asynchronously.
*
* @param array $config Authentication and account configuration.
* @param string $dataSource The target data source name.
* Format: `accounts/{account}/dataSources/{datasource}`.
* @return void
*/
public static function insertProductInputAsyncSample(array $config, string $dataSource): void
{
// Fetches OAuth2 credentials for making API calls.
$credentials = Authentication::useServiceAccountOrTokenFile();
// Prepares client options with the fetched credentials.
$options = ['credentials' => $credentials];
// Initializes the ProductInputsServiceAsyncClient.
// This is the key for asynchronous operations.
$productInputsServiceAsyncClient = new ProductInputsServiceClient($options);
// Constructs the parent resource string.
$parent = self::getParent($config['accountId']);
$promises = [];
$insertedProductInputs = [];
print "Sending insert product input requests asynchronously...\n";
// Create and send 5 insert product input requests asynchronously.
for ($i = 0; $i < 5; $i++) {
$productInput = self::createRandomProduct();
// Create the request object.
$request = new InsertProductInputRequest([
'parent' => $parent,
'data_source' => $dataSource,
'product_input' => $productInput
]);
// Make the asynchronous API call. This returns a Promise.
$promise = $productInputsServiceAsyncClient->insertProductInputAsync($request);
// Attach success and error handlers to the promise.
$promise->then(
function (ProductInput $response) use (&$insertedProductInputs) {
// This callback is executed when the promise resolves (success).
$insertedProductInputs[] = $response;
print "Successfully inserted product with offer ID: " . $response->getOfferId() . "\n";
},
function (ApiException $e) {
// This callback is executed if the promise rejects (failure).
echo "ApiException occurred for one of the requests:\n";
echo $e;
}
);
$promises[] = $promise;
}
// Wait for all promises to settle (either resolve or reject).
// Reduce::all() creates a single promise that resolves when all input promises resolve.
// If any promise rejects, the combined promise will reject.
all($promises)->then(
function () use (&$insertedProductInputs) {
print "All asynchronous requests have completed.\n";
// Print details of all successfully inserted products.
print "Inserted products below\n";
foreach ($insertedProductInputs as $p) {
print_r($p);
}
},
function ($reason) {
// This block is executed if any promise in the array rejects.
echo "One or more asynchronous requests failed.\n";
if ($reason instanceof ApiException) {
echo "API Exception: " . $reason->getMessage() . "\n";
} else {
echo "Error: " . $reason . "\n";
}
}
)->always(function () use ($productInputsServiceAsyncClient) {
// This 'always' callback ensures the client is closed after all promises settle.
$productInputsServiceAsyncClient->close();
});
// Run the event loop. This is crucial for asynchronous operations to execute.
// The script will block here until all promises are resolved/rejected or the loop is stopped.
Loop::run();
}
/**
* Executes the sample code to insert multiple product inputs.
*
* @return void
*/
public function callSample(): void
{
$config = Config::generateConfig();
// Define the data source that will own the product inputs.
// IMPORTANT: Replace `<DATA_SOURCE_ID>` with your actual data source ID.
$dataSourceId = '<DATA_SOURCE_ID>';
$dataSourceName = sprintf(
"accounts/%s/dataSources/%s",
$config['accountId'], $dataSourceId
);
// Call the method to insert multiple product inputs asynchronously.
self::insertProductInputAsyncSample($config, $dataSourceName);
}
}
$sample = new InsertProductInputAsyncSample();
$sample->callSample();
Python
# -*- coding: utf-8 -*-
# Copyright 2025 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.
"""A module to insert product inputs asynchronously."""
import
asyncio
import
functools
import
random
import
string
from
examples.authentication
import
configuration
from
examples.authentication
import
generate_user_credentials
from
google.shopping.merchant_products_v1
import
Availability
from
google.shopping.merchant_products_v1
import
Condition
from
google.shopping.merchant_products_v1
import
InsertProductInputRequest
from
google.shopping.merchant_products_v1
import
ProductAttributes
from
google.shopping.merchant_products_v1
import
ProductInput
from
google.shopping.merchant_products_v1
import
ProductInputsServiceAsyncClient
from
google.shopping.merchant_products_v1
import
Shipping
from
google.shopping.type
import
Price
# Read merchant account information from the configuration file.
_ACCOUNT_ID
=
configuration
.
Configuration
()
.
read_merchant_info
()
# The parent account for the product input.
# Format: accounts/{account}
_PARENT
=
f
"accounts/
{
_ACCOUNT_ID
}
"
def
_generate_random_string
(
length
:
int
=
8
)
-
> str
:
"""Generates a random string of a given length."""
characters
=
string
.
ascii_letters
+
string
.
digits
return
""
.
join
(
random
.
choice
(
characters
)
for
_
in
range
(
length
))
def
_create_random_product
()
-
> ProductInput
:
"""Creates a ProductInput with random elements and predefined attributes."""
price
=
Price
(
amount_micros
=
33450000
,
currency_code
=
"USD"
)
shipping1
=
Shipping
(
price
=
price
,
country
=
"GB"
,
service
=
"1st class post"
)
shipping2
=
Shipping
(
price
=
price
,
country
=
"FR"
,
service
=
"1st class post"
)
attributes
=
ProductAttributes
(
title
=
"Async - A Tale of Two Cities"
,
description
=
"A classic novel about the French Revolution"
,
link
=
"https://exampleWebsite.com/tale-of-two-cities.html"
,
image_link
=
"https://exampleWebsite.com/tale-of-two-cities.jpg"
,
availability
=
Availability
.
IN_STOCK
,
condition
=
Condition
.
NEW
,
google_product_category
=
"Media > Books"
,
gtins
=
[
"9780007350896"
],
shipping
=
[
shipping1
,
shipping2
],
)
return
ProductInput
(
content_language
=
"en"
,
feed_label
=
"US"
,
offer_id
=
_generate_random_string
(),
product_attributes
=
attributes
,
)
def
print_product_input
(
i
,
task
):
print
(
"Inserted ProductInput number: "
,
i
)
# task.result() contains the response from async_insert_product_input
print
(
task
.
result
())
async
def
async_insert_product_input
(
client
:
ProductInputsServiceAsyncClient
,
request
:
InsertProductInputRequest
):
"""Inserts product inputs.
Args:
client: The ProductInputsServiceAsyncClient to use.
request: The InsertProductInputRequest to send.
Returns:
The response from the insert_produc_input request.
"""
print
(
"Sending insert product input requests"
)
try
:
response
=
await
client
.
insert_product_input
(
request
=
request
)
# The response is an async corouting inserting the ProductInput.
return
response
except
RuntimeError
as
e
:
# Catch and print any exceptions that occur during the API calls.
print
(
e
)
async
def
main
():
# The ID of the data source that will own the product input.
# This is a placeholder and should be replaced with an actual data source ID.
datasource_id
=
"<INSERT_DATA_SOURCE_ID_HERE>"
data_source_name
=
f
"accounts/
{
_ACCOUNT_ID
}
/dataSources/
{
datasource_id
}
"
# Gets OAuth Credentials.
credentials
=
generate_user_credentials
.
main
()
# Creates a ProductInputsServiceClient.
client
=
ProductInputsServiceAsyncClient
(
credentials
=
credentials
)
tasks
=
[]
for
i
in
range
(
5
):
product_input
=
_create_random_product
()
request
=
InsertProductInputRequest
(
parent
=
_PARENT
,
data_source
=
data_source_name
,
product_input
=
product_input
,
)
# Create the async task
insert_product_task
=
asyncio
.
create_task
(
async_insert_product_input
(
client
,
request
)
)
# Add the callback
callback_function
=
functools
.
partial
(
print_product_input
,
i
)
insert_product_task
.
add_done_callback
(
callback_function
)
# Add the task to our list
tasks
.
append
(
insert_product_task
)
# Await all tasks to complete concurrently
# The print_product_input callback will be called for each as it finishes
await
asyncio
.
gather
(
*
tasks
)
if
__name__
==
"__main__"
:
asyncio
.
run
(
main
())
Without the client library
If you aren't using the client library, accomplish batching as explained at Send multiple requests at once .
For example, replace a Content API for Shopping request like the following:
POST
h
tt
ps
:
//shoppingcontent.googleapis.com/content/v2.1/products/batch
{
"entries"
:
[
{
"method"
:
"insert"
,
"product"
:
{
…
}
}
…
]
}
with this Write a batch request example.