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": "Sentinel Bitcoin Sync (Hardcoded Auth)",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 1
}
]
}
},
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
250,
300
]
},
{
"parameters": {
"url": "https://api.coingecko.com/api/v3/coins/bitcoin/market_chart",
"options": {},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "x-cg-demo-api-key",
"value": "CG-unVU5nDtud2jHLq8eBU1shZ2"
}
]
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "vs_currency",
"value": "usd"
},
{
"name": "days",
"value": "365"
}
]
}
},
"name": "CoinGecko API",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
450,
300
]
},
{
"parameters": {
"jsCode": "function calculateSMA(prices,period){if(prices.length<period)return null;const slice=prices.slice(-period);return slice.reduce((a,b)=>a+b,0)/period}function calculateRSI(prices,period=14){if(prices.length<period+1)return null;let gains=0;let losses=0;for(let i=prices.length-period;i<prices.length;i++){const diff=prices[i]-prices[i-1];if(diff>0)gains+=diff;else losses-=diff}const avgGain=gains/period;const avgLoss=losses/period;if(avgLoss===0)return 100;const rs=avgGain/avgLoss;return 100-(100/(1+rs))}function calculateBollingerBands(prices,period=20,stdDev=2){if(prices.length<period)return{upper:null,lower:null};const slice=prices.slice(-period);const sma=slice.reduce((a,b)=>a+b,0)/period;const variance=slice.reduce((a,b)=>a+Math.pow(b-sma,2),0)/period;const std=Math.sqrt(variance);return{upper:sma+(stdDev*std),lower:sma-(stdDev*std)}}function processMarketData(items){const rawData=items[0].json;const priceData=rawData.prices||[];if(priceData.length===0){throw new Error('No price data received from CoinGecko API')}const closePrices=[];let maxPrice=0;const results=[];for(const[timestamp,price]of priceData){closePrices.push(price);if(price>maxPrice)maxPrice=price;const date=new Date(timestamp).toISOString().split('T')[0];const sma50=calculateSMA(closePrices,50);const sma200=calculateSMA(closePrices,200);const rsi=calculateRSI(closePrices,14);const{upper:bbUpper,lower:bbLower}=calculateBollingerBands(closePrices,20,2);const drawdownPct=((price-maxPrice)/maxPrice)*100;results.push({date,close:Math.round(price*100)/100,open:Math.round(price*100)/100,high:Math.round(price*100)/100,low:Math.round(price*100)/100,volume:0,sma_50:sma50?Math.round(sma50*100)/100:null,sma_200:sma200?Math.round(sma200*100)/100:null,rsi:rsi?Math.round(rsi*100)/100:null,bb_upper:bbUpper?Math.round(bbUpper*100)/100:null,bb_lower:bbLower?Math.round(bbLower*100)/100:null,drawdown_pct:Math.round(drawdownPct*100)/100})}return results.slice(-30)}return $input.all().map(item=>{const processedData=processMarketData($input.all());return processedData.map(row=>({json:row}))}).flat();"
},
"name": "Calculate Indicators",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
650,
300
]
},
{
"parameters": {
"method": "POST",
"url": "https://uzxocjwuisgzldbtppnk.supabase.co/rest/v1/bitcoin_data",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "<redacted-credential>"
},
{
"name": "Authorization",
"value": "<redacted-credential>"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Prefer",
"value": "resolution=merge-duplicates"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "date",
"value": "={{ $json.date }}"
},
{
"name": "close",
"value": "={{ $json.close }}"
},
{
"name": "sma_50",
"value": "={{ $json.sma_50 }}"
},
{
"name": "sma_200",
"value": "={{ $json.sma_200 }}"
},
{
"name": "rsi",
"value": "={{ $json.rsi }}"
},
{
"name": "bb_upper",
"value": "={{ $json.bb_upper }}"
},
{
"name": "bb_lower",
"value": "={{ $json.bb_lower }}"
},
{
"name": "drawdown_pct",
"value": "={{ $json.drawdown_pct }}"
}
]
}
},
"name": "Supabase API Upsert",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
850,
300
]
}
],
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "CoinGecko API",
"type": "main",
"index": 0
}
]
]
},
"CoinGecko API": {
"main": [
[
{
"node": "Calculate Indicators",
"type": "main",
"index": 0
}
]
]
},
"Calculate Indicators": {
"main": [
[
{
"node": "Supabase API Upsert",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Sentinel Bitcoin Sync (Hardcoded Auth). Uses httpRequest. Scheduled trigger; 4 nodes.
Source: https://github.com/abdullah-binmadhi/Bitcoin-Dashboard/blob/main/n8n/workflow_final.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.
Birthday Automation - Production (Fixed). Uses stopAndError, httpRequest, emailSend, bannerbear. Scheduled trigger; 86 nodes.
This template runs two scheduled workflows to govern Microsoft Entra ID (Azure AD) guest accounts by detecting stale users via Microsoft Graph, staging deletions in SharePoint with a 72-hour window, n
Jira-Allure-Auto-Qa. Uses httpRequest, jira. Scheduled trigger; 68 nodes.
Spotify-Sync-Surrealdb-V1. Uses httpRequest, n8n-nodes-surrealdb, spotify. Scheduled trigger; 62 nodes.
As n8n instances scale, teams often lose track of sub-workflows—who uses them, where they are referenced, and whether they can be safely updated. This leads to inefficiencies like unnecessary copies o