Merchant API v1beta was discontinued and shut down on February 28, 2026. For steps to transition to the latest stable version, seeMigrate from v1beta to v1.
Add and manage productsStay organized with collectionsSave and categorize content based on your preferences.
The Products sub-API lets you manage the entire lifecycle of your products
in Merchant Center. You can use it to upload new products, update existing
ones, retrieve product information, and delete products you no longer sell.
Special considerations
Products can only be inserted, updated or deleted if they belong todata sourcesof typeAPI. You cannot insert or update products within data sources that
use file-based uploads.
To keep your products relevant and prevent expiration , you should update or
refresh them with a regular cadence (at least every 30 days).
TheProductInput.namesegment is a unique identifier for the product.
Products are identified by a combination of language, feed label and offer
ID, in the formatcontentLanguage~feedLabel~offerIdsuch asen~US~sku12345. Merchant API uses this identifier to buildproductandproductInputresource names, for exampleaccounts/12345/products/en~US~SKU12345.
You mustencodethe identifier parten~US~SKU12345if any part of the product identifier
such as the offerId contains URL-reserved characters or characters used by
Merchant API such as/,%, or~. For more information, see theProductInput.namefield. The identifier parten~US~SKU12345must be URL-encoded when
included in a request URL.
Prerequisites
Before you can add or manage products using the API, you must have at least one
data source configured in your Merchant Center account.
To create a data source, use thedataSources.createmethod from the Data Sources sub-API. To help you decide on the type of
data source to create, seeChoose your data source strategyandManage API data sources for product uploads.
After creating a data source, take note of itsname(for example,accounts/12345/dataSources/67890), as you'll need it for product-related
creation, update, or deletion requests.
Add a product
To add a new product to your Merchant Center account, you need to insert aProductInputresource into a primary data source. This action creates the
product and starts processing. The fields within theproductAttributesobject
must conform to theProduct data specification.
Use theproductInputs.insertmethod and provide thenameof your primary data source as thedataSourceparameter.
The following example inserts a new product for an online store into a primary
data source. The product has some attributes such as:
For more information about Product attributes, seeProductAttributes.
POST https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
{"offerId":"SKU12345","contentLanguage":"en","feedLabel":"US","productAttributes":{"title":"Classic Cotton T-Shirt","description":"A comfortable, durable, and stylish t-shirt made from 100% cotton.","link":"https://www.example.com/p/SKU12345","imageLink":"https://www.example.com/img/SKU12345.jpg","videoLinks":["https://www.example.com/videos/SKU12345_1.mp4","https://www.example.com/videos/SKU12345_2.mp4"],"availability":"IN_STOCK","price":{"amountMicros":"15990000",// 15.99 USD"currencyCode":"USD"},"condition":"NEW","gtins":["9780007350896","93433295494587"]}}
A successful call returns the newly createdProductInputresource. Thenamefield contains the unique identifier for this product input, and theproductfield contains the name of the final, processed product you can later use to
retrieve it.
The fields returned in aproductInputs.insertresponse reflect the input values. The processed values that will be persisted
in the resultingproductAttributesmight differ.
{"name":"accounts/{ACCOUNT_ID}/productInputs/{en~US~SKU12345}","product":"accounts/{ACCOUNT_ID}/products/{en~US~SKU12345}","offerId":"SKU12345","contentLanguage":"en","feedLabel":"US","productAttributes":{"title":"Classic Cotton T-Shirt","description":"A comfortable, durable, and stylish t-shirt made from 100% cotton.","link":"https://www.example.com/p/SKU12345","imageLink":"https://www.example.com/img/SKU12345.jpg","videoLinks":["https://www.example.com/videos/SKU12345_1.mp4","https://www.example.com/videos/SKU12345_2.mp4"],"availability":"IN_STOCK","price":{"amountMicros":"15990000","currencyCode":"USD"},"condition":"NEW","gtins":["9780007350896"]}}
The following code samples show how to add a product.
fromexamples.authenticationimportconfigurationfromexamples.authenticationimportgenerate_user_credentialsfromgoogle.shoppingimportmerchant_products_v1fromgoogle.shopping.merchant_products_v1importAvailabilityfromgoogle.shopping.merchant_products_v1importConditionfromgoogle.shopping.typeimportPrice_ACCOUNT=configuration.Configuration().read_merchant_info()_PARENT=f"accounts/{_ACCOUNT}"# You can only insert products into datasource types of Input "API" and# "FILE", and of Type "Primary" or "Supplemental."_DATA_SOURCE="[INSERT_DATA_SOURCE_HERE]"_DATA_SOURCE_NAME=f"accounts/{_ACCOUNT}/dataSources/{_DATA_SOURCE}"defcreate_product_input():"""Creates a `ProductInput` resource."""# Creates a shipping settingprice=Price()price.amount_micros=33_450_000price.currency_code="GBP"shipping_option_1=merchant_products_v1.Shipping()shipping_option_1.price=priceshipping_option_1.country="GB"shipping_option_1.service="1st class post"price2=Price()price2.amount_micros=33_450_000price2.currency_code="EUR"shipping_option_2=merchant_products_v1.Shipping()shipping_option_2.price=price2shipping_option_2.country="FR"shipping_option_2.service="2nd class post"# Sets product attributes. Make sure to replace these values with your own.attributes=merchant_products_v1.ProductAttributes()attributes.title="A Tale of Two Cities"attributes.description="A classic novel about the French Revolution"attributes.link="https://exampleWebsite.com/tale-of-two-cities.html"attributes.image_link="https://exampleWebsite.com/tale-of-two-cities.jpg"attributes.price=priceattributes.availability=Availability.IN_STOCKattributes.condition=Condition.NEWattributes.google_product_category="Media > Books"attributes.gtins=["9780007350896"]attributes.shipping=[shipping_option_1,shipping_option_2]returnmerchant_products_v1.ProductInput(content_language="en",feed_label="GB",offer_id="sku123",product_attributes=attributes,)definsert_product_input():"""Inserts the specified `ProductInput` resource."""# Gets OAuth Credentials.credentials=generate_user_credentials.main()# Creates a client.client=merchant_products_v1.ProductInputsServiceClient(credentials=credentials)# Creates the request.request=merchant_products_v1.InsertProductInputRequest(parent=_PARENT,# If this product is already owned by another datasource, when# re-inserting, the new datasource will take ownership of the product.product_input=create_product_input(),data_source=_DATA_SOURCE_NAME,)# Makes the request and catches and prints any error messages.try:response=client.insert_product_input(request=request)# The last part of the product name will be the product ID assigned to a# product by Google. Product ID has the format# `contentLanguage~feedLabel~offerId`print(f"Input successful:{response}")exceptRuntimeErrorase:print("Input failed")print(e)# After the product is inserted, the product ID will be returned in the# response. We recommend that you check the Merchant Center to ensure that# the product is approved and visible to users before using the product ID# in any downstream processes.if__name__=="__main__":insert_product_input()
/***Insertsaproductintotheproductslist.LogstheAPIresponse.*/functionproductInsert(){//IMPORTANT://EnabletheMerchantAPIProductssub-APIAdvancedServiceandcallit//"MerchantApiProducts"//ReplacethiswithyourMerchantCenterID.constaccountId='INSERT_MERCHANT_ID';//ReplacethiswiththeDataSourceIDyouwanttouse.constdataSourceId='INSERT_DATASOURCE_ID';//Constructtheparentnameconstparent='accounts/'+accountId;//ConstructtheDataSourcenameconstdataSource=parent+'/dataSources/'+dataSourceId;//CreateaproductresourceandinsertitconstproductResource={'offerId':'fromAppsScript','contentLanguage':'en','feedLabel':'US','productAttributes':{'title':'A Tale of Two Cities','description':'A classic novel about the French Revolution','link':'http://my-book-shop.com/tale-of-two-cities.html','imageLink':'http://my-book-shop.com/tale-of-two-cities.jpg','availability':'IN_STOCK','condition':'new','googleProductCategory':'Media > Books','gtins':'[9780007350896]','price':{'amountMicros':'2500000','currencyCode':'USD'},},};try{console.log('Sending insert ProductInput request');//CalltheProductInputs.insertAPImethod.constresponse=MerchantApiProducts.Accounts.ProductInputs.insert(productResource,parent,{dataSource});//RESTfulinsertreturnstheJSONobjectasaresponse.console.log('Inserted ProductInput below');console.log(response);}catch(e){console.log('ERROR!');console.log(e);}}
curl -X POST \"https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}" \-H "Authorization: Bearer <API_TOKEN>" \-H "Content-Type: application/json" \-d '{"offerId": "SKU12345","contentLanguage": "en","feedLabel": "US","productAttributes": {"title": "Classic Cotton T-Shirt","description": "A comfortable, durable, and stylish t-shirt made from 100% cotton.","link": "https://www.example.com/p/SKU12345","imageLink": "https://www.example.com/img/SKU12345.jpg","videoLinks": ["https://www.example.com/videos/SKU12345_1.mp4","https://www.example.com/videos/SKU12345_2.mp4"],"availability": "IN_STOCK","price": {"amountMicros": "15990000","currencyCode": "USD"},"condition": "NEW","gtins": ["9780007350896"]}}'
Add or update product information with a supplemental data source
Use a supplemental data source to provide additional or overriding data for
products that already exist in a primary data source. This is useful for adding
information like promotions, custom labels, or overriding specific product data
without modifying the original product input.
To do this, use theproductInput.insertmethod, but specify thenameof your supplemental data source in thedataSourceparameter. Verify thatofferId,contentLanguage, andfeedLabelmatch an existing product.
This example adds a custom label to an existing product using a supplemental
data source.
POST https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{SUPPLEMENTAL_DATASOURCE_ID}
After this call, the finalProductwill havecustomLabel0set toclearance-sale, assuming the supplemental data source has a higher priority
than the primary data source in your feed rules as defined by thedefault_rule.
Add products asynchronously
To upload a large number of products efficiently, you can send multiple insert
requests concurrently. Instead of waiting for a response to each request before
sending the next, you can send them asynchronously and handle the responses as
they arrive. This approach can significantly improve your data upload
throughput.
The following code samples show how to insert products asynchronously. To learn
about performing multiple requests at once usingcurl, seeSend multiple
requests at
once.
You can set country targeting for individual products to override the settings
from the data source, or to target products when the data source has no
countries defined.
Target countries with theshippingattribute
If your data source doesn't have specific countries defined, you can target
countries for a product by providing theshippingfield withinproductAttributes. This field lets you specify shipping costs and rules for
different countries, implicitly targeting them for serving.
This example targets a product to the US and Canada by providing two separateshippingentries.
POST https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
If your data source already targets multiple countries, you can exclude a
product from showing in a subset of those countries or from specific
destinations.
Use theshoppingAdsExcludedCountriesattribute to prevent a product from
appearing in Shopping ads in specific countries.
Use theexcludedDestinationsattribute to prevent a product from appearing
within specificMarketing
Methods, such asFreeListings.
This example assumes the data source targets the US, Canada, and Mexico. The
request excludes the product from Shopping ads in Mexico and from the Free
Listings destination entirely.
POST https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
{"offerId":"SKU_EXCLUDE_TARGET","contentLanguage":"en","feedLabel":"NA","productAttributes":{"title":"North America T-Shirt","link":"https://www.example.com/p/SKU_EXCLUDE_TARGET","imageLink":"https://www.example.com/img/SKU_EXCLUDE_TARGET.jpg","availability":"IN_STOCK","price":{"amountMicros":"19990000","currencyCode":"USD"},"shoppingAdsExcludedCountries":["MX"],"excludedDestinations":["FREE_LISTINGS"]}}
Get product information
To retrieve the final processed state of a product, use theproducts.getmethod. This method returns theProductresource, which includes allproductAttributesafter feed rules and supplemental data sources have been
applied, along with its current validation status.
There can be a delay of a few minutes between when you insert or update aProductInputand when the finalProductis available to retrieve.
GET https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/products/{PRODUCT_ID}
A successful request returns theProductresource.
{"name":"accounts/{ACCOUNT_ID}/products/{PRODUCT_ID}}","offerId":"SKU12345","contentLanguage":"en","feedLabel":"US","dataSource":"accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}","productAttributes":{"title":"Classic Cotton T-Shirt","description":"A comfortable, durable, and stylish t-shirt made from 100% cotton.","link":"https://www.example.com/p/SKU12345","imageLink":"https://www.example.com/img/SKU12345.jpg","availability":"IN_STOCK","price":{"amountMicros":"15990000","currencyCode":"USD"},"condition":"NEW","gtins":["9780007350896"]},"productStatus":{"destinationStatuses":[{"reportingContext":"SHOPPING_ADS","approvedCountries":["US"]}],"creationDate":"2024-05-20T10:00:00Z","lastUpdateDate":"2024-05-20T10:05:00Z","googleExpirationDate":"2024-06-19T10:05:00Z"}}
The following code samples show how to get a product.
importbase64fromexamples.authenticationimportconfigurationfromexamples.authenticationimportgenerate_user_credentialsfromgoogle.shopping.merchant_products_v1importGetProductRequestfromgoogle.shopping.merchant_products_v1importProductsServiceClient# This is needed for base64url encoding if product IDs contain special# characters such as forward slashes.defencode_product_id(product_id_to_encode:str)->str:"""Base64url encodes a string without padding.Args:product_id_to_encode: The product ID string to encode.Returns:The encoded product ID string."""encoded_bytes=base64.urlsafe_b64encode(product_id_to_encode.encode("utf-8"))returnencoded_bytes.rstrip(b"=").decode("utf-8")defget_product(account_id_arg:str,product_id_arg:str)->None:"""Retrieves a single product from a Merchant Center account.Args:account_id_arg: The ID of the Merchant Center account.product_id_arg: The ID of the product to retrieve."""# Gets OAuth Credentials.credentials=generate_user_credentials.main()# Creates a client.client=ProductsServiceClient(credentials=credentials)# The name has the format: accounts/{account}/products/{product}name=f"accounts/{account_id_arg}/products/{product_id_arg}"# Creates the request.request=GetProductRequest(name=name)print("Sending get product request:")# Makes the request and catches and prints any error messages.try:response=client.get_product(request=request)print("Retrieved Product below")print(response)exceptRuntimeErrorase:print(e)if__name__=="__main__":# Retrieves the configured account ID from the config file.account_id=configuration.Configuration().read_merchant_info()# The ID of the product, which is the final component of the product's# resource name. The product ID is the same as the offer ID.# For example, `en~US~sku123`.product_id="en~US~sku123"# Replace with your actual product ID.# Uncomment the following line if the product ID contains special characters# (such as forward slashes) and needs base64url encoding.# product_id = encode_product_id(product_id)get_product(account_id,product_id)
/***GetaspecificproductforagivenMerchantCenteraccount.*/functiongetProduct(){//IMPORTANT://EnabletheMerchantAPIProductssub-APIAdvancedServiceandcallit//"MerchantApiProducts"//ReplacethiswithyourMerchantCenterID.constaccountId='<MERCHANT_CENTER_ID>';//TheIDoftheproducttoretrieve.//ThisIDisassignedbyGoogleandtypicallyfollowstheformat://contentLanguage~feedLabel~offerId//ReplacewithanactualproductIDfromyourMerchantCenteraccount.constproductId='<PRODUCT_ID>';//Constructtheparentnameconstparent='accounts/'+accountId;//Constructtheproductresourcenameconstname=parent+'/products/'+productId;try{console.log('Sending get Product request');//CalltheProducts.getAPImethod.constproduct=MerchantApiProducts.Accounts.Products.get(name);console.log(product);}catch(e){console.log('ERROR!');console.log(e);}}
curl -X GET \"https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/products/{PRODUCT_ID}" \-H "Authorization: Bearer <API_TOKEN>"
Delete a product from a data source
To delete a product input from a specific data source, use theproductInputs.deletemethod.
If you delete from aprimary data source, the entire product including
its supplementalproductInputsis removed from Merchant Center.
If you delete from asupplemental data source, only the attributes from
that data source are removed from the product. The product itself remains,
sourced from the primary and any other supplemental data sources.
You must specify thedataSourcefrom which you are deleting the product input.
fromexamples.authenticationimportconfigurationfromexamples.authenticationimportgenerate_user_credentialsfromgoogle.shoppingimportmerchant_products_v1_ACCOUNT=configuration.Configuration().read_merchant_info()# ENSURE you fill in the product ID and data source for the# sample to work.# In the format of `contentLanguage~feedLabel~offerId`_PRODUCT="[INSERT_PRODUCT_HERE]"_DATA_SOURCE="[INSERT_DATA_SOURCE_HERE]"_NAME=f"accounts/{_ACCOUNT}/productInputs/{_PRODUCT}"_DATA_SOURCE_NAME=f"accounts/{_ACCOUNT}/dataSources/{_DATA_SOURCE}"defdelete_product_input():"""Deletes the specified `ProductInput` resource."""# Gets OAuth Credentials.credentials=generate_user_credentials.main()# Creates a client.client=merchant_products_v1.ProductInputsServiceClient(credentials=credentials)# Creates the request.request=merchant_products_v1.DeleteProductInputRequest(name=_NAME,data_source=_DATA_SOURCE_NAME)# Makes the request and catch and print any error messages.try:client.delete_product_input(request=request)print("Deletion successful")exceptRuntimeErrorase:print("Deletion failed")print(e)if__name__=="__main__":delete_product_input()
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2026-05-26 UTC."],[],[]]