shopify-product-upsert
POST
/api/v1/shopify-product-upsert
1 credits/call
shopify
catalog
Create or update one Shopify product by style code, set its stock, and publish it to every sales channel. Idempotent.
Sign in + create an API key on the keys page to authenticate calls.
curl -X POST https://api.fulcrumgo.com/api/v1/shopify-product-upsert \
-H "Authorization: Bearer mcpsk_<your_api_key>" \
-H "Content-Type: application/json" \
-d '{
"style_code": "",
"title": "",
"vendor": "",
"product_type": "",
"variants": [],
"description_html": "",
"category_id": "",
"status": "ACTIVE",
"publish": true,
"allow_new_vendor": false
}'
Add this server to Claude Desktop's claude_desktop_config.json. The endpoint becomes a callable tool inside Claude. See the MCP setup guide for the full walk-through.
{
"mcpServers": {
"this-api": {
"url": "https://api.fulcrumgo.com/mcp",
"transport": "http",
"auth": {
"type": "bearer",
"token": "mcpsk_<your_api_key>"
}
}
}
}
Inside Claude this endpoint surfaces as the tool shopify-product-upsert.
Standard requests — no custom SDK needed. pip install requests first.
import requests
r = requests.post(
"https://api.fulcrumgo.com/api/v1/shopify-product-upsert",
headers={"Authorization": "Bearer mcpsk_<your_api_key>"},
json={
"style_code": "",
"title": "",
"vendor": "",
"product_type": "",
"variants": [],
"description_html": "",
"category_id": "",
"status": "ACTIVE",
"publish": true,
"allow_new_vendor": false
},
)
r.raise_for_status()
print(r.json())
Plain fetch. Works in Node 18+, Deno, Bun, and any modern browser.
const r = await fetch("https://api.fulcrumgo.com/api/v1/shopify-product-upsert", {
method: "POST",
headers: {
"Authorization": "Bearer mcpsk_<your_api_key>",
"Content-Type": "application/json",
},
body: JSON.stringify({
"style_code": "",
"title": "",
"vendor": "",
"product_type": "",
"variants": [],
"description_html": "",
"category_id": "",
"status": "ACTIVE",
"publish": true,
"allow_new_vendor": false
}),
});
if (!r.ok) throw new Error(`HTTP ${r.status}`);
console.log(await r.json());
Input
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| style_code | string | required | — |
Stable supplier style code. This is the idempotency key: the same code always updates the same product.
maxLength=120
|
| title | string | required | — |
maxLength=255
|
| vendor | string | required | — | Must already exist on the store, spelled exactly. Set allow_new_vendor to create a new one. |
| product_type | string | required | — | Must already exist on the store, spelled exactly. |
| options | array<any> | optional | — | |
| variants | array<any> | required | — | |
| description_html | string | optional | ||
| category_id | string | optional | Shopify taxonomy GID, e.g. 'gid://shopify/TaxonomyCategory/aa-2-17'. Leaving this blank leaves the product Uncategorized. | |
| tags | array<string> | optional | — | |
| image_urls | array<string> | optional | — | Public image URLs. Shopify fetches them; it never sees our host. |
| status | string | optional | ACTIVE |
pattern=^(ACTIVE|DRAFT|ARCHIVED)$
|
| publish | boolean | optional | True | Publish to every sales channel after upserting. |
| allow_new_vendor | boolean | optional | False | Off by default. Creating vendors by accident is how a store ends up with 'Billionaire Boys Club' next to "Billionaire Boys' Club". |
Output
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| product_id | string | required | — | |
| handle | string | required | — | |
| admin_url | string | required | — | |
| created | boolean | required | — | False when an existing style code was updated. |
| variant_count | integer | required | — | |
| stock_set | boolean | required | — | |
| published | boolean | required | — | False means the product exists but is NOT live on any channel. Never report it as live when this is false. |
| published_to | array<string> | optional | — | |
| warnings | array<string> | optional | — | Non-fatal problems. A product can land with stock unset or unpublished. |
Try it
Fires a real POST /api/v1/shopify-product-upsert from your browser. Charges 1 credit per call against your account.