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 Best-Time-to-Bid Radar",
"nodes": [
{
"id": "bb000000-0000-4000-8000-000000000001",
"name": "\u25b6 Run now",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-360,
540
],
"parameters": {},
"typeVersion": 1
},
{
"id": "bb000000-0000-4000-8000-000000000002",
"name": "\ud83d\udd52 Every hour",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-360,
760
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 1
}
]
}
},
"typeVersion": 1.2
},
{
"id": "bb000000-0000-4000-8000-000000000003",
"name": "\u2460 Keywords",
"type": "n8n-nodes-base.code",
"position": [
40,
620
],
"parameters": {
"jsCode": "return ['AI automation','GoHighLevel','n8n','make.com automation'].map(q=>({json:{q}}));"
},
"typeVersion": 2
},
{
"id": "bb000000-0000-4000-8000-000000000004",
"name": "\u2461 Search market",
"type": "n8n-nodes-base.httpRequest",
"position": [
420,
620
],
"parameters": {
"url": "http://localhost:4178/api/search",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $json.q }}"
},
{
"name": "limit",
"value": "10"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "bb000000-0000-4000-8000-000000000005",
"name": "\u2462 Bucket by hour/day",
"type": "n8n-nodes-base.code",
"position": [
800,
620
],
"parameters": {
"jsCode": "// tally job post times into persistent buckets (UTC)\nconst s = $getWorkflowStaticData('global');\ns.hours = s.hours || Array(24).fill(0);\ns.days = s.days || Array(7).fill(0);\ns.samples = s.samples || 0;\nlet counted = 0;\nfor (const it of $input.all()) {\n for (const j of (it.json.jobs || [])) {\n const d = j.published_date ? new Date(j.published_date) : null;\n if (!d || isNaN(d)) continue;\n s.hours[d.getUTCHours()]++; s.days[d.getUTCDay()]++; counted++;\n }\n}\ns.samples++;\nreturn [{ json: { counted_this_run: counted, total_samples: s.samples } }];"
},
"typeVersion": 2
},
{
"id": "bb000000-0000-4000-8000-000000000006",
"name": "\u2463 Build heatmap",
"type": "n8n-nodes-base.code",
"position": [
1180,
620
],
"parameters": {
"jsCode": "// render an ASCII heatmap + peak windows from the tally\nconst s = $getWorkflowStaticData('global');\nconst hours = s.hours || Array(24).fill(0);\nconst days = s.days || Array(7).fill(0);\nconst dn = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];\nconst max = Math.max(1, ...hours);\nconst bar = v => '#'.repeat(Math.round(v/max*12)).padEnd(12,'.');\nconst L = ['# Best time to bid (UTC)','',`Samples: ${s.samples||0} \u00b7 jobs seen: ${hours.reduce((a,b)=>a+b,0)}`,'','## By hour'];\nhours.forEach((v,h)=>L.push(`${String(h).padStart(2,'0')}:00 ${bar(v)} ${v}`));\nconst topH = hours.map((v,h)=>({h,v})).sort((a,b)=>b.v-a.v).slice(0,3).map(x=>x.h+':00').join(', ');\nconst topD = days.map((v,i)=>({d:dn[i],v})).sort((a,b)=>b.v-a.v).slice(0,3).map(x=>x.d).join(', ');\nL.push('', 'Peak hours: '+topH, 'Peak days: '+topD);\nreturn [{ json: { report: L.join('\\n'), peak_hours: topH, peak_days: topD } }];"
},
"typeVersion": 2
},
{
"id": "bb000000-0000-4000-8000-000000000007",
"name": "\ud83d\udcca Timing report",
"type": "n8n-nodes-base.noOp",
"position": [
1560,
620
],
"parameters": {},
"typeVersion": 1
},
{
"id": "bb000000-0000-4000-8000-000000000008",
"name": "note-in",
"type": "n8n-nodes-base.stickyNote",
"position": [
20,
420
],
"parameters": {
"color": 4,
"width": 720,
"height": 140,
"content": "## \u2460 SAMPLE THE MARKET\nHourly, search your keywords and collect fresh postings + their publish times."
},
"typeVersion": 1
},
{
"id": "bb000000-0000-4000-8000-000000000009",
"name": "note-bucket",
"type": "n8n-nodes-base.stickyNote",
"position": [
780,
420
],
"parameters": {
"color": 5,
"width": 340,
"height": 140,
"content": "## \u2461 BUCKET BY TIME\nTally post times into persistent hour/weekday buckets (survives runs)."
},
"typeVersion": 1
},
{
"id": "bb000000-0000-4000-8000-000000000010",
"name": "note-out",
"type": "n8n-nodes-base.stickyNote",
"position": [
1160,
420
],
"parameters": {
"color": 3,
"width": 760,
"height": 140,
"content": "## \u2462 HEATMAP + PEAK WINDOWS\nRender when HOT gigs actually drop, so you know when to be online."
},
"typeVersion": 1
}
],
"connections": {
"\u25b6 Run now": {
"main": [
[
{
"node": "\u2460 Keywords",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udd52 Every hour": {
"main": [
[
{
"node": "\u2460 Keywords",
"type": "main",
"index": 0
}
]
]
},
"\u2460 Keywords": {
"main": [
[
{
"node": "\u2461 Search market",
"type": "main",
"index": 0
}
]
]
},
"\u2461 Search market": {
"main": [
[
{
"node": "\u2462 Bucket by hour/day",
"type": "main",
"index": 0
}
]
]
},
"\u2462 Bucket by hour/day": {
"main": [
[
{
"node": "\u2463 Build heatmap",
"type": "main",
"index": 0
}
]
]
},
"\u2463 Build heatmap": {
"main": [
[
{
"node": "\ud83d\udcca Timing report",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Upwork Best-Time-to-Bid Radar. Uses httpRequest. Event-driven trigger; 10 nodes.
Source: https://github.com/Majboor/upwork-mcp-cli/blob/main/examples/n8n/upwork-best-time-radar.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)