This workflow follows the Execute Workflow Trigger → HTTP Request recipe pattern — see all workflows that pair these two integrations.
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 →
{
"name": "XHS-Discovery",
"nodes": [
{
"parameters": {},
"id": "workflow-trigger",
"name": "Workflow Input",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1,
"position": [
0,
300
]
},
{
"parameters": {
"jsCode": "// Extract records from input\nconst records = $input.first().json.records || [];\n\nif (records.length === 0) {\n return [{ json: { success: false, message: 'No records to process' } }];\n}\n\n// Map to individual items for processing\nreturn records.map(record => ({\n json: {\n record_id: record.record_id,\n keyword: record.fields?.keyword || '',\n category: record.fields?.category || '',\n min_likes: record.fields?.min_likes || 100,\n crawl_limit: record.fields?.crawl_limit || 20,\n priority: record.fields?.priority || 5\n }\n}));"
},
"id": "extract-keywords",
"name": "Extract Keywords",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
200,
300
]
},
{
"parameters": {
"method": "PUT",
"url": "=https://open.feishu.cn/open-apis/bitable/v1/apps/{{ $env.LARK_APP_TOKEN }}/tables/{{ $env.KEYWORDS_TABLE_ID }}/records/{{ $json.record_id }}",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"fields\": {\n \"status\": \"\u91c7\u96c6\u4e2d\",\n \"locked_at\": \"{{ $now.toISO() }}\",\n \"locked_by\": \"{{ $workflow.id }}\"\n }\n}",
"options": {}
},
"id": "lock-record",
"name": "Lock Record (\u91c7\u96c6\u4e2d)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
400,
300
],
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "POST",
"url": "={{ $env.CRAWLER_API_URL }}/api/search/human",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"keyword\": \"{{ $('Extract Keywords').item.json.keyword }}\",\n \"limit\": {{ $('Extract Keywords').item.json.crawl_limit }}\n}",
"options": {
"timeout": 60000
}
},
"id": "search-xhs",
"name": "Search XHS (Human)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
600,
300
],
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "check-success",
"leftValue": "={{ $json.success }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "if-search-success",
"name": "IF Search Success",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
800,
300
]
},
{
"parameters": {
"jsCode": "// Filter results by min_likes and transform to Feishu records\nconst searchResult = $input.first().json;\nconst items = searchResult.data?.items || [];\nconst minLikes = $('Extract Keywords').item.json.min_likes || 100;\nconst keywordRecordId = $('Extract Keywords').item.json.record_id;\nconst keyword = $('Extract Keywords').item.json.keyword;\n\nconst filteredItems = items.filter(item => {\n // \u5982\u679c\u6709\u70b9\u8d5e\u6570\u4fe1\u606f\u5219\u8fc7\u6ee4\uff0c\u5426\u5219\u4fdd\u7559\n const likes = item.likes || item.liked_count || 0;\n return likes >= minLikes || likes === 0; // 0 means unknown, keep it\n});\n\nif (filteredItems.length === 0) {\n return [{ json: { success: true, topics_count: 0, message: 'No items passed filter' } }];\n}\n\n// Transform to Feishu topic records\nconst topicRecords = filteredItems.map(item => ({\n fields: {\n keyword_id: keywordRecordId,\n keyword: keyword,\n note_id: item.note_id || item.id,\n title: item.title || '',\n author: item.author || item.nickname || '',\n likes: item.likes || item.liked_count || 0,\n cover_url: item.cover || item.cover_url || '',\n note_url: `https://www.xiaohongshu.com/explore/${item.note_id || item.id}`,\n status: '\u5f85\u63d0\u53d6',\n crawled_at: new Date().toISOString()\n }\n}));\n\nreturn [{ json: { records: topicRecords, count: topicRecords.length } }];"
},
"id": "filter-and-transform",
"name": "Filter & Transform",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1000,
200
]
},
{
"parameters": {
"method": "POST",
"url": "=https://open.feishu.cn/open-apis/bitable/v1/apps/{{ $env.LARK_APP_TOKEN }}/tables/{{ $env.TOPICS_TABLE_ID }}/records/batch_create",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ records: $json.records }) }}",
"options": {}
},
"id": "batch-create-topics",
"name": "Batch Create Topics",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1200,
200
],
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "PUT",
"url": "=https://open.feishu.cn/open-apis/bitable/v1/apps/{{ $env.LARK_APP_TOKEN }}/tables/{{ $env.KEYWORDS_TABLE_ID }}/records/{{ $('Extract Keywords').item.json.record_id }}",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"fields\": {\n \"status\": \"\u5df2\u91c7\u96c6\",\n \"last_crawl_time\": \"{{ $now.toISO() }}\",\n \"locked_at\": null,\n \"locked_by\": null\n }\n}",
"options": {}
},
"id": "update-keyword-success",
"name": "Update Keyword (\u5df2\u91c7\u96c6)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1400,
200
],
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Handle search failure\nconst error = $input.first().json;\nconst errorMessage = error.error?.message || 'Unknown error';\n\nreturn [{ json: {\n success: false,\n error: errorMessage,\n record_id: $('Extract Keywords').item.json.record_id,\n keyword: $('Extract Keywords').item.json.keyword\n} }];"
},
"id": "handle-error",
"name": "Handle Search Error",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1000,
400
]
},
{
"parameters": {
"method": "PUT",
"url": "=https://open.feishu.cn/open-apis/bitable/v1/apps/{{ $env.LARK_APP_TOKEN }}/tables/{{ $env.KEYWORDS_TABLE_ID }}/records/{{ $json.record_id }}",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"fields\": {\n \"status\": \"\u91c7\u96c6\u5931\u8d25\",\n \"error_message\": \"{{ $json.error }}\",\n \"retry_count\": {{ ($('Extract Keywords').item.json.retry_count || 0) + 1 }},\n \"locked_at\": null,\n \"locked_by\": null\n }\n}",
"options": {}
},
"id": "update-keyword-failed",
"name": "Update Keyword (\u91c7\u96c6\u5931\u8d25)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1200,
400
],
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {},
"id": "merge-results",
"name": "Merge Results",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
1600,
300
]
},
{
"parameters": {
"jsCode": "// Prepare output summary\nconst results = $input.all();\nlet successCount = 0;\nlet failCount = 0;\nlet topicsCreated = 0;\n\nfor (const item of results) {\n if (item.json.success !== false) {\n successCount++;\n topicsCreated += item.json.count || 0;\n } else {\n failCount++;\n }\n}\n\nreturn [{ json: {\n action: 'discovery',\n success: failCount === 0,\n keywords_processed: results.length,\n keywords_success: successCount,\n keywords_failed: failCount,\n topics_created: topicsCreated,\n message: `Processed ${results.length} keywords, created ${topicsCreated} topics`\n} }];"
},
"id": "prepare-output",
"name": "Prepare Output",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1800,
300
]
}
],
"connections": {
"Workflow Input": {
"main": [
[
{
"node": "Extract Keywords",
"type": "main",
"index": 0
}
]
]
},
"Extract Keywords": {
"main": [
[
{
"node": "Lock Record (\u91c7\u96c6\u4e2d)",
"type": "main",
"index": 0
}
]
]
},
"Lock Record (\u91c7\u96c6\u4e2d)": {
"main": [
[
{
"node": "Search XHS (Human)",
"type": "main",
"index": 0
}
]
]
},
"Search XHS (Human)": {
"main": [
[
{
"node": "IF Search Success",
"type": "main",
"index": 0
}
]
]
},
"IF Search Success": {
"main": [
[
{
"node": "Filter & Transform",
"type": "main",
"index": 0
}
],
[
{
"node": "Handle Search Error",
"type": "main",
"index": 0
}
]
]
},
"Filter & Transform": {
"main": [
[
{
"node": "Batch Create Topics",
"type": "main",
"index": 0
}
]
]
},
"Batch Create Topics": {
"main": [
[
{
"node": "Update Keyword (\u5df2\u91c7\u96c6)",
"type": "main",
"index": 0
}
]
]
},
"Update Keyword (\u5df2\u91c7\u96c6)": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 0
}
]
]
},
"Handle Search Error": {
"main": [
[
{
"node": "Update Keyword (\u91c7\u96c6\u5931\u8d25)",
"type": "main",
"index": 0
}
]
]
},
"Update Keyword (\u91c7\u96c6\u5931\u8d25)": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 1
}
]
]
},
"Merge Results": {
"main": [
[
{
"node": "Prepare Output",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"saveManualExecutions": true,
"callerPolicy": "workflowsFromSameOwner"
},
"staticData": null,
"tags": [
{
"name": "XHS-Pipeline",
"id": "xhs-pipeline"
}
],
"meta": {
"templateCredsSetupCompleted": true
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
httpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
XHS-Discovery. Uses executeWorkflowTrigger, httpRequest. Event-driven trigger; 12 nodes.
Source: https://github.com/wade56754/XHS/blob/b5b999f35721bcfe8ffc6b518245e1d8dbaab5c5/n8n-workflows/WF-Discovery.json — 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.
02_LLM_Pipeline v1.0. Uses executeWorkflowTrigger, httpRequest, seaTable. Event-driven trigger; 65 nodes.
This template is a powerful, reusable utility for managing stateful, long-running processes. It allows a main workflow to be paused indefinitely at "checkpoints" and then be resumed by external, async
Upload files from any source to your account Kommo or AmoCRM with a simple and reusable workflow. It can split a large file into small ones and upload chunks. Works for Kommo and amoCRM There are 3 re
Remixed Backup your workflows to GitHub from Solomon's work. Check out his templates.
Remixed Backup your workflows to GitHub from Solomon's work. Check out his templates.