Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Access the Google Merchant Center API with managed OAuth authentication. Manage products, inventories, promotions, data sources, and reports for Google Shopping.
.claude/skills/google-merchant/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 315% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 363% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 226% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 438% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 394% | 0% |
Access the Google Merchant Center API with managed OAuth authentication. Manage products, inventories, promotions, data sources, and reports for Google Shopping.
bash# List products in your Merchant Center account python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/google-merchant/products/v1/accounts/{accountId}/products') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
https://gateway.maton.ai/google-merchant/{sub-api}/{version}/accounts/{accountId}/{resource}The Merchant API uses a modular sub-API structure. Replace:
{sub-api} with the service: products, accounts, datasources, reports, promotions, inventories, notifications, conversions{version} with v1{accountId} with your Merchant Center account IDThe gateway proxies requests to merchantapi.googleapis.com and automatically injects your OAuth token.
Important: The v1 API requires one-time developer registration. See Developer Registration section.
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEYEnvironment Variable: Set your API key as MATON_API_KEY:
bashexport MATON_API_KEY="YOUR_API_KEY"
Your Merchant Center account ID is a numeric identifier. To find it:
https://merchants.google.com/mc/overview?a=ACCOUNT_IDImportant: Before using the v1 API, you must complete a one-time developer registration to associate your account with the API.
Option A: Try fetching via API first
Try listing accounts using the v1beta endpoint. If this works, you can get your account ID automatically:
bashpython <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/google-merchant/accounts/v1beta/accounts') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') try: result = json.load(urllib.request.urlopen(req)) for account in result.get('accounts', []): print(f"Account ID: {account['accountId']}, Name: {account['accountName']}") except Exception as e: print(f"v1beta not available - use Option B to get your account ID manually") EOF
Option B: From Merchant Center UI (if Option A fails)
If the v1beta endpoint is unavailable or returns an error:
https://merchants.google.com/mc/overview?a=YOUR_ACCOUNT_IDFor example, if your URL is https://merchants.google.com/mc/overview?a=123456789, your account ID is 123456789.
Call the registerGcp endpoint with your account ID and email:
bashpython <<'EOF' import urllib.request, os, json account_id = 'YOUR_ACCOUNT_ID' # From Step 1 developer_email = 'your-email@example.com' # Your Google account email data = json.dumps({'developerEmail': developer_email}).encode() req = urllib.request.Request( f'https://gateway.maton.ai/google-merchant/accounts/v1/accounts/{account_id}/developerRegistration:registerGcp', data=data, method='POST' ) req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') result = json.load(urllib.request.urlopen(req)) print(json.dumps(result, indent=2)) EOF
Response:
json{ "name": "accounts/123456789/developerRegistration", "gcpIds": ["216141799266"] }
After registration, v1 endpoints will work:
bashpython <<'EOF' import urllib.request, os, json account_id = 'YOUR_ACCOUNT_ID' req = urllib.request.Request(f'https://gateway.maton.ai/google-merchant/accounts/v1/accounts/{account_id}') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Note: Registration only needs to be done once per Merchant Center account. After registration, all v1 endpoints will work for that account.
Manage your Google Merchant OAuth connections at https://ctrl.maton.ai.
bashpython <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections?app=google-merchant&status=ACTIVE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
bashpython <<'EOF' import urllib.request, os, json data = json.dumps({'app': 'google-merchant'}).encode() req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
bashpython <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Response:
json{ "connection": { "connection_id": "00726960-095e-47e2-92e6-6e9cdf3e40a1", "status": "ACTIVE", "creation_time": "2026-02-07T06:41:22.751289Z", "last_updated_time": "2026-02-07T06:42:29.411979Z", "url": "https://connect.maton.ai/?session_token=...", "app": "google-merchant", "metadata": {} } }
Open the returned url in a browser to complete OAuth authorization.
bashpython <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
If you have multiple Google Merchant connections, specify which one to use with the Maton-Connection header:
bashpython <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/google-merchant/products/v1/accounts/123456/products') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Maton-Connection', '00726960-095e-47e2-92e6-6e9cdf3e40a1') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
If omitted, the gateway uses the default (oldest) active connection.
The Merchant API is organized into sub-APIs:
| Sub-API | Purpose | Version | |---------|---------|---------| | products | Product catalog management | v1 | | accounts | Account settings and users | v1 | | datasources | Data source configuration | v1 | | reports | Analytics and reporting | v1 | | promotions | Promotional offers (requires enrollment) | v1 | | inventories | Local and regional inventory | v1 | | notifications | Webhook subscriptions | v1 | | conversions | Conversion tracking | v1 |
bashGET /google-merchant/accounts/v1/accounts
Returns all Merchant Center accounts accessible with your OAuth credentials. Use this to find your account ID.
bashGET /google-merchant/accounts/v1/accounts/{accountId}
bashGET /google-merchant/accounts/v1/accounts/{accountId}:listSubaccounts
Note: This endpoint only works for multi-client accounts (MCAs). Standard merchant accounts will receive a 403 error.
bashGET /google-merchant/accounts/v1/accounts/{accountId}/businessInfo
bashPATCH /google-merchant/accounts/v1/accounts/{accountId}/businessInfo?updateMask=customerService Content-Type: application/json { "customerService": { "email": "support@example.com" } }
bashGET /google-merchant/accounts/v1/accounts/{accountId}/homepage
bashGET /google-merchant/accounts/v1/accounts/{accountId}/shippingSettings
bashPOST /google-merchant/accounts/v1/accounts/{accountId}/shippingSettings:insert Content-Type: application/json { "services": [ { "serviceName": "Standard Shipping", "deliveryCountries": ["US"], "currencyCode": "USD", "deliveryTime": { "minTransitDays": 3, "maxTransitDays": 7, "minHandlingDays": 0, "maxHandlingDays": 1 }, "rateGroups": [ { "singleValue": { "flatRate": { "amountMicros": "0", "currencyCode": "USD" } } } ], "active": true } ] }
bashGET /google-merchant/accounts/v1/accounts/{accountId}/users
bashGET /google-merchant/accounts/v1/accounts/{accountId}/users/{email}
bashGET /google-merchant/accounts/v1/accounts/{accountId}/programs
bashGET /google-merchant/accounts/v1/accounts/{accountId}/regions
bashGET /google-merchant/accounts/v1/accounts/{accountId}/issues
bashGET /google-merchant/accounts/v1/accounts/{accountId}/onlineReturnPolicies
bashGET /google-merchant/products/v1/accounts/{accountId}/products
Query parameters:
pageSize (integer): Maximum results per pagepageToken (string): Pagination tokenbashGET /google-merchant/products/v1/accounts/{accountId}/products/{productId}
Product ID format: contentLanguage~feedLabel~offerId (e.g., en~US~sku123)
bashPOST /google-merchant/products/v1/accounts/{accountId}/productInputs:insert?dataSource=accounts/{accountId}/dataSources/{dataSourceId} Content-Type: application/json { "offerId": "sku123", "contentLanguage": "en", "feedLabel": "US", "productAttributes": { "title": "Product Title", "description": "Product description", "link": "https://example.com/product", "imageLink": "https://example.com/image.jpg", "availability": "in_stock", "price": { "amountMicros": "19990000", "currencyCode": "USD" }, "condition": "new" } }
Note: Products can only be inserted into data sources with input: "API" type. Create an API data source first if needed.
bashDELETE /google-merchant/products/v1/accounts/{accountId}/productInputs/{productId}?dataSource=accounts/{accountId}/dataSources/{dataSourceId}
bashGET /google-merchant/inventories/v1/accounts/{accountId}/products/{productId}/localInventories
Note: Local inventories are only available for products with LOCAL channel. Use a product ID like local~en~US~sku123.
bashPOST /google-merchant/inventories/v1/accounts/{accountId}/products/{productId}/localInventories:insert Content-Type: application/json { "storeCode": "store123" }
Note: The storeCode must be a valid store code configured in your Merchant Center account. Additional inventory attributes may be available - refer to the Google Merchant API Reference for the complete field list.
bashGET /google-merchant/inventories/v1/accounts/{accountId}/products/{productId}/regionalInventories
bashGET /google-merchant/datasources/v1/accounts/{accountId}/dataSources
bashGET /google-merchant/datasources/v1/accounts/{accountId}/dataSources/{dataSourceId}
bashPOST /google-merchant/datasources/v1/accounts/{accountId}/dataSources Content-Type: application/json { "displayName": "API Data Source", "primaryProductDataSource": { "feedLabel": "US", "contentLanguage": "en" } }
Response:
json{ "name": "accounts/123456/dataSources/789", "dataSourceId": "789", "displayName": "API Data Source", "primaryProductDataSource": { "feedLabel": "US", "contentLanguage": "en" }, "input": "API" }
bashPATCH /google-merchant/datasources/v1/accounts/{accountId}/dataSources/{dataSourceId}?updateMask=displayName Content-Type: application/json { "displayName": "Updated Name" }
bashDELETE /google-merchant/datasources/v1/accounts/{accountId}/dataSources/{dataSourceId}
bashPOST /google-merchant/datasources/v1/accounts/{accountId}/dataSources/{dataSourceId}:fetch
Note: Fetch only works for data sources with FILE input type. API and UI data sources cannot be fetched.
bashPOST /google-merchant/reports/v1/accounts/{accountId}/reports:search Content-Type: application/json { "query": "SELECT offer_id, title, clicks, impressions FROM product_performance_view WHERE date BETWEEN '2026-01-01' AND '2026-01-31'" }
Example: Query product_view (requires id field):
json{ "query": "SELECT id, offer_id, title, item_issues FROM product_view LIMIT 10" }
Note: The product_view table requires the id field in the SELECT clause.
Available report tables:
product_performance_view - Clicks, impressions, CTR by productproduct_view - Current inventory with attributes and issues (requires id in SELECT)price_competitiveness_product_view - Pricing vs competitors (requires Market Insights)price_insights_product_view - Suggested pricingbest_sellers_product_cluster_view - Best sellers by category (requires Market Insights)competitive_visibility_competitor_view - Competitor visibilityNote: Promotions require your Merchant Center account to be enrolled in the Promotions program. You'll receive a 403 error if not enrolled.
bashGET /google-merchant/promotions/v1/accounts/{accountId}/promotions
bashGET /google-merchant/promotions/v1/accounts/{accountId}/promotions/{promotionId}
bashPOST /google-merchant/promotions/v1/accounts/{accountId}/promotions:insert Content-Type: application/json { "promotionId": "promo123", "contentLanguage": "en", "targetCountry": "US", "redemptionChannel": ["ONLINE"], "attributes": { "longTitle": "20% off all products", "promotionEffectiveDates": "2026-02-01T00:00:00Z/2026-02-28T23:59:59Z" } }
bashGET /google-merchant/notifications/v1/accounts/{accountId}/notificationsubscriptions
bashPOST /google-merchant/notifications/v1/accounts/{accountId}/notificationsubscriptions Content-Type: application/json { "registeredEvent": "PRODUCT_STATUS_CHANGE", "callBackUri": "https://example.com/webhook", "allManagedAccounts": true }
Note: You must specify either allManagedAccounts: true OR targetAccount: "accounts/{accountId}" to indicate which accounts the subscription applies to.
Alternative with targetAccount:
json{ "registeredEvent": "PRODUCT_STATUS_CHANGE", "callBackUri": "https://example.com/webhook", "targetAccount": "accounts/123456789" }
bashDELETE /google-merchant/notifications/v1/accounts/{accountId}/notificationsubscriptions/{subscriptionId}
bashGET /google-merchant/conversions/v1/accounts/{accountId}/conversionSources
bashPOST /google-merchant/conversions/v1/accounts/{accountId}/conversionSources Content-Type: application/json { "merchantCenterDestination": { "displayName": "My Conversion Source", "destination": "SHOPPING_ADS", "currencyCode": "USD", "attributionSettings": { "attributionLookbackWindowDays": 30, "attributionModel": "CROSS_CHANNEL_LAST_CLICK" } } }
bashDELETE /google-merchant/conversions/v1/accounts/{accountId}/conversionSources/{conversionSourceId}
The API uses token-based pagination:
bashGET /google-merchant/products/v1/accounts/{accountId}/products?pageSize=50
Response includes nextPageToken when more results exist:
json{ "products": [...], "nextPageToken": "CAE..." }
Use the token for the next page:
bashGET /google-merchant/products/v1/accounts/{accountId}/products?pageSize=50&pageToken=CAE...
javascriptconst accountId = '123456789'; const response = await fetch( `https://gateway.maton.ai/google-merchant/products/v1/accounts/${accountId}/products`, { headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}` } } ); const data = await response.json();
pythonimport os import requests account_id = '123456789' response = requests.get( f'https://gateway.maton.ai/google-merchant/products/v1/accounts/{account_id}/products', headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'} ) data = response.json()
contentLanguage~feedLabel~offerId (e.g., en~US~sku123)input: "API" typeLOCAL channel (not ONLINE)curl -g when URLs contain brackets to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments| Status | Meaning | |--------|---------| | 400 | Invalid request or missing Google Merchant connection | | 401 | Invalid/missing Maton API key, or GCP project not registered (see Developer Registration) | | 403 | Permission denied - account not enrolled in required program or feature not available | | 404 | Resource not found | | 429 | Rate limited | | 4xx/5xx | Passthrough error from Google Merchant API |
"GCP project is not registered": You need to complete developer registration. See Developer Registration section.
"The caller does not have access to the accounts": The specified account ID is not accessible with your OAuth credentials. Verify you have access to the Merchant Center account.
"Promotion program not enabled": Your Merchant Center account is not enrolled in the Promotions program. Enable it in Merchant Center settings.
"This method can only be accessed by multi-client accounts": You're calling an endpoint (like listSubaccounts) that only works for multi-client accounts (MCAs).
"Mismatched channel": You're trying to access local inventories for an ONLINE product. Local inventories only work with LOCAL channel products.
MATON_API_KEY environment variable is set:bashecho $MATON_API_KEY
bashpython <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Ensure your URL path starts with google-merchant. For example:
https://gateway.maton.ai/google-merchant/products/v1/accounts/{accountId}/productshttps://gateway.maton.ai/products/v1/accounts/{accountId}/productsIf you see an error like "GCP project is not registered with the merchant account":
?a=)registerGcp endpoint with your account ID and email| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 10,120 | 5,709 | -44% | 1 | 1 | 0% | 1,817 | 7,549 | +315% | 0 | 0 | — |
case-02 | fail→pass | 7,990 | 3,279 | -59% | 1 | 1 | 0% | 1,515 | 7,009 | +363% | 0 | 0 | — |
case-03 | fail→pass | 10,766 | 6,581 | -39% | 1 | 1 | 0% | 2,398 | 7,813 | +226% | 0 | 0 | — |
case-04 | fail→fail | 15,838 | 10,898 | -31% | 1 | 1 | 0% | 3,245 | 8,589 | +165% | 0 | 0 | — |
case-05 | fail→fail | 15,748 | 12,756 | -19% | 1 | 1 | 0% | 3,292 | 9,038 | +175% | 0 | 0 | — |
case-06 | fail→fail | 9,899 | 14,097 | +42% | 1 | 1 | 0% | 2,130 | 8,763 | +311% | 0 | 0 | — |
case-07 | fail→pass | 5,215 | 4,601 | -12% | 1 | 1 | 0% | 1,380 | 7,422 | +438% | 0 | 0 | — |
case-08 | fail→pass | 7,090 | 3,545 | -50% | 1 | 1 | 0% | 1,426 | 7,045 | +394% | 0 | 0 | — |
case-09 | fail→pass | 9,492 | 3,865 | -59% | 1 | 1 | 0% | 2,120 | 7,173 | +238% | 0 | 0 | — |
case-10 | fail→pass | 5,767 | 5,444 | -6% | 1 | 1 | 0% | 1,171 | 7,552 | +545% | 0 | 0 | — |
case-11 | fail→pass | 6,404 | 4,492 | -30% | 1 | 1 | 0% | 1,312 | 7,204 | +449% | 0 | 0 | — |
case-12 | fail→pass | 8,955 | 2,354 | -74% | 1 | 1 | 0% | 1,581 | 6,700 | +324% | 0 | 0 | — |
case-13 | fail→pass | 5,855 | 5,091 | -13% | 1 | 1 | 0% | 1,168 | 7,440 | +537% | 0 | 0 | — |
case-14 | fail→pass | 6,730 | 4,967 | -26% | 1 | 1 | 0% | 1,624 | 7,438 | +358% | 0 | 0 | — |
case-15 | fail→pass | 5,442 | 4,640 | -15% | 1 | 1 | 0% | 1,081 | 7,275 | +573% | 0 | 0 | — |
case-16 | fail→pass | 4,925 | 4,025 | -18% | 1 | 1 | 0% | 945 | 6,987 | +639% | 0 | 0 | — |
case-17 | fail→pass | 11,291 | 6,181 | -45% | 1 | 1 | 0% | 2,507 | 6,888 | +175% | 0 | 0 | — |
case-18 | fail→pass | 7,482 | 7,919 | +6% | 1 | 1 | 0% | 1,617 | 8,229 | +409% | 0 | 0 | — |
case-19 | fail→pass | 9,200 | 3,912 | -57% | 1 | 1 | 0% | 1,826 | 7,175 | +293% | 0 | 0 | — |
case-20 | fail→fail | 3,392 | 2,246 | -34% | 1 | 1 | 0% | 606 | 6,753 | +1014% | 0 | 0 | — |
case-21 | fail→pass | 12,604 | 4,848 | -62% | 1 | 1 | 0% | 2,535 | 7,187 | +184% | 0 | 0 | — |
case-22 | fail→pass | 8,558 | 10,164 | +19% | 1 | 1 | 0% | 1,661 | 7,695 | +363% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +82 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.