This guide explains the migration process from Content API for Shopping to Merchant API for business data management.
You can use this guide to migrate your existing Content API for Shopping implementation to Merchant API. For more information about the details of Merchant API and its sub-APIs, see Merchant API design.
Get started
To start using Merchant API, change your request URLs to the following format:
https://merchantapi.googleapis.com/{SUB_API}/{VERSION}/{RESOURCE_NAME}:{METHOD}…
To use the Merchant API, you must link your Merchant Center account and your Google Cloud project using the Developer Registration method, as follows:
POST https://merchantapi.googleapis.com/accounts/v1beta/accounts/{ACCOUNT_ID}/developerRegistration:registerGcp
{
developer_email:"example-email@example.com"
}
For more information, see the quickstart guide and the Merchant API reference.
See the latest updates in Merchant API (beta).
Improvements over Content API for Shopping
The Merchant API lets you automate and streamline workflows in Merchant Center and offers enhanced capabilities over Content API for Shopping.
Key use cases:
- Automated account management
- Automated product management
- Automated inventory management
- Custom reporting
Key improvement areas:
- Sub-APIs with new features, including:
- Order tracking supports business order tracking history to provide precise and accurate shipping estimates to customers. Its signals also enable enhanced listings with free and fast shipping.
- Issue resolution provides access to diagnostic content and support actions in the same way as it's available in the Merchant Center UI.
- Product Studio (ALPHA) leverages genAI to generate and optimize product titles and descriptions. You need to sign this form to request access.
- New resources in the Accounts sub-API.
OmnichannelSettings
manages the account configuration for omnichannel serving, such as Free Local Listings (FLL) and Local Inventory Ads (LIA).LfpProviders
connects to Local Feeds Partnership (LFP) partners for inventory data.GbpAccounts
connects to Google Business Profile account for local store data.OnlineReturnPolicy
provides the ability to create, delete and update your online policies.
- New methods for inventory, products data, and other APIs, including:
- A new method in the Products sub-API.
ProductsUpdate
lets you update individual products without the need to provide all the fields required forProductInput
.
- The ability to create not only primary data sources, but multiple data sources like:
- Introduces upload of product reviews and merchant reviews
- With Merchant API, you can enable notifications for changes to account data
What's changed:
- The maximum
pageSize
increased from 250 to 1000 rows per API call. - A delay that existed for product insertion, promotions, product reviews, and
merchant reviews after
DataSources
creation is fixed.
What's coming:
- Deprecation and future removal of the channel field for
DataSources
and products. - Launch of an updated definition for
clickPotentialRank
in theproductView
table under the Reporting sub-API: * Ranking of products based onclickPotential
is normalized to values between 1 and 1000.- Products with low
clickPotentialRank
still have the highest click potential among the merchant's products that fulfill the search query conditions. This is a non-breaking change that might be launched on July 1, 2025.
- Products with low
- The
AccountIdAlias
in theAccountRelationship
resource, makes it possible to better manage complex account structures. For example, marketplaces use a user-defined alias instead of the merchant's internal ID, such as account ID.
gRPC support
The Merchant API supports gRPC and REST. You can use gRPC for the Merchant API and REST for the Content API for Shopping at the same time.
The Merchant API client libraries require gRPC.
For more information, see gRPC overview.
Compatibility
This guide describes general changes that apply to the entire Merchant API.
The Merchant API is designed to work alongside existing Content API for Shopping features.
For example, you can use the Merchant Inventories API alongside your existing
Content API for Shopping v2.1
products
implementation. You
might use the Content API for Shopping to upload a new local
product (that you sell
in a local store), then use the Merchant Inventories API
LocalInventory
resource to manage in-store information for that product.
Improvements over Content API
Merchant API improves over Content API in the following areas:
- Sub-APIs with new features for your unique integration
- New methods for inventory, products data, and other APIs
- The ability to create not only primary data sources, but multiple data sources, such as:
- Introduces upload of product reviews and merchant reviews
- With Merchant API, you can enable notifications for changes to account data.
- Introduces filtering capability for the Accounts resource
Consider these changes in more detail.
Versioning and sub-APIs
Merchant API introduces the concepts of versioning and sub-APIs. Its modular design improves ease of use, by allowing you to focus on the sub-APIs you need and enabling easier future migrations to newer versions. Versioning will be applied with your request URLs. The strategy is similar to the Google Ads API experience.
More robust requests
Merchant API URL requests require more parameters to call Merchant API. This includes the resource, version, name (identifiers) and method (non standard methods). For more about this, see Account and Product identifiers and examples.
AIP principles for identifiers
While Content API for Shopping uses IDs to identify resources (for example,
merchantId
, productId
), Merchant API uses a
name
identifier to align with the AIP (see API improvement
principles).
The {name}
identifier includes the resource identifier and its parent (or
potentially multiple parents), such that {name}
equals
accounts/{account}/products/{product}
All read and write calls return the name
field as the resource identifier.
{name}
also includes the collection identifiers accounts/
and products/
.
Merchant API uses {account}
to refer to a Merchant Center ID and {product}
to refer to product identifiers.
For example, implement a getName()
method to retrieve the name
from a
resource, and store the output as a variable instead of constructing the name
from the merchant and resource IDs yourself.
Here's an example of how to use the name
field in your calls:
POST https://merchantapi.googleapis.com/inventories/v1beta/{PARENT}/regionalInventories:insert
The table shows how the Content API for Shopping products.get
request changes:
Content API for Shopping | Merchant API |
---|---|
GET https://shoppingcontent.googleapis.com/content/v2.1/{merchantId}/products/{productId}
|
GET https://merchantapi.googleapis.com/products/v1beta/{name}
|
For more details, review Identifier changes.
As another example, retrieving a product with the identifier online~en~US~1234
from Merchant Center ID 4321
using Merchant API would look like the following:
GET
https://merchantapi.googleapis.com/products/v1beta/accounts/4321/products/online~en~US~1234
where {name}
equals accounts/4321/products/online~en~US~1234
. This new name
field is returned as the resource identifier for all read and write calls in
Merchant API.
In Content API for Shopping, a colon (:) denotes a delimiter in product name whereas, in Merchant API, a tilde (~) performs this function.
For example, product ID in Content API for Shopping:
channel:contentLanguage:feedLabel:offerId
.
in Merchant Center API becomes the following:
channel~contentLanguage~feedLabel~offerId
.
Parent fields for child resources
In Merchant API, all child resources have the
parent
field. You can use the parent
field to specify the {name}
of the resource to
insert the child into, instead of passing the entire parent resource. You can
also use the parent
field with
list
For example, to list local inventories for a given product, specify the
product's name
in the
parent
field for the
list
method. In this case, the given product
is the parent
of the
LocalInventory
resources returned.
GET
https://merchantapi.googleapis.com/inventories/v1beta/{parent}/localInventories
To retrieve all local inventories for product online~en~US~1234'
and account
4321
the request would look like
GET
https://merchantapi.googleapis.com/inventories/v1beta/accounts/4321/products/online~en~US~1234/localInventories</code>
The Parent is accounts/{account}/products/{product}
. Note that in this case
the
localInventories
resource has two parents included in the name identifier (accounts/
and
products/
), as the account is the parent of the product resource.
Common enums
The use of common enums provides more consistency.
The
Destination.DestinationEnum
field specifies the surfaces on which to display your resources.
DestinationEnum
lists all available values for destination targeting and is
unified across sub-APIs, for example for promotions
attributes.
The
ReportingContext.ReportingContextEnum
field represents the context to which your account and product issues apply.
This field is used across reporting methods (for example, for
IssueSeverityPerReportingContext
).
Backwards compatibility
As you start using Merchant API, your existing Content API for Shopping integration continues to function without interruption. For more information, see Compatibility.
Once you migrate your sub-APIs to Merchant API, we recommend you use only Merchant API for your migrated sub-APIs.
Remote procedure call (gRPC) availability
gRPC is the new recommended way to integrate with Merchant API.
Its advantages include the following:
- Language-agnostic
- Relies on protocol buffers
Uses HTTP/2 to provide high-performance scalable solutions (RPC reference)
If you use our client libraries or code samples, gRPC is the default transport mechanism.
For more information on gRPC, see the following:
Custom batching becomes built-in batching
Batching performs more efficiently when you use asynchronous calls. Learn more about using parallel calls to achieve batching in Merchant API and how to Refactor code for concurrent requests.
To help expedite your migration, we recommend the client libraries.
Merchant API doesn't support the
customBatch
method featured in the Content API for Shopping. Instead, see Send multiple
requests at once or execute your calls
asynchronously.
The following Java sample demonstrates how to insert a product input.
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.v1beta.Attributes;
import com.google.shopping.merchant.products.v1beta.InsertProductInputRequest;
import com.google.shopping.merchant.products.v1beta.ProductInput;
import com.google.shopping.merchant.products.v1beta.ProductInputsServiceClient;
import com.google.shopping.merchant.products.v1beta.ProductInputsServiceSettings;
import com.google.shopping.merchant.products.v1beta.Shipping;
import com.google.shopping.type.Channel.ChannelEnum;
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();
Attributes attributes =
Attributes.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("in stock")
.setCondition("new")
.setGoogleProductCategory("Media > Books")
.addGtin("9780007350896")
.addShipping(shipping)
.addShipping(shipping2)
.build();
return ProductInput.newBuilder()
.setChannel(ChannelEnum.ONLINE)
.setContentLanguage("en")
.setFeedLabel("CH")
.setOfferId(generateRandomString())
.setAttributes(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);
}
}
If you use
customBatch
in
Content API, and need this feature for the Merchant API, let us know why in your
feedback.
Exclusive features
Future features will appear only in Merchant API. (There will be a few exceptions, such as the 2025 annual feed spec.)
Features exclusive to Merchant API include
- Reviews API. Use Reviews to implement and manage your product and shop ratings. For more information see Seller review and Product Review.
- Notifications: Sign up to receive push notifications for changes to an account's product data.
Price
Here's what's changed for Price
in the Merchant Common package:
Content API for Shopping | Merchant API | |
---|---|---|
Amount field | value:string |
amountMicros:int64 |
Currency field | currency:string
|
currencyCode:string |
The Price
amount is now recorded in micros, where 1 million micros is
equivalent to your currency's standard unit.
In the Content API for Shopping, Price
was a decimal number in the form of a
string.
The amount field name has changed from value
to amountMicros
The currency field name has changed from currency
to currencyCode
. The
format continues to be ISO 4217.
Latest updates and announcements
For more granular updates, see the release notes specific to each sub-API. For more regular aggregated Merchant API updates, review our latest updates.
For more specific details and to learn even more about Merchant API, view our developer site overview and overall migration guide for more details.
See Merchant API design for details about Merchant API and its sub-APIs.