Migrating from Content API to Merchant API v1: The Complete Developer Guide for 2026

Google announced it will shut down the Content API for Shopping on August 18, 2026. If your integration still sends product data through Content API endpoints, every product listing, every Shopping campaign, and every data pipeline you depend on will break on that date. The Merchant API v1beta version sunsets even sooner -- February 28, 2026 -- meaning developers who adopted the beta must migrate again within weeks.
This is not a cosmetic rename. According to Dataslayer.ai, the Merchant API is a complete rebuild created to support the demands of modern e-commerce. The two-resource model, new data structures, and mandatory GCP registration represent fundamental architectural changes that require careful planning.
At Ekamoira, we have already completed this migration and built our production Commerce Feed Optimizer on Merchant API v1. This guide shares the battle-tested patterns, undocumented gotchas, and real code examples from that implementation -- the kind of practical knowledge you will not find in official documentation alone.
What You'll Learn
The two critical deadlines and what breaks if you miss them
Why GCP registration is the silent migration killer (and how to fix it)
The two-resource model shift from single resource to ProductInput (write) vs Product (read-only)
Before/after code examples for every major structural change
When to use
productInputs.patchvs supplemental data sourcesAI-generated content disclosure requirements (
structured_titleanddigital_source_type)A complete migration checklist with rollback strategy
Rate limits, quota management, and error handling patterns
Summary: Key migration facts at a glance
Metric | Value | Source |
|---|---|---|
Content API sunset date | August 18, 2026 | Search Engine Land, 2025 |
v1beta sunset date | February 28, 2026 | |
Max product updates per day | 2 per product | Google Quotas & Limits, 2026 |
Max sub-account updates per day | 1 per sub-account | Google Quotas & Limits, 2026 |
GTINs per product | Up to 10 (array) | |
Complex migration timeline | 16-20 weeks (4-5 months) | ALMcorp, 2026 |
Official code samples | Java, Python, PHP |
What are the migration deadlines and what happens if you miss them?
There are two distinct deadlines that developers must understand. Each applies to a different starting point, and missing either one has the same catastrophic result: your campaigns stop serving and your product data pipelines break.
Deadline 1: February 28, 2026 -- v1beta sunset. According to Google's latest updates page, the v1beta version of the Merchant API is scheduled for discontinuation on February 28, 2026. All API calls must be directed to v1 and v1alpha versions before this deadline. If you adopted the Merchant API early using v1beta endpoints, you must migrate again to v1.
Deadline 2: August 18, 2026 -- Content API for Shopping sunset. According to Search Engine Land, Google announced it will shut down the Content API for Shopping on August 18, 2026. After this date, the Content API will stop functioning entirely. This is the hard cutoff for all developers still using the legacy API.
Watch Out: According to ALMcorp's migration guide, campaigns relying on product data fed through the old API may stop serving after the cutoff dates. This is not a gradual degradation -- it is an immediate stop.
The business context makes this migration even more urgent. The agentic commerce ecosystem depends on structured, API-accessible product data. AI shopping agents need reliable programmatic access to your product catalog, and Merchant API v1 is the foundation that makes this possible. Merchant API v1 also serves as the data layer for the Universal Commerce Protocol, enabling AI agents to browse and purchase your products autonomously.
According to ALMcorp, high-complexity merchants should plan for 16-20 weeks (4-5 months) for a complete migration. That means if you have a complex setup and you start today (February 2026), you are cutting it dangerously close to the August deadline.
Key Finding: Two deadlines, not one: v1beta sunsets February 28, 2026, and Content API sunsets August 18, 2026. Both result in broken product listings and stalled data pipelines if missed. -- Google Merchant API Latest Updates and ALMcorp
Why is GCP registration the number one undocumented gotcha?
This is the single most painful step in the migration, not because it is difficult, but because it is invisible when missing. API calls fail silently without GCP registration. You will get empty results or cryptic errors, and nothing in the error messages points you toward the actual problem. Developers routinely waste hours debugging this.
According to Google's migration overview, you must create a link between your Google Cloud project and your primary Merchant Center account before any v1 methods will work. The GCP registration samples provide code that demonstrates the developerRegistration:registerGcp endpoint.
Here is what you need to know:
One-time registration per Google Cloud project. You only do this once, but you must do it before any other API call.
Admin privileges required. The person performing the registration needs admin access on the Merchant Center account.
Developer email restrictions. The email address used in registration must be a Gmail or Google Workspace account. Service account emails will not work.
Invitation flow. If the developer email does not already have access to the Merchant Center account, an invitation is sent that must be accepted.
Here is a TypeScript example for GCP registration based on the patterns from Ekamoira's production implementation:
// Step 0: Register GCP - MUST be done before any other Merchant API call
// This creates the link between your Google Cloud project and Merchant Center
async function registerGcp(merchantId: string, developerEmail: string) {
const url = `https://merchantapi.googleapis.com/accounts/v1beta/accounts/${merchantId}/developerRegistration:registerGcp`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${await getAccessToken()}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
// Developer email MUST be Gmail or Google Workspace
// Service account emails will NOT work here
gcpServiceAccountEmail: developerEmail,
}),
});
if (!response.ok) {
const error = await response.json();
// Common error: 403 = not admin on Merchant Center account
// Common error: 400 = email is a service account, not Gmail/Workspace
throw new Error(
`GCP Registration failed: ${error.error?.message || response.statusText}. ` +
`Ensure the email is Gmail/Workspace and you have admin access.`
);
}
console.log('GCP Registration successful. You can now use Merchant API v1.');
return response.json();
}
Pro Tip: Run GCP registration as the very first step of your migration. Add a startup check in your application that verifies registration status before making any product API calls. At Ekamoira, we built this check into our Commerce Feed Optimizer initialization sequence so that new merchant connections never hit the silent failure state.
What is the two-resource model and why does it matter?
The most fundamental conceptual change in Merchant API v1 is the shift from a single resource to a two-resource model. In Content API for Shopping, you had one products resource that handled both reading and writing product data. In Merchant API v1, this splits into two distinct resources.
ProductInput is the write resource. It represents the raw data you submit to Google. When you call productInputs.insert or productInputs.patch, you are writing to this resource. Think of it as your submission layer.
Product is the read-only resource. It represents the final processed result after Google applies its rules, policies, and any supplemental data source merges. When you call products.get or products.list, you are reading from this processed layer.
According to Google's add and manage products guide, after inserting, updating, or deleting a product input, it may take several minutes before the processed product can be retrieved. This processing delay is critical for testing and workflow design.
Aspect | Content API (Legacy) | Merchant API v1 |
|---|---|---|
Write resource |
|
|
Read resource |
|
|
Partial update |
|
|
Data source | Implicit | Explicit |
Processing | Synchronous-like | Asynchronous (several minutes delay) |
Attributes |
|
|
Watch Out: The processing delay between writing a
ProductInputand reading the processedProductis measured in minutes, not milliseconds. Do not write automated tests that insert a product and immediately try to read it -- the product will not exist yet. Build polling or callback patterns into your test harness.
This two-resource model exists because Google now separates your input data from its processed output. This separation allows Google to apply policy rules, merge supplemental feeds, and validate data without modifying your original submission. Merchant API v1 is a traditional REST API -- if you are building AI agent integrations and want to understand how it compares to protocol-based approaches, see our guide on traditional REST APIs vs MCP.
How do data structures change from Content API to Merchant API v1?
The structural changes in Merchant API v1 will break every existing Content API integration that is not updated. Here are the key transformations with before/after code examples.
productAttributes nesting
In Content API, product attributes lived at the top level of the product object. In Merchant API v1, according to the migration overview, the Product.attributes field has been renamed to Product.productAttributes, and all attribute fields must be nested inside this object.
// BEFORE: Content API for Shopping - attributes at top level
const contentApiProduct = {
offerId: 'SKU-12345',
title: 'Premium Running Shoes',
description: 'Lightweight performance running shoes',
link: 'https://example.com/products/running-shoes',
imageLink: 'https://example.com/images/running-shoes.jpg',
price: {
value: '129.99',
currency: 'USD',
},
availability: 'in_stock',
condition: 'new',
brand: 'RunFast',
gtin: '0195937087654', // single value
channel: 'online',
};
// AFTER: Merchant API v1 - attributes nested in productAttributes
const merchantApiProduct = {
name: `accounts/${merchantId}/productInputs/online~en~US~SKU-12345`,
offerId: 'SKU-12345',
feedLabel: 'US',
contentLanguage: 'en',
productAttributes: {
title: 'Premium Running Shoes',
description: 'Lightweight performance running shoes',
link: 'https://example.com/products/running-shoes',
imageLink: 'https://example.com/images/running-shoes.jpg',
price: {
amountMicros: '129990000', // $129.99 in micros
currencyCode: 'USD',
},
availability: 'in_stock',
condition: 'new',
brand: 'RunFast',
gtins: ['0195937087654'], // array, not single value
// channel removed -- use legacyLocal boolean instead
},
};
Price format changes
The price format is one of the most common sources of runtime errors during migration. Content API accepted a simple {value, currency} object. Merchant API v1 requires {amountMicros, currencyCode} where amountMicros is an int64 string representing the price in millionths of the currency unit.
// Price conversion utility for migration
function convertPriceToMicros(value: string, currency: string) {
// Content API: { value: "29.99", currency: "USD" }
// Merchant API v1: { amountMicros: "29990000", currencyCode: "USD" }
const micros = Math.round(parseFloat(value) * 1_000_000);
return {
amountMicros: micros.toString(),
currencyCode: currency,
};
}
// Usage:
const legacyPrice = { value: '129.99', currency: 'USD' };
const v1Price = convertPriceToMicros(legacyPrice.value, legacyPrice.currency);
// Result: { amountMicros: "129990000", currencyCode: "USD" }
GTIN changes
According to the v1beta to v1 migration guide, the gtin field has been renamed to gtins to better reflect that it can hold multiple values. The ProductAttributes reference confirms you can provide up to 10 GTINs per product.
Other structural changes
According to the v1beta to v1 migration guide:
taxesandtaxCategoryfields removed fromproductAttributes-- tax configuration is now handled at the account levelchannelfield removed -- replaced with alegacyLocalboolean for products sold in physical stores
TL;DR:
Nest all attributes inside
productAttributesConvert prices to
amountMicros(int64 string) +currencyCodeChange
gtin(string) togtins(string array, up to 10)Remove
channel, uselegacyLocalboolean for physical storesRemove
taxesandtaxCategoryfrom product-level attributes
How do you insert a product in Merchant API v1?
The productInputs.insert method is the Merchant API v1 replacement for Content API's products.insert. According to Google's add and manage products guide, the insert method requires you to provide the name of your primary data source as the dataSource parameter. The required attributes are feedLabel, contentLanguage, and offerId.
// Inserting a product via Merchant API v1
async function insertProduct(
merchantId: string,
dataSourceId: string,
product: MerchantApiProduct
) {
// dataSource is a REQUIRED query parameter -- Content API did not have this
const dataSource = `accounts/${merchantId}/dataSources/${dataSourceId}`;
const url = `https://merchantapi.googleapis.com/products/v1/accounts/${merchantId}/productInputs:insert?dataSource=${encodeURIComponent(dataSource)}`;
const body = {
offerId: product.offerId,
feedLabel: product.feedLabel, // e.g., "US"
contentLanguage: product.contentLanguage, // e.g., "en"
productAttributes: {
title: product.title,
description: product.description,
link: product.link,
imageLink: product.imageLink,
price: {
amountMicros: product.priceMicros,
currencyCode: product.currencyCode,
},
availability: product.availability,
condition: product.condition,
brand: product.brand,
gtins: product.gtins,
},
};
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${await getAccessToken()}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Product insert failed: ${JSON.stringify(error)}`);
}
// IMPORTANT: The product is NOT immediately available for reading.
// It may take several minutes before the processed Product appears.
const result = await response.json();
console.log(`ProductInput created: ${result.name}`);
return result;
}
Key Finding: Every write operation in Merchant API v1 requires an explicit
dataSourceparameter. This is the single biggest difference from Content API, where the data source was implicit. If you forget this parameter, the API will reject your request immediately. -- Google Add and Manage Products
When should you use productInputs.patch vs supplemental data sources?
Merchant API v1 gives you two distinct approaches for updating product data. Choosing the wrong one can lead to data loss, rate limit exhaustion, or policy violations. Understanding when to use each approach is critical for a successful migration.
productInputs.patch: Direct partial updates
According to Google's frequent updates guide, the productInputs.patch method lets you make partial updates to existing products. You specify which fields to modify using the updateMask parameter -- a comma-separated list of field paths.
According to Google's quotas and limits documentation, you can only update your products up to twice per day. This is a hard limit that cannot be increased.
// Patching a product - update specific fields only
async function patchProduct(
merchantId: string,
dataSourceId: string,
productName: string,
updates: Partial<ProductAttributes>,
updateMask: string[]
) {
const dataSource = `accounts/${merchantId}/dataSources/${dataSourceId}`;
const url = `https://merchantapi.googleapis.com/products/v1/${productName}:patch?dataSource=${encodeURIComponent(dataSource)}&updateMask=${updateMask.join(',')}`;
const body = {
productAttributes: updates,
};
const response = await fetch(url, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${await getAccessToken()}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Product patch failed: ${JSON.stringify(error)}`);
}
return response.json();
}
// Example: Update price and availability only
await patchProduct(
merchantId,
dataSourceId,
`accounts/${merchantId}/productInputs/online~en~US~SKU-12345`,
{
price: { amountMicros: '139990000', currencyCode: 'USD' },
availability: 'out_of_stock',
},
['productAttributes.price', 'productAttributes.availability']
);
Supplemental data sources: Non-destructive enrichments
Supplemental data sources let you layer additional data on top of a merchant's primary feed without modifying the original. This is the approach Ekamoira's Commerce Feed Optimizer uses for AI-driven enrichments because it preserves the merchant's original data and prevents accidental overwrites.
// Step 1: Create a supplemental data source
async function createSupplementalDataSource(
merchantId: string,
displayName: string
) {
const url = `https://merchantapi.googleapis.com/datasources/v1/accounts/${merchantId}/dataSources`;
const body = {
displayName: displayName,
// Supplemental sources merge with primary source data
supplementalProductDataSource: {
feedLabel: 'US',
contentLanguage: 'en',
},
};
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${await getAccessToken()}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
if (!response.ok) {
throw new Error(`Failed to create supplemental data source`);
}
const result = await response.json();
console.log(`Supplemental source created: ${result.name}`);
return result;
}
// Step 2: Insert enrichment via supplemental source
// This adds/overrides specific fields WITHOUT touching the primary feed
async function insertEnrichment(
merchantId: string,
supplementalDataSourceId: string,
offerId: string,
enrichments: Partial<ProductAttributes>
) {
const dataSource = `accounts/${merchantId}/dataSources/${supplementalDataSourceId}`;
const url = `https://merchantapi.googleapis.com/products/v1/accounts/${merchantId}/productInputs:insert?dataSource=${encodeURIComponent(dataSource)}`;
const body = {
offerId: offerId,
feedLabel: 'US',
contentLanguage: 'en',
productAttributes: enrichments,
};
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${await getAccessToken()}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
return response.json();
}
This supplemental data source approach is the foundation of policy-first AI feed optimization, ensuring your AI-driven enrichments do not trigger Google suspensions by keeping them separate from the merchant's original product data.
Decision framework: Patch vs supplemental
Factor | Use | Use Supplemental Data Source |
|---|---|---|
Ownership | You own the primary feed | Merchant owns the primary feed |
Update frequency | Infrequent (2/day limit) | Batch enrichments, no per-product limit |
Data safety | Acceptable to overwrite | Must preserve original data |
Use case | Price/availability updates | Title optimization, description enrichment |
Rollback | Manual revert required | Delete supplemental source to revert |
AI enrichments | Not recommended | Recommended -- non-destructive |
Pro Tip: At Ekamoira, we use supplemental data sources for all AI-generated enrichments (optimized titles, enhanced descriptions, additional product attributes). This way, if an enrichment causes a policy issue, we can remove it without affecting the merchant's original product data. The patch method is reserved for merchant-initiated changes like price and availability updates.
How do you handle AI-generated content in Merchant API v1?
Google requires specific attribution for AI-generated product content. According to Google Merchant Center Help, titles created using generative AI must use the structured_title attribute with the digital_source_type set to trained_algorithmic_media. This requirement applies whether you use Google's own Product Studio or a third-party AI tool.
// Submitting AI-generated titles with required disclosure
const aiEnrichedProduct = {
offerId: 'SKU-12345',
feedLabel: 'US',
contentLanguage: 'en',
productAttributes: {
// Standard title still required as fallback
title: 'Running Shoes - Premium Lightweight',
// AI-generated title with required disclosure
structuredTitle: {
digitalSourceType: 'trained_algorithmic_media',
content: 'RunFast Premium Lightweight Running Shoes for Marathon Training - Breathable Mesh, Carbon Plate, Size 10',
},
// AI-generated description (same pattern)
structuredDescription: {
digitalSourceType: 'trained_algorithmic_media',
content: 'Engineered for marathon distance with breathable mesh upper, carbon fiber plate for energy return, and responsive foam midsole. Available in 8 colorways.',
},
},
};
Watch Out: If you are using AI to optimize product titles or descriptions -- whether through your own models, Ekamoira's Commerce Feed Optimizer, or Google's Product Studio -- you must include the
digital_source_typedisclosure. Failing to do so risks policy violations that could lead to product disapprovals or account suspensions.
According to Google's Product Studio documentation, Product Studio is a suite of generative-AI tools that simplifies merchant workflows including generating SEO-optimized titles for products. The Product Studio Text API is currently in a controlled alpha launch and requires allowlist access and a Google Cloud project.
How do you check product status and diagnose issues?
After submitting products through Merchant API v1, you need to monitor their approval status. According to Google's product issues guide, the itemLevelIssues array contains data validation and policy issues found for each product. You can query the ProductView table to filter products by their approval status.
// Check product status and identify issues
async function getProductStatus(merchantId: string, productName: string) {
const url = `https://merchantapi.googleapis.com/products/v1/${productName}`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${await getAccessToken()}`,
},
});
if (!response.ok) {
throw new Error(`Failed to get product: ${response.statusText}`);
}
const product = await response.json();
// Check for issues
if (product.productStatus?.itemLevelIssues?.length > 0) {
for (const issue of product.productStatus.itemLevelIssues) {
console.log(`Issue: ${issue.code}`);
console.log(`Description: ${issue.description}`);
console.log(`Severity: ${issue.severity}`);
// severity: DISAPPROVED means the product cannot serve ads
if (issue.severity === 'DISAPPROVED') {
console.error(`CRITICAL: Product ${productName} is disapproved.`);
}
}
}
return product;
}
// Filter disapproved products across your catalog using ProductView
async function listDisapprovedProducts(merchantId: string) {
const url = `https://merchantapi.googleapis.com/reports/v1/accounts/${merchantId}/reports:search`;
const body = {
query: `
SELECT
product_view.id,
product_view.title,
product_view.aggregated_reporting_context_status
FROM ProductView
WHERE aggregated_reporting_context_status = 'NOT_ELIGIBLE_OR_DISAPPROVED'
`,
};
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${await getAccessToken()}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
return response.json();
}
Pro Tip: Build automated monitoring that runs the disapproved products query daily. At Ekamoira, our Commerce Feed Optimizer checks
itemLevelIssuesafter every enrichment cycle and automatically rolls back any AI-generated content that triggers policy disapprovals -- this is a core part of our policy-first architecture.
What are the rate limits and how do you manage quotas?
Merchant API v1 introduces a dynamic quota system that differs significantly from Content API's static limits. According to Google's quotas and limits documentation, the Merchant API automatically adjusts call quotas for your products and accounts based on your usage patterns.
Key limits confirmed in the documentation:
Maximum 2 updates per product per day -- this is a hard limit
Maximum 1 update per sub-account per day -- critical for MCA setups
Each request counts once, regardless of its type or items returned
Dynamic adjustment -- the system increases or decreases your quota based on usage patterns
When you exceed quotas, the API returns specific error codes:
quota/request_rate_too_high-- you are making requests too quicklyquota/daily_limit_exceeded-- you have hit your daily maximum
// Rate-limit-aware product update with exponential backoff
async function rateLimitedUpdate(
merchantId: string,
dataSourceId: string,
updates: ProductUpdate[],
maxConcurrent: number = 5
) {
const results: UpdateResult[] = [];
// Process in batches to respect rate limits
for (let i = 0; i < updates.length; i += maxConcurrent) {
const batch = updates.slice(i, i + maxConcurrent);
const batchResults = await Promise.allSettled(
batch.map(async (update) => {
let retries = 0;
const maxRetries = 3;
while (retries < maxRetries) {
try {
return await patchProduct(
merchantId,
dataSourceId,
update.productName,
update.attributes,
update.updateMask
);
} catch (error: any) {
if (error.message.includes('quota/request_rate_too_high')) {
retries++;
// Exponential backoff: 1s, 2s, 4s
const delay = Math.pow(2, retries) * 1000;
console.log(`Rate limited. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
} else if (error.message.includes('quota/daily_limit_exceeded')) {
throw new Error(
`Daily quota exceeded for ${update.productName}. ` +
`Max 2 updates per product per day.`
);
} else {
throw error;
}
}
}
throw new Error(`Max retries exceeded for ${update.productName}`);
})
);
results.push(...batchResults);
// Pause between batches to avoid rate limiting
if (i + maxConcurrent < updates.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
return results;
}
What does a complete migration checklist look like?
Based on Ekamoira's production migration experience and the patterns documented in the Google migration overview and v1beta to v1 migration guide, here is a comprehensive step-by-step checklist. Google confirms that you can migrate in stages, updating one API at a time.
Phase 1: Preparation (Week 1-2)
Audit your existing Content API integration. Document every endpoint you use, every product attribute you send, and every batch operation you perform. Map these to their Merchant API v1 equivalents.
Complete GCP registration. Call
developerRegistration:registerGcpwith a Gmail or Google Workspace email. Verify admin access on the Merchant Center account first.Identify your data source IDs. Merchant API v1 requires explicit data source parameters for every write operation. Find your primary data source ID in Merchant Center.
Set up a test environment. Create a sandbox Merchant Center account or use a limited product subset for testing.
Phase 2: Code migration (Week 3-8)
Update authentication. Ensure your OAuth2 scopes include
https://www.googleapis.com/auth/content(same scope, new endpoints).Migrate product insert logic. Replace
products.insertwithproductInputs.insert. Add thedataSourceparameter. Nest all attributes insideproductAttributes.Convert price format. Replace
{value, currency}with{amountMicros, currencyCode}. Build and test the conversion utility.Update GTIN handling. Change
gtin(string) togtins(string array).Remove deprecated fields. Delete
channel,taxes, andtaxCategoryfrom product-level attributes. UselegacyLocalfor physical store products.Migrate update logic. Replace
products.updatewithproductInputs.patchusingupdateMask. Respect the 2-updates-per-product-per-day limit.Add processing delay handling. Build polling or retry logic to handle the several-minute delay between write and read.
Phase 3: Testing and validation (Week 9-12)
Test with a small product set. Insert 10-20 products through the new API. Wait for processing, then verify they appear correctly.
Validate product status. Check
itemLevelIssuesfor every test product. Confirm no new disapprovals compared to Content API.Run parallel operations. Send the same products through both Content API and Merchant API v1. Compare results to ensure parity.
Test error handling. Deliberately trigger rate limits and quota errors to verify your retry logic works.
Phase 4: Cutover and monitoring (Week 13-16+)
Switch production traffic gradually. Route 10%, then 50%, then 100% of your product updates through Merchant API v1.
Monitor for errors. Watch for
quota/request_rate_too_highand disapproval spikes.Keep Content API as fallback. Maintain your Content API integration until well past the switchover. Only decommission it once Merchant API v1 is proven stable in production.
Document rollback triggers. Define specific error thresholds that trigger a rollback to Content API (e.g., disapproval rate exceeding 5%, processing delay exceeding 30 minutes).
Key Finding: According to ALMcorp, high-complexity merchants should plan for 16-20 weeks total. Simpler integrations may complete in less time, but do not underestimate the testing and validation phases.
What common errors will you encounter and how do you fix them?
Based on Ekamoira's production implementation and the verified documentation, here are the most common errors and their solutions:
Error | Root Cause | Fix |
|---|---|---|
Empty API response / no data | GCP registration not completed | Run |
| Attributes not nested correctly | Move all attributes inside |
Invalid price format | Using | Convert to micros (multiply by 1,000,000) |
| Too many concurrent requests | Add exponential backoff, reduce concurrency |
| More than 2 updates/product/day | Batch updates, prioritize which products need updates |
Product not found after insert | Processing delay (several minutes) | Wait and poll, do not read immediately after write |
Missing | Forgot to include in API call | Add |
GTIN validation error | Sending single string instead of array | Change |
Tax-related errors |
| Remove from product level, configure at account level |
Watch Out: The silent failure from missing GCP registration is the most dangerous error because it does not produce a clear error message. If your API calls return empty results or generic authentication errors after migrating to v1, check GCP registration first. This saved us hours of debugging at Ekamoira.
Frequently asked questions
When exactly does Content API for Shopping shut down?
According to Search Engine Land, Google announced it will shut down the Content API for Shopping on August 18, 2026. After this date, the API will stop functioning entirely, and any integrations still using it will break. This deadline is non-negotiable and affects all developers and platforms using Content API endpoints.
What happens if I do not migrate by the deadline?
According to ALMcorp, campaigns relying on product data fed through the old API may stop serving after the cutoff dates. Your product listings will become stale, data pipelines will break, and Shopping campaigns will stop delivering. There is no grace period after August 18, 2026.
Do I need a new Google Cloud project for Merchant API v1?
No. You can use your existing Google Cloud project. However, you must perform a one-time GCP registration to link that project to your Merchant Center account. This step is required before any Merchant API v1 calls will work, according to the Google migration overview.
Can I use both Content API and Merchant API v1 during the migration?
Yes. Google supports running both APIs simultaneously during the transition period. According to the v1beta to v1 migration guide, you can migrate in stages, updating one API at a time. This allows you to test Merchant API v1 while keeping Content API as a fallback.
What is the difference between ProductInput and Product?
ProductInput is the write resource where you submit your raw product data. Product is the read-only resource that represents the final processed result after Google applies rules, policies, and supplemental data source merges. According to Google's add and manage products guide, it may take several minutes after writing a ProductInput before the processed Product can be retrieved.
How long does GCP registration take?
The API call itself completes in seconds. However, the overall process -- ensuring admin access, using the correct email type (Gmail or Google Workspace, not service account), and accepting any invitations -- can take longer. Plan for 30 minutes to an hour for the entire registration process, including verification.
How do rate limits work in Merchant API v1?
According to Google's quotas and limits documentation, you can update each product a maximum of 2 times per day and each sub-account a maximum of 1 time per day. The system dynamically adjusts overall call quotas based on your usage patterns. Each request counts once, regardless of its type.
Do I need to migrate if I use Feedonomics, DataFeedWatch, or GoDataFeed?
According to ALMcorp, if you use feed management platforms, contact their support teams. Many platforms are handling the migration on their end, but you should verify directly with your provider and understand their timeline to ensure coverage before the deadline.
How do I handle AI-generated product titles in Merchant API v1?
According to Google Merchant Center Help, titles created using generative AI must use the structured_title attribute with the digital_source_type set to trained_algorithmic_media. The same pattern applies to AI-generated descriptions using the structured_description attribute.
Where can I find official code examples?
Google maintains a Merchant API samples repository on GitHub with code examples in Java, Python, and PHP. The repository also includes migration assistance tools. For TypeScript/JavaScript examples, Ekamoira's Commerce Feed Optimizer implementation serves as a production reference.
What is the dataSource parameter and why is it required?
The dataSource parameter tells Merchant API v1 which data source (primary or supplemental) should receive your product data. According to Google's add and manage products guide, the productInputs.insert method requires you to provide the name of your data source. Content API did not have this concept -- it was an implicit single source.
How do I handle multi-client accounts (MCA)?
MCA setups require passing both the merchantId (sub-account) and aggregatorId (parent account) parameters. The API response structure also differs for MCA accounts. Test your MCA handling thoroughly during migration, as the parameter naming conventions have changed from Content API.
What happens to the channel field?
According to the v1beta to v1 migration guide, the channel field has been removed from Merchant API v1. It is replaced by a legacyLocal boolean for products sold in physical stores. Online-only products do not need this field at all.
Can I roll back to Content API if migration fails?
Yes, during the transition period (before August 18, 2026). Keep your Content API integration code and data pipelines intact until Merchant API v1 is verified in production. Define specific rollback triggers such as disapproval rate spikes or processing timeout patterns. After the August deadline, rollback is no longer possible.
How does Ekamoira's Commerce Feed Optimizer use Merchant API v1?
Ekamoira's Commerce Feed Optimizer is a production system built entirely on Merchant API v1. It uses supplemental data sources for non-destructive AI enrichments, productInputs.patch for merchant-initiated updates, and automated itemLevelIssues monitoring to prevent policy violations. The optimizer completed the full migration and serves as a battle-tested reference implementation.
Sources
Search Engine Land (2025). "Google replaces Content API for Shopping with new Merchant API." https://searchengineland.com/google-content-api-shopping-new-merchant-api-460937
Google for Developers (2025). "Migrate from Content API for Shopping to Merchant API." https://developers.google.com/merchant/api/guides/compatibility/overview
Google for Developers (2025). "Latest updates | Merchant API." https://developers.google.com/merchant/api/latest-updates
Google for Developers (2025). "Migrate from v1beta to v1 | Merchant API." https://developers.google.com/merchant/api/guides/compatibility/migrate-v1beta-v1
Google for Developers (2025). "Register GCP | Merchant API." https://developers.google.com/merchant/api/samples/register-gcp
Google for Developers (2026). "Add and manage products | Merchant API." https://developers.google.com/merchant/api/guides/products/add-manage
Google for Developers (2025). "Make frequent updates to your products | Merchant API." https://developers.google.com/merchant/api/guides/products/frequent-updates
Google for Developers (2026). "Quotas and limits | Merchant API." https://developers.google.com/merchant/api/guides/quotas-limits
Dataslayer.ai (2025). "Google Merchant API Migration: Key Changes, Deadlines, and How to Prepare." https://www.dataslayer.ai/blog/new-google-merchant-api
ALMcorp (2026). "Google Shopping API Migration Deadline: February 28 & August 18, 2026 Guide." https://almcorp.com/blog/google-shopping-api-migration-deadline-2026/
Google for Developers (2025). "ProductAttributes | Merchant API." https://developers.google.com/merchant/api/reference/rest/products_v1/ProductAttributes
Google Merchant Center Help (2025). "AI-generated content." https://support.google.com/merchants/answer/14743464
Google for Developers (2025). "How to Use the Product Studio Text API." https://developers.google.com/product-studio/docs/onboarding
Google (2025). "Merchant API Samples Repository." https://github.com/google/merchant-api-samples
Google for Developers (2025). "List your products data and product issues | Merchant API." https://developers.google.com/merchant/api/guides/products/list-products-data-issues
Ready to optimize your product feeds on Merchant API v1?
Ekamoira's Commerce Feed Optimizer is built on Merchant API v1 with supplemental data sources, policy-first AI enrichments, and automated issue monitoring. Skip the migration pain -- we have already done it. Start Free
Once your Merchant API integration is live, explore our protocol comparison to decide whether to adopt UCP, MCP, or A2A for your agentic commerce strategy.
About the Author

Co-founder of Ekamoira. Building AI-powered SEO tools to help brands achieve visibility in the age of generative search.
of brands invisible in AI
Our proprietary Query Fan-Out Formula predicts exactly which content AI will cite. Get visible in your topic cluster within 30 days.
Free 15-min strategy session · No commitment
Related Articles

The Policy-First Architecture: Building AI Feed Optimizers That Don't Get Suspended in 2026
Policy-first AI feed optimization prioritizes Google Merchant Center compliance and sustainable growth over aggressive performance maximization. This guide covers the 4-layer enrichment system, MC-First architecture, and proven strategies to prevent feed suspensions while improving visibility.

UCP vs MCP vs A2A: Which AI Commerce Protocol Should You Adopt in 2026? (Complete Comparison + Decision Matrix)
With more than 10,000 active public MCP servers now deployed and UCP launching in January 2026, retailers face a critical question: which protocol deserves your...

What Is Agentic Commerce? 45% of Shoppers Use AI (2026)
According to the IBM Institute for Business Value (January 2026), 45% of consumers already use AI for at least part of their buying journey.