This workflow corresponds to n8n.io template #15867 — we link there as the canonical source.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "4WFdISM7wbKhn8PX",
"name": "Get Taobao and Tmall shop products and first product detail with JustOneAPI",
"tags": [],
"nodes": [
{
"id": "0497a697-1164-457c-834a-c98170512c36",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
11104,
3472
],
"parameters": {
"width": 496,
"height": 496,
"content": "## Get Taobao and Tmall shop products and first product detail with JustOneAPI\n\n### How it works\n\n1. Trigger workflow manually\n2. Prepare API and shop inputs for JustOneAPI\n3. Fetch Taobao/Tmall shop products list\n4. Extract first product ID from the list\n5. Fetch product details using the extracted ID\n6. Build and store final product detail output\n\n### Setup steps\n\n- - [ ] Configure JustOneAPI credentials in the HTTP request nodes\n- - [ ] Set the correct base URL for the API endpoints\n- - [ ] Verify the code nodes for proper data extraction and transformation\n\n### Customization\n\nYou can modify the API endpoints in the HTTP request nodes to fetch different data or add additional fields to the output by updating the code nodes."
},
"typeVersion": 1
},
{
"id": "2e60ef49-d37a-4770-87be-1c8381a7e0fa",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
11664,
3472
],
"parameters": {
"color": 7,
"width": 256,
"height": 96,
"content": "## Workflow Trigger\n\nManually initiates the workflow execution"
},
"typeVersion": 1
},
{
"id": "6b5cd0fd-7430-4dda-84db-017120e25bf1",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
11936,
3472
],
"parameters": {
"color": 7,
"width": 256,
"height": 112,
"content": "## Input Preparation\n\nPrepares API and shop inputs for subsequent requests"
},
"typeVersion": 1
},
{
"id": "99fdeb9d-404d-4ae0-b465-b5d28c666fcd",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
12240,
3472
],
"parameters": {
"color": 7,
"width": 496,
"height": 112,
"content": "## Fetch Shop Products\n\nRetrieves the list of products from Taobao/Tmall shop"
},
"typeVersion": 1
},
{
"id": "aa5c4041-be30-4357-86a8-6aed3d76816f",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
12768,
3472
],
"parameters": {
"color": 7,
"width": 496,
"height": 112,
"content": "## Extract First Product ID\n\nExtracts the first product ID from the shop products list"
},
"typeVersion": 1
},
{
"id": "85c506a8-7979-45ff-822d-4e493f77a1e3",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
13296,
3472
],
"parameters": {
"color": 7,
"width": 272,
"height": 112,
"content": "## Fetch Product Details\n\nRetrieves detailed information for the extracted product ID"
},
"typeVersion": 1
},
{
"id": "7bb83410-001f-4741-9661-6d450d51e9c6",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
13584,
3472
],
"parameters": {
"color": 7,
"width": 656,
"height": 112,
"content": "## Build and Store Output\n\nConstructs and stores the final product detail output"
},
"typeVersion": 1
},
{
"id": "d0b870f3-800e-4bd2-b7b2-951ae99d38db",
"name": "Start Workflow Manually",
"type": "n8n-nodes-base.manualTrigger",
"position": [
11712,
3632
],
"parameters": {},
"typeVersion": 1
},
{
"id": "70cb3a92-c1e6-480f-a3a9-c31fd47c08f3",
"name": "Set API and Shop Parameters",
"type": "n8n-nodes-base.set",
"position": [
11984,
3632
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "{\n \"baseUrl\": \"https://api.justoneapi.com\",\n \"token\": \"YOUR_JUSTONEAPI_TOKEN\",\n \"userId\": \"TARGET_SELLER_USER_ID\",\n \"shopId\": \"TARGET_SHOP_ID\",\n \"sort\": \"coefp\",\n \"page\": 1,\n \"maxItems\": 1\n}"
},
"typeVersion": 3.4
},
{
"id": "3d9081ee-3a63-459e-bb00-cbdcf0b28203",
"name": "Fetch Shop Product List via API",
"type": "n8n-nodes-base.httpRequest",
"position": [
12288,
3632
],
"parameters": {
"url": "={{$json.baseUrl + '/api/taobao/get-shop-item-list/v2'}}",
"options": {
"redirect": {
"redirect": {}
}
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "token",
"value": "={{$json.token}}"
},
{
"name": "userId",
"value": "={{$json.userId}}"
},
{
"name": "shopId",
"value": "={{$json.shopId}}"
},
{
"name": "sort",
"value": "={{$json.sort}}"
},
{
"name": "page",
"value": "={{$json.page}}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "ce2566a9-bf5a-4d4f-ad3a-bd0331f0e30f",
"name": "Store Raw Product List Data",
"type": "n8n-nodes-base.set",
"position": [
12592,
3856
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={{$json}}"
},
"typeVersion": 3.4
},
{
"id": "8a02ebd3-f00e-483d-aa0a-c8052bc00700",
"name": "Extract First Product ID",
"type": "n8n-nodes-base.code",
"position": [
12816,
3632
],
"parameters": {
"jsCode": "const cfg = $('Set API and Shop Parameters').first().json;\nconst maxItems = Math.max(1, Number(cfg.maxItems || 1));\nconst rows = $input.all();\n\nfunction cleanUrl(value) {\n if (!value) return '';\n const text = String(value);\n if (text.startsWith('//')) return `https:${text}`;\n return text;\n}\n\nfunction cleanShopItem(item) {\n return {\n itemId: item.itemId ?? '',\n itemIdStr: item.itemIdStr || '',\n itemName: item.itemName || '',\n picUrlFull: cleanUrl(item.picUrlFull || ''),\n priceCurrency: item.priceCurrency || '',\n priceFen: item.priceFen ?? null,\n priceYuanDouble: item.priceYuanDouble ?? null,\n priceZKFen: item.priceZKFen ?? null,\n priceZKYuanDouble: item.priceZKYuanDouble ?? null,\n priceZKYuanDoubleWorld: item.priceZKYuanDoubleWorld ?? null,\n priceZKDoubleHKD: item.priceZKDoubleHKD ?? null,\n priceZKDoubleTWD: item.priceZKDoubleTWD ?? null,\n discntPriceYuan: item.discntPriceYuan ?? null,\n discntType: item.discntType || '',\n commentCount: item.commentCount || '',\n orderCount30Day: item.orderCount30Day || '',\n orderPayUV: item.orderPayUV || '',\n soldCount30Day: item.soldCount30Day || '',\n freeShipping: item.freeShipping ?? null,\n areaLimit: item.areaLimit ?? null,\n backCatId: item.backCatId ?? '',\n backCatIdL1: item.backCatIdL1 ?? '',\n commentTagList: Array.isArray(item.commentTagList) ? item.commentTagList : [],\n raw: item\n };\n}\n\nconst selectedProducts = [];\n\nfor (const row of rows) {\n const root = row.json || {};\n const httpData = root.data?.httpData || {};\n const pageData = root.data?.pageData || {};\n\n const itemList = httpData.itemListModuleResponse?.itemList;\n if (!Array.isArray(itemList)) {\n continue;\n }\n\n const shopList = Array.isArray(httpData.shopListModuleResponse?.shopList)\n ? httpData.shopListModuleResponse.shopList\n : [];\n const firstShop = shopList[0] || {};\n const pageInfo = httpData.itemListModuleResponse?.page || {};\n const meta = httpData.metaModuleResponse || {};\n const breadcrumbList = Array.isArray(httpData.breadcrumbModuleResponse?.breadcrumbList)\n ? httpData.breadcrumbModuleResponse.breadcrumbList\n : [];\n const pageSimplified = httpData.pageSimplifiedModuleResponse || {};\n const banner = httpData.seoCommonBannerResponse || {};\n\n for (const product of itemList) {\n if (product?.itemId === undefined || product?.itemId === null || String(product.itemId).trim() === '') {\n continue;\n }\n\n selectedProducts.push({\n root,\n product,\n shopContext: {\n shop: {\n shopId: firstShop.shopId ?? cfg.shopId ?? '',\n sellerId: firstShop.sellerId ?? cfg.userId ?? '',\n shopName: firstShop.shopName || '',\n picUrl: cleanUrl(firstShop.picUrl || ''),\n descriptionMatchScore: firstShop.descriptionMatchScore || '',\n serviceScore: firstShop.serviceScore || '',\n deliverScore: firstShop.deliverScore || ''\n },\n pageInfo: {\n pageNo: pageInfo.pageNo ?? null,\n pageSize: pageInfo.pageSize ?? null,\n totalCount: pageInfo.totalCount ?? null,\n totalPages: pageInfo.totalPages ?? null,\n nextNo: pageInfo.nextNo ?? null,\n prevNo: pageInfo.prevNo ?? null,\n showBegin: pageInfo.showBegin ?? null,\n showEnd: pageInfo.showEnd ?? null,\n hideTotalCount: pageInfo.hideTotalCount || ''\n },\n meta: {\n title: meta.title || '',\n keyword: meta.keyword || '',\n description: meta.description || '',\n robots: meta.robots || '',\n linkList: Array.isArray(meta.linkList) ? meta.linkList : []\n },\n breadcrumbList,\n pageSimplified: {\n simplified: pageSimplified.simplified ?? null,\n simplifiedType: pageSimplified.simplifiedType || '',\n userId: pageSimplified.userId || '',\n success: pageSimplified.success ?? null\n },\n banner: {\n color: banner.color || '',\n loginShow: banner.loginShow ?? null,\n pcBanner: cleanUrl(banner.pcBanner || ''),\n targetURl: cleanUrl(banner.targetURl || ''),\n success: banner.success ?? null\n },\n pageData: {\n env: pageData.env || '',\n locale: pageData.locale || '',\n wh_locale: pageData.wh_locale || '',\n client: pageData.client || '',\n traffic: pageData.traffic || '',\n wh_pageType: pageData.wh_pageType || '',\n sort: pageData.sort || '',\n detailUrl: cleanUrl(pageData.detailUrl || ''),\n currentUrl: cleanUrl(pageData.currentUrl || ''),\n keyword: pageData.keyword || '',\n pageUrlFollow: pageData.pageUrlFollow ?? null,\n isBase64On: pageData.isBase64On ?? null,\n query: pageData.query || {}\n }\n }\n });\n }\n}\n\nconst limitedProducts = selectedProducts.slice(0, maxItems);\n\nreturn limitedProducts.map((entry, index) => ({\n json: {\n baseUrl: cfg.baseUrl,\n token: cfg.token,\n requestedUserId: cfg.userId,\n requestedShopId: cfg.shopId,\n requestedSort: cfg.sort,\n requestedPage: cfg.page,\n itemId: String(entry.product.itemId),\n itemRank: index + 1,\n selectedBy: 'get-shop-item-list-v2:data.httpData.itemListModuleResponse.itemList',\n shopProduct: cleanShopItem(entry.product),\n shopContext: entry.shopContext,\n rawShopListResponse: entry.root\n }\n}));\n"
},
"typeVersion": 2
},
{
"id": "998543f2-a140-4aad-a247-95866f4d7761",
"name": "Store Extracted Product ID",
"type": "n8n-nodes-base.set",
"position": [
13104,
3856
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={{$json}}"
},
"typeVersion": 3.4
},
{
"id": "a0d01092-3177-459e-8a26-9def4f943ed9",
"name": "Fetch Product Details via API",
"type": "n8n-nodes-base.httpRequest",
"position": [
13344,
3632
],
"parameters": {
"url": "={{$json.baseUrl + '/api/taobao/get-item-detail/v4'}}",
"options": {
"redirect": {
"redirect": {}
}
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "token",
"value": "={{$json.token}}"
},
{
"name": "itemId",
"value": "={{$json.itemId}}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "b3017b77-dd1a-4573-a056-362183fbe760",
"name": "Build Product Detail Output",
"type": "n8n-nodes-base.code",
"position": [
13616,
3632
],
"parameters": {
"jsCode": "const rows = $input.all();\nconst cfg = $('Set API and Shop Parameters').first().json;\nconst selectedRows = $('Extract First Product ID').all();\n\nfunction toNumberOrNull(value) {\n if (value === undefined || value === null || value === '') return null;\n const num = Number(value);\n return Number.isFinite(num) ? num : null;\n}\n\nfunction fenToYuan(value) {\n const num = toNumberOrNull(value);\n return num === null ? null : num / 100;\n}\n\nreturn rows.map((item, index) => {\n const root = item.json || {};\n const detail = root.data || {};\n const selected = selectedRows[index]?.json || {};\n const shopProduct = selected.shopProduct || {};\n const shopContext = selected.shopContext || {};\n\n const skus = Array.isArray(detail.sku2info) ? detail.sku2info : [];\n const skuProperties = Array.isArray(detail.skuBase) ? detail.skuBase : [];\n\n const cleanedSkus = skus.map(sku => ({\n skuId: sku.skuId || '',\n skuName: sku.skuName || '',\n skuPicUrl: sku.skuPicUrl || '',\n itemPriceFen: sku.itemPrice ?? null,\n itemPriceYuan: fenToYuan(sku.itemPrice),\n finalSkuPriceFen: sku.finalSkuPrice ?? null,\n finalSkuPriceYuan: fenToYuan(sku.finalSkuPrice),\n finalPriceFen: sku.finalPrice ?? null,\n finalPriceYuan: fenToYuan(sku.finalPrice),\n thirdOriginalDiscountPriceFen: sku.thirdOriginalDiscountPrice ?? null,\n thirdOriginalDiscountPriceYuan: fenToYuan(sku.thirdOriginalDiscountPrice),\n stock: sku.stock ?? '',\n valueList: Array.isArray(sku.valueList) ? sku.valueList : []\n }));\n\n const finalSkuPrices = cleanedSkus\n .map(sku => sku.finalSkuPriceFen)\n .filter(value => typeof value === 'number');\n\n const totalStock = cleanedSkus.reduce((sum, sku) => {\n const stockNum = Number(sku.stock);\n return Number.isFinite(stockNum) ? sum + stockNum : sum;\n }, 0);\n\n const cleanedSkuProperties = skuProperties.map(property => ({\n propertyId: property.propertyId || '',\n propertyName: property.propertyName || '',\n values: Array.isArray(property.itemPropertyValues)\n ? property.itemPropertyValues.map(value => ({\n valueId: value.valueId || '',\n value: value.value || '',\n pic: value.pic || '',\n badge: value.badge ?? null\n }))\n : []\n }));\n\n return {\n json: {\n requestedUserId: cfg.userId || '',\n requestedShopId: cfg.shopId || '',\n requestedSort: cfg.sort || '',\n requestedPage: cfg.page ?? '',\n shopListEndpoint: '/api/taobao/get-shop-item-list/v2',\n detailEndpoint: '/api/taobao/get-item-detail/v4',\n selectedItemId: selected.itemId || String(detail.itemId || ''),\n selectedBy: selected.selectedBy || '',\n shopInfo: shopContext.shop || {},\n shopPageInfo: shopContext.pageInfo || {},\n shopMeta: shopContext.meta || {},\n breadcrumbList: shopContext.breadcrumbList || [],\n pageSimplified: shopContext.pageSimplified || {},\n banner: shopContext.banner || {},\n pageData: shopContext.pageData || {},\n shopSourceProduct: shopProduct,\n product: {\n itemId: detail.itemId ?? '',\n title: detail.title || '',\n itemPic: detail.itemPic || '',\n images: Array.isArray(detail.images) ? detail.images : [],\n itemPriceFen: detail.itemPrice ?? null,\n itemPriceYuan: fenToYuan(detail.itemPrice),\n discountPriceFen: detail.DiscountPrice ?? null,\n discountPriceYuan: fenToYuan(detail.DiscountPrice),\n shopName: detail.shopName || '',\n shopType: detail.shopType || ''\n },\n skuSummary: {\n skuCount: cleanedSkus.length,\n skuPropertyCount: cleanedSkuProperties.length,\n minFinalSkuPriceFen: finalSkuPrices.length ? Math.min(...finalSkuPrices) : null,\n minFinalSkuPriceYuan: finalSkuPrices.length ? Math.min(...finalSkuPrices) / 100 : null,\n maxFinalSkuPriceFen: finalSkuPrices.length ? Math.max(...finalSkuPrices) : null,\n maxFinalSkuPriceYuan: finalSkuPrices.length ? Math.max(...finalSkuPrices) / 100 : null,\n totalStock\n },\n skus: cleanedSkus,\n skuProperties: cleanedSkuProperties,\n raw: {\n detailResponse: root,\n shopListResponse: selected.rawShopListResponse || null\n }\n }\n };\n});\n"
},
"typeVersion": 2
},
{
"id": "1b3b3586-0ace-40c6-9872-434c7f5f7cdd",
"name": "Store Final Product Details",
"type": "n8n-nodes-base.set",
"position": [
14080,
3632
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={{$json}}"
},
"typeVersion": 3.4
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "e7a4fd51-a6d9-4b2d-ad15-ea7509cbc589",
"connections": {
"Start Workflow Manually": {
"main": [
[
{
"node": "Set API and Shop Parameters",
"type": "main",
"index": 0
}
]
]
},
"Extract First Product ID": {
"main": [
[
{
"node": "Store Extracted Product ID",
"type": "main",
"index": 0
},
{
"node": "Fetch Product Details via API",
"type": "main",
"index": 0
}
]
]
},
"Build Product Detail Output": {
"main": [
[
{
"node": "Store Final Product Details",
"type": "main",
"index": 0
}
]
]
},
"Set API and Shop Parameters": {
"main": [
[
{
"node": "Fetch Shop Product List via API",
"type": "main",
"index": 0
}
]
]
},
"Fetch Product Details via API": {
"main": [
[
{
"node": "Build Product Detail Output",
"type": "main",
"index": 0
}
]
]
},
"Fetch Shop Product List via API": {
"main": [
[
{
"node": "Store Raw Product List Data",
"type": "main",
"index": 0
},
{
"node": "Extract First Product ID",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Use this workflow to fetch a Taobao or Tmall shop product list, extract the first returned product ID, and retrieve detailed product data for that item with JustOneAPI.
Source: https://n8n.io/workflows/15867/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow listens for an “Approved” label on a Trello card, reads the AI draft bookkeeping JSON from card comments, and posts the corresponding transaction to Xero. It then adds a Xero deep link b
02_LLM_Pipeline v1.0. Uses executeWorkflowTrigger, httpRequest, seaTable. Event-driven trigger; 65 nodes.
This workflow allows you to import any workflow from a file or another n8n instance and map the credentials easily. A multi-form setup guides you through the entire process At the beginning you have t
[n8n] Advanced URL Parsing and Shortening Workflow - Switchy.io Integration. Uses splitInBatches, stickyNote, httpRequest, html. Event-driven trigger; 56 nodes.
[](https://youtu.be/c7yCZhmMjtI)