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": "Upwork Pre-Bid Triage",
"nodes": [
{
"parameters": {},
"id": "b1a1e1a1-0001-4001-8001-000000000001",
"name": "Run triage",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-120,
300
]
},
{
"parameters": {
"url": "http://localhost:4178/api/search",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "AI automation"
},
{
"name": "limit",
"value": "8"
}
]
},
"options": {}
},
"id": "b1a1e1a1-0002-4001-8001-000000000002",
"name": "Search Upwork (MCP bridge)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
120,
300
]
},
{
"parameters": {
"jsCode": "// one item per job, carrying the search fields forward\nreturn ($input.first().json.jobs || []).map(j => ({ json: j }));"
},
"id": "b1a1e1a1-0003-4001-8001-000000000003",
"name": "Split jobs",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
360,
300
]
},
{
"parameters": {
"url": "http://localhost:4178/api/job",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "id",
"value": "={{ $json.id }}"
}
]
},
"options": {}
},
"id": "b1a1e1a1-0004-4001-8001-000000000004",
"name": "Enrich (deep intel)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
600,
300
]
},
{
"parameters": {
"jsCode": "// zip the search items with their enriched deep-intel (1:1 by order), score,\n// tag HOT/WATCH/SKIP, keep the ones worth opening, sorted best-first.\nconst search = $('Split jobs').all();\nconst deep = $input.all();\nconst num = v => (v==null||v===''||isNaN(+v)) ? null : +v;\nconst out = [];\nfor (let i=0;i<deep.length;i++){\n const s = (search[i]||{}).json || {};\n const j = (deep[i].json.job) || {};\n const bid = j.bid_stats || {};\n const cr = j.client_record || {};\n const spend = num(cr.spend_total);\n const prop = num(s.proposal_count) || 0;\n const hired = (j.job_activity && j.job_activity.totalHired) || 0;\n const spendScore = spend!=null ? Math.min(1, Math.log10(spend+1)/6) : 0.2;\n const compScore = 1 - Math.min(1, prop/50);\n const openScore = hired>0 ? 0.2 : 1;\n const payScore = bid.avg!=null ? Math.min(1, bid.avg/120) : 0.4;\n const score = Math.round(100*(0.34*spendScore+0.28*compScore+0.20*openScore+0.18*payScore));\n const tag = score>=72 ? 'HOT' : score>=55 ? 'WATCH' : 'SKIP';\n out.push({ json: {\n score, tag,\n title: s.title || j.title,\n type: s.job_type,\n proposals: prop,\n bid_avg: bid.avg, bid_min: bid.min, bid_max: bid.max,\n client_spend: spend,\n client_country: (s.client||{}).country,\n verified: (s.client||{}).verification_status === 'VERIFIED',\n connects_cost: num(j.connects_cost),\n id: s.id\n }});\n}\nout.sort((a,b)=> b.json.score - a.json.score);\nreturn out;"
},
"id": "b1a1e1a1-0005-4001-8001-000000000005",
"name": "Score & filter",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
840,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"leftValue": "={{ $json.score }}",
"rightValue": 60,
"operator": {
"type": "number",
"operation": "gte"
}
}
]
},
"options": {}
},
"id": "b1a1e1a1-0006-4001-8001-000000000006",
"name": "Worth opening? (score \u2265 60)",
"type": "n8n-nodes-base.filter",
"typeVersion": 2,
"position": [
1080,
300
]
}
],
"connections": {
"Run triage": {
"main": [
[
{
"node": "Search Upwork (MCP bridge)",
"type": "main",
"index": 0
}
]
]
},
"Search Upwork (MCP bridge)": {
"main": [
[
{
"node": "Split jobs",
"type": "main",
"index": 0
}
]
]
},
"Split jobs": {
"main": [
[
{
"node": "Enrich (deep intel)",
"type": "main",
"index": 0
}
]
]
},
"Enrich (deep intel)": {
"main": [
[
{
"node": "Score & filter",
"type": "main",
"index": 0
}
]
]
},
"Score & filter": {
"main": [
[
{
"node": "Worth opening? (score \u2265 60)",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"active": false
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Upwork Pre-Bid Triage. Uses httpRequest. Event-driven trigger; 6 nodes.
Source: https://github.com/Majboor/upwork-cli/blob/main/examples/n8n/upwork-triage-starter.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.
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)