This workflow corresponds to n8n.io template #16153 — we link there as the canonical source.
This workflow follows the Form 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 →
{
"id": "X5tYtZ5mvCCZf778",
"name": "SMC Screener Analysis API Workflow - Read, Create, Reanalyze, Clear, Delete",
"tags": [],
"nodes": [
{
"id": "note-community-copy",
"name": "\u2728 Community Copy",
"type": "n8n-nodes-base.stickyNote",
"position": [
1808,
-1072
],
"parameters": {
"color": 6,
"width": 1260,
"height": 364,
"content": "## \u2728 Community Publishing Copy\n\n**Title**\nAutomate SMC Screener analysis actions from n8n\n\n**Short description**\nThis workflow lets users manage SMC Screener analysis records with their own API key: list analyses, create a new analysis, update metadata, queue re-analysis, validate clear requests, delete records with confirmation, and inspect runtime status.\n\n**Best for**\n\n- \ud83d\udcca Traders who organize analysis records from forms or spreadsheets\n- \u2699\ufe0f Automation builders connecting SMC Screener to n8n\n- \ud83d\udd01 Teams that need repeatable analysis creation and re-analysis workflows\n\n**Important note**\n\nThis workflow is analysis-only. It does not place trades, hold funds, or provide investment advice."
},
"typeVersion": 1
},
{
"id": "note-overview",
"name": "\ud83d\ude80 Template Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
1808,
-672
],
"parameters": {
"color": 5,
"width": 1260,
"height": 456,
"content": "## \ud83d\ude80 SMC Screener Analysis API Template\n\nA polished n8n workflow for SMC Screener users who want to automate analysis records with their own API key.\n\n**\ud83d\udd10 API Key**\nPaste the user's SMC Screener API key into the first form field: `api_key`. For manual runs, replace `api_key` inside **Manual Test Payload**.\n\n**\ud83d\udcda API Docs**\nhttps://api.smcscreener.com/api/v1\n\n| Icon | Action | Endpoint | Permission |\n|---|---|---|---|\n| \ud83d\udcda | List user analyses | `\ud83d\udd17GET /analyses/` | `\u2611\ufe0fanalyses_read` |\n\n| \ud83d\udd0e | Get one analysis | `\ud83d\udd17GET /analyses/{id}/` | `\u2611\ufe0fanalyses_read` |\n\n| \u2795 | Create analysis | `\ud83d\udd17POST /analyses/` | `\u2611\ufe0fanalyses_create` |\n\n| \u270f\ufe0f | Update analysis | `\ud83d\udd17PATCH /analyses/{id}/` | `\u2611\ufe0fanalyses_edit` |\n\n| \ud83d\udd01 | Queue re-analysis | `\ud83d\udd17POST /analyses/{id}/reanalyze/` | `\u2611\ufe0fanalyses_reanalyze` |\n\n| \ud83e\uddf9 | Clear analysis data | `\ud83d\udd17POST /analyses/{id}/clear/` | `\u2611\ufe0fanalyses_clear` |\n\n| \ud83d\uddd1\ufe0f | Delete analysis | `\ud83d\udd17DELETE /analyses/{id}/` | `\u2611\ufe0fanalyses_delete` |\n\n| \ud83e\udded | Runtime status | `\ud83d\udd17GET /analyses/runtime-status/` | `\u2611\ufe0fanalyses_read` |"
},
"typeVersion": 1
},
{
"id": "note-inputs",
"name": "\ud83e\udded Setup & Inputs",
"type": "n8n-nodes-base.stickyNote",
"position": [
1808,
-176
],
"parameters": {
"color": 4,
"width": 1260,
"height": 418,
"content": "## \ud83e\udded Setup & Inputs\n\nUse the public **n8n Form** as the user-facing API entry point, or run **Manual Test Payload** while building.\n\n**Required for all live requests**\n\n- \ud83d\udd10 `api_key` - user's SMC Screener API key\n- \u2699\ufe0f `action` - selected analysis API action\n\n**Create analysis fields**\n\n- \ud83d\udc8e `symbol` - example `BTCUSDT`\n- \ud83e\udde9 `analysisref` / `db` - analysis reference number\n- \u23f1\ufe0f `timeframe` / `tf` - timeframe in minutes or label\n- \ud83d\udcc8 `side` - `buy` or `sell`\n- \ud83d\udd52 `start_time` - ISO datetime such as `2026-05-01T00:00:00Z`\n\n**Confirm-sensitive actions**\n\nClear and delete require `confirm=true`. Delete is permanent. Clear validates the request through the public endpoint and returns the cleanup service message."
},
"typeVersion": 1
},
{
"id": "section-inputs",
"name": "\ud83d\udd10 0. User Input & API Key",
"type": "n8n-nodes-base.stickyNote",
"position": [
1808,
272
],
"parameters": {
"color": 7,
"width": 1260,
"height": 264,
"content": "## \ud83d\udd10 0. User Input & API Key\n\nCollect the user's API key and normalize every action into one internal payload.\n\n**API key field**\n`api_key` is the only secret the user needs to paste.\n\n**Flow**\nForm or manual payload \u2192 Normalize inputs \u2192 Validate required fields \u2192 Example or live API route"
},
"typeVersion": 1
},
{
"id": "section-list",
"name": "\ud83d\udcda 1. Read User Analyses",
"type": "n8n-nodes-base.stickyNote",
"position": [
3664,
-1616
],
"parameters": {
"color": 3,
"width": 1172,
"height": 442,
"content": "## \ud83d\udcda 1. Read User Analyses\n\n**Purpose**\nFetch the user's analysis records with optional filters for symbol, analysis reference, timeframe, side, active state, limit, and offset.\n\n**API used**\n`GET /analyses/`\n\n**Flow**\nAction Router \u2192 GET analyses \u2192 Build list summary"
},
"typeVersion": 1
},
{
"id": "section-detail",
"name": "\ud83d\udd0e 2. Get One Analysis",
"type": "n8n-nodes-base.stickyNote",
"position": [
3664,
-1152
],
"parameters": {
"color": 5,
"width": 1172,
"height": 448,
"content": "## \ud83d\udd0e 2. Get One Analysis\n\n**Purpose**\nLoad a single analysis record by `analysis_id`.\n\n**API used**\n`GET /analyses/{analysis_id}/`\n\n**Common error**\n`analysisnotfound` when the analysis does not belong to the API-key owner."
},
"typeVersion": 1
},
{
"id": "section-create",
"name": "\u2795 3. Create Analysis",
"type": "n8n-nodes-base.stickyNote",
"position": [
3664,
-688
],
"parameters": {
"color": 4,
"width": 1168,
"height": 472,
"content": "## \u2795 3. Create Analysis\n\n**Purpose**\nCreate a new analysis record from n8n form data or a spreadsheet row.\n\n**API used**\n`POST /analyses/`\n\n**Required inputs**\n`symbol`, `analysisref`, `timeframe`, `side`, `start_time`, and `analysis_name`.\n\n**Flow**\nAction Router \u2192 POST create analysis \u2192 Build create summary"
},
"typeVersion": 1
},
{
"id": "section-update",
"name": "\u270f\ufe0f 4. Update Analysis",
"type": "n8n-nodes-base.stickyNote",
"position": [
3664,
-192
],
"parameters": {
"color": 2,
"width": 1168,
"height": 458,
"content": "## \u270f\ufe0f 4. Update Analysis\n\n**Purpose**\nUpdate editable analysis metadata such as title, side, visibility, active state, end time, end price, and start-violation behavior.\n\n**API used**\n`PATCH /analyses/{analysis_id}/`\n\n**Flow**\nAction Router \u2192 PATCH analysis \u2192 Build update summary"
},
"typeVersion": 1
},
{
"id": "section-reanalyze",
"name": "\ud83d\udd01 5. Reanalyze Analysis",
"type": "n8n-nodes-base.stickyNote",
"position": [
3664,
288
],
"parameters": {
"color": 7,
"width": 1164,
"height": 410,
"content": "## \ud83d\udd01 5. Reanalyze Analysis\n\n**Purpose**\nQueue a selected analysis for re-analysis and return the queue token.\n\n**API used**\n`POST /analyses/{analysis_id}/reanalyze/`\n\n**Flow**\nAction Router \u2192 POST reanalyze \u2192 Build queue summary"
},
"typeVersion": 1
},
{
"id": "section-clear",
"name": "\ud83e\uddf9 6. Clear Analysis Data",
"type": "n8n-nodes-base.stickyNote",
"position": [
3664,
720
],
"parameters": {
"color": 6,
"width": 1160,
"height": 468,
"content": "## \ud83e\uddf9 6. Clear Analysis Data\n\n**Purpose**\nValidate a clear-analysis request through the public API.\n\n**API used**\n`POST /analyses/{analysis_id}/clear/`\n\n**Required safety flag**\nUse `confirm=true`. Optional `dry_run=true` keeps the request in preview mode.\n\n**Flow**\nAction Router \u2192 POST clear \u2192 Build clear summary"
},
"typeVersion": 1
},
{
"id": "section-delete",
"name": "\ud83d\uddd1\ufe0f 7. Delete Analysis",
"type": "n8n-nodes-base.stickyNote",
"position": [
3664,
1216
],
"parameters": {
"width": 1164,
"height": 420,
"content": "## \ud83d\uddd1\ufe0f 7. Delete Analysis\n\n**Purpose**\nDelete an analysis record owned by the API-key user.\n\n**API used**\n`DELETE /analyses/{analysis_id}/?confirm=true`\n\n**Safety note**\nDelete is permanent and requires the API key permission `analyses_delete`. Default chart analysis rows can be blocked by the API."
},
"typeVersion": 1
},
{
"id": "section-runtime",
"name": "\ud83e\udded 8. Runtime Status",
"type": "n8n-nodes-base.stickyNote",
"position": [
3664,
1664
],
"parameters": {
"color": 5,
"width": 1164,
"height": 426,
"content": "## \ud83e\udded 8. Runtime Status\n\n**Purpose**\nInspect queue, processing, and runtime state for selected analysis IDs or analysis references.\n\n**API used**\n`GET /analyses/runtime-status/`\n\n**Flow**\nAction Router \u2192 GET runtime status \u2192 Build runtime summary"
},
"typeVersion": 1
},
{
"id": "form-trigger",
"name": "SMC_Analysis_Form",
"type": "n8n-nodes-base.formTrigger",
"position": [
2016,
992
],
"parameters": {
"options": {
"path": "smc-analysis-api",
"buttonLabel": "\ud83d\ude80 Run Analysis Workflow",
"appendAttribution": false,
"respondWithOptions": {
"values": {
"formSubmittedText": "\u2705 Request received. Open the execution output to review the API response."
}
}
},
"formTitle": "SMC Screener Analysis API Workflow",
"formFields": {
"values": [
{
"fieldName": "api_key",
"fieldType": "password",
"fieldLabel": "\ud83d\udd10 Paste Your SMC API Key",
"placeholder": "smc_sk_live_...",
"requiredField": true
},
{
"fieldName": "action",
"fieldType": "dropdown",
"fieldLabel": "\u2699\ufe0f Action",
"defaultValue": "list_analyses",
"fieldOptions": {
"values": [
{
"option": "list_analyses"
},
{
"option": "get_analysis"
},
{
"option": "create_analysis"
},
{
"option": "update_analysis"
},
{
"option": "reanalyze_analysis"
},
{
"option": "clear_analysis"
},
{
"option": "delete_analysis"
},
{
"option": "runtime_status"
}
]
},
"requiredField": true
},
{
"fieldName": "analysis_id",
"fieldType": "number",
"fieldLabel": "\ud83e\udde9 Analysis ID",
"placeholder": "123"
},
{
"fieldName": "symbol",
"fieldLabel": "\ud83d\udc8e Symbol",
"placeholder": "BTCUSDT",
"defaultValue": "BTCUSDT"
},
{
"fieldName": "market_type",
"fieldType": "dropdown",
"fieldLabel": "\ud83d\udcc8 Market",
"defaultValue": "crypto",
"fieldOptions": {
"values": [
{
"option": "crypto"
},
{
"option": "forex"
}
]
}
},
{
"fieldName": "timeframe",
"fieldType": "dropdown",
"fieldLabel": "\u23f1\ufe0f Timeframe",
"defaultValue": "4h",
"fieldOptions": {
"values": [
{
"option": "15m"
},
{
"option": "30m"
},
{
"option": "1h"
},
{
"option": "2h"
},
{
"option": "4h"
},
{
"option": "6h"
},
{
"option": "8h"
},
{
"option": "12h"
},
{
"option": "1d"
},
{
"option": "3d"
},
{
"option": "1w"
}
]
}
},
{
"fieldName": "db",
"fieldType": "number",
"fieldLabel": "\ud83d\udd22 Analysis Ref / DB",
"defaultValue": "9201"
},
{
"fieldName": "side",
"fieldType": "dropdown",
"fieldLabel": "\ud83d\udcca Side",
"defaultValue": "buy",
"fieldOptions": {
"values": [
{
"option": "buy"
},
{
"option": "sell"
}
]
}
},
{
"fieldName": "start_time",
"fieldLabel": "\ud83d\udd52 Start Time",
"placeholder": "2026-05-01T00:00:00Z",
"defaultValue": "2026-05-01T00:00:00Z"
},
{
"fieldName": "analysis_name",
"fieldLabel": "\ud83c\udff7\ufe0f Analysis Name",
"placeholder": "BTCUSDT 4h Buy Plan",
"defaultValue": "BTCUSDT 4h Buy Plan"
},
{
"fieldName": "publish_state",
"fieldType": "dropdown",
"fieldLabel": "\ud83d\udc41\ufe0f Visibility",
"defaultValue": "public",
"fieldOptions": {
"values": [
{
"option": "public"
},
{
"option": "private"
},
{
"option": "off"
}
]
}
},
{
"fieldName": "active",
"fieldType": "dropdown",
"fieldLabel": "\u2705 Active",
"defaultValue": "true",
"fieldOptions": {
"values": [
{
"option": "true"
},
{
"option": "false"
}
]
}
},
{
"fieldName": "start_price",
"fieldLabel": "\ud83d\udcb5 Start Price",
"placeholder": "60000.00"
},
{
"fieldName": "end_time",
"fieldLabel": "\ud83c\udfc1 End Time",
"placeholder": "2026-06-01T00:00:00Z"
},
{
"fieldName": "end_price",
"fieldLabel": "\ud83d\udcb0 End Price",
"placeholder": "65000.00"
},
{
"fieldName": "confirm",
"fieldType": "dropdown",
"fieldLabel": "\u26a0\ufe0f Confirm Clear/Delete",
"defaultValue": "false",
"fieldOptions": {
"values": [
{
"option": "false"
},
{
"option": "true"
}
]
}
},
{
"fieldName": "dry_run",
"fieldType": "dropdown",
"fieldLabel": "\ud83e\uddea Clear Preview / Dry Run",
"defaultValue": "true",
"fieldOptions": {
"values": [
{
"option": "true"
},
{
"option": "false"
}
]
}
},
{
"fieldName": "limit",
"fieldType": "number",
"fieldLabel": "\ud83d\udd22 Limit",
"defaultValue": "50"
},
{
"fieldName": "offset",
"fieldType": "number",
"fieldLabel": "\u21aa\ufe0f Offset",
"defaultValue": "0"
},
{
"fieldName": "ids",
"fieldLabel": "\ud83e\uddfe Runtime IDs",
"placeholder": "123,124"
},
{
"fieldName": "dbs",
"fieldLabel": "\ud83e\udde9 Runtime Analysis Refs",
"placeholder": "9201,9202"
},
{
"fieldName": "view",
"fieldType": "dropdown",
"fieldLabel": "\ud83e\udded Runtime View",
"defaultValue": "auto",
"fieldOptions": {
"values": [
{
"option": "auto"
},
{
"option": "byid"
},
{
"option": "bydb"
}
]
}
}
]
},
"formDescription": "\ud83d\udd10 Paste your SMC Screener API key, choose an analysis action, and run read/create/update/reanalyze/clear/delete/runtime requests. API docs: https://api.smcscreener.com/api/v1"
},
"typeVersion": 2.5
},
{
"id": "manual-trigger",
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"position": [
2016,
1152
],
"parameters": {},
"typeVersion": 1
},
{
"id": "manual-payload",
"name": "Manual Test Payload",
"type": "n8n-nodes-base.code",
"position": [
2304,
1152
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "return {\n json: {\n api_key: 'smc_sk_live_example',\n action: 'create_analysis',\n analysis_id: 123,\n symbol: 'BTCUSDT',\n market_type: 'crypto',\n timeframe: '4h',\n db: 9201,\n side: 'buy',\n start_time: '2026-05-01T00:00:00Z',\n analysis_name: 'BTCUSDT 4h Buy Plan',\n publish_state: 'public',\n active: true,\n confirm: false,\n dry_run: true,\n limit: 50,\n offset: 0,\n ids: '123',\n dbs: '9201',\n view: 'auto'\n }\n};"
},
"typeVersion": 2
},
{
"id": "normalize",
"name": "Normalize Analysis Input",
"type": "n8n-nodes-base.code",
"position": [
2624,
1072
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const input = $json.body || $json.query || $json;\n\nfunction pick(...keys) {\n for (const key of keys) {\n if (input[key] !== undefined && input[key] !== null && String(input[key]).trim() !== '') return input[key];\n }\n return undefined;\n}\nfunction parseBool(value, defaultValue = false) {\n if (value === undefined || value === null || String(value).trim() === '') return defaultValue;\n if (typeof value === 'boolean') return value;\n const token = String(value).trim().toLowerCase();\n if (['1', 'true', 'yes', 'y', 'on'].includes(token)) return true;\n if (['0', 'false', 'no', 'n', 'off'].includes(token)) return false;\n return defaultValue;\n}\nfunction toInt(value, defaultValue = null) {\n if (value === undefined || value === null || String(value).trim() === '') return defaultValue;\n const n = Number.parseInt(String(value).trim(), 10);\n return Number.isFinite(n) ? n : defaultValue;\n}\nfunction cleanSymbol(value) {\n return String(value || '').trim().toUpperCase().replace(/[^A-Z0-9_./-]/g, '');\n}\nfunction cleanCsv(value) {\n return String(value || '').split(/[\\n,;|]+/).map((s) => s.trim()).filter(Boolean).join(',');\n}\nfunction query(params) {\n const pairs = [];\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined || value === null || String(value).trim() === '') continue;\n pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(String(value)));\n }\n return pairs.length ? '?' + pairs.join('&') : '';\n}\n\nconst apiBaseUrl = 'https://api.smcscreener.com/api/v1';\nconst rawApiKey = String(pick('api_key', 'apikey', 'smc_api_key', 'apiKey', 'SMC_API_KEY') || '').trim();\nconst sampleValues = new Set(['', 'smc_sk_live_example', 'your_smc_api_key', 'smc_sk_test_example']);\nconst isSampleApi = sampleValues.has(rawApiKey.toLowerCase());\n\nconst actionRaw = String(pick('action', 'mode') || 'list_analyses').trim().toLowerCase();\nconst actionMap = {\n list: 'list_analyses',\n read: 'list_analyses',\n get_all: 'list_analyses',\n list_analyses: 'list_analyses',\n get: 'get_analysis',\n detail: 'get_analysis',\n get_analysis: 'get_analysis',\n create: 'create_analysis',\n create_analysis: 'create_analysis',\n update: 'update_analysis',\n edit: 'update_analysis',\n patch: 'update_analysis',\n update_analysis: 'update_analysis',\n reanalyze: 'reanalyze_analysis',\n re_analysis: 'reanalyze_analysis',\n reanalyze_analysis: 'reanalyze_analysis',\n clear: 'clear_analysis',\n clear_analysis: 'clear_analysis',\n delete: 'delete_analysis',\n delete_analysis: 'delete_analysis',\n runtime: 'runtime_status',\n status: 'runtime_status',\n runtime_status: 'runtime_status',\n};\nconst action = actionMap[actionRaw] || 'list_analyses';\n\nconst tfMap = {\n '1m': 1, '5m': 5, '15m': 15, '30m': 30,\n '1h': 60, '2h': 120, '3h': 180, '4h': 240, '6h': 360, '8h': 480, '12h': 720,\n '1d': 1440, '3d': 4320, '1w': 10080,\n};\nconst tfRaw = String(pick('tf', 'timeframe', 'timeframe_minutes', 'timeframe_label') || '4h').trim().toLowerCase();\nconst tf = tfMap[tfRaw] || toInt(tfRaw, 240);\nconst tfStr = Object.entries(tfMap).find(([, minutes]) => minutes === tf)?.[0] || tfRaw || String(tf);\nconst analysisId = toInt(pick('analysis_id', 'analysisid', 'id', 'ref'), null);\nconst symbol = cleanSymbol(pick('symbol', 'pair') || 'BTCUSDT');\nconst marketTypeRaw = String(pick('market_type', 'market') || 'crypto').trim().toLowerCase();\nconst marketType = ['crypto', 'forex'].includes(marketTypeRaw) ? marketTypeRaw : 'crypto';\nconst db = toInt(pick('db', 'analysisref', 'analysis_ref', 'analysis'), 9201);\nconst sideRaw = String(pick('side') || 'buy').trim().toLowerCase();\nconst side = ['buy', 'sell'].includes(sideRaw) ? sideRaw : 'buy';\nconst startTime = String(pick('start_time', 'start') || '2026-05-01T00:00:00Z').trim();\nconst analysisName = String(pick('analysis_name', 'name', 'title') || symbol + ' ' + tfStr + ' ' + side.toUpperCase() + ' Plan').trim();\nconst publishRaw = String(pick('publish_state', 'visibility') || 'public').trim().toLowerCase();\nconst publishState = ['public', 'private', 'off'].includes(publishRaw) ? publishRaw : 'public';\nconst active = parseBool(pick('active', 'enabled'), true);\nconst stopOnStartViolation = parseBool(pick('stop_on_start_violation', 'strictstart'), true);\nconst confirm = parseBool(pick('confirm'), false);\nconst dryRun = parseBool(pick('dry_run', 'preview'), true);\nconst startPrice = String(pick('start_price', 'startprice') || '').trim();\nconst endTime = String(pick('end_time', 'end') || '').trim();\nconst endPrice = String(pick('end_price', 'endprice') || '').trim();\nconst limit = Math.min(Math.max(toInt(pick('limit'), 50) || 50, 1), 300);\nconst offset = Math.max(toInt(pick('offset'), 0) || 0, 0);\nconst ids = cleanCsv(pick('ids', 'refs', 'analysis_ids', 'analysisrefs') || '');\nconst dbs = cleanCsv(pick('dbs', 'analysisrefs', 'analysisref') || '');\nconst viewRaw = String(pick('view', 'output', 'shape') || 'auto').trim().toLowerCase();\nconst view = ['auto', 'byid', 'bydb'].includes(viewRaw) ? viewRaw : 'auto';\n\nconst createBody = {\n symbol,\n market_type: marketType,\n db,\n tf,\n tf_str: tfStr,\n side,\n start_time: startTime,\n analysis_name: analysisName,\n publish_state: publishState,\n active,\n stop_on_start_violation: stopOnStartViolation,\n};\nif (startPrice) createBody.start_price = startPrice;\nif (endTime) createBody.end_time = endTime;\nif (endPrice) createBody.end_price = endPrice;\n\nconst updateBody = {\n analysis_name: analysisName,\n side,\n publish_state: publishState,\n active,\n stop_on_start_violation: stopOnStartViolation,\n};\nif (endTime) updateBody.end_time = endTime;\nif (endPrice) updateBody.end_price = endPrice;\n\nconst requests = {\n list_analyses: {\n method: 'GET',\n endpoint: 'GET /analyses/',\n url: apiBaseUrl + '/analyses/' + query({ pair: symbol, db, tf, side, active, limit, offset }),\n },\n get_analysis: {\n method: 'GET',\n endpoint: 'GET /analyses/{analysis_id}/',\n url: apiBaseUrl + '/analyses/' + analysisId + '/',\n },\n create_analysis: {\n method: 'POST',\n endpoint: 'POST /analyses/',\n url: apiBaseUrl + '/analyses/',\n body: createBody,\n },\n update_analysis: {\n method: 'PATCH',\n endpoint: 'PATCH /analyses/{analysis_id}/',\n url: apiBaseUrl + '/analyses/' + analysisId + '/',\n body: updateBody,\n },\n reanalyze_analysis: {\n method: 'POST',\n endpoint: 'POST /analyses/{analysis_id}/reanalyze/',\n url: apiBaseUrl + '/analyses/' + analysisId + '/reanalyze/',\n body: {},\n },\n clear_analysis: {\n method: 'POST',\n endpoint: 'POST /analyses/{analysis_id}/clear/',\n url: apiBaseUrl + '/analyses/' + analysisId + '/clear/',\n body: { confirm, dry_run: dryRun },\n },\n delete_analysis: {\n method: 'DELETE',\n endpoint: 'DELETE /analyses/{analysis_id}/',\n url: apiBaseUrl + '/analyses/' + analysisId + '/' + query({ confirm }),\n },\n runtime_status: {\n method: 'GET',\n endpoint: 'GET /analyses/runtime-status/',\n url: apiBaseUrl + '/analyses/runtime-status/' + query({ ids, dbs, view }),\n },\n};\n\nconst validationErrors = [];\nif (!rawApiKey) validationErrors.push('api_key is required.');\nif (['get_analysis', 'update_analysis', 'reanalyze_analysis', 'clear_analysis', 'delete_analysis'].includes(action) && (!analysisId || analysisId <= 0)) {\n validationErrors.push('analysis_id is required for this action.');\n}\nif (action === 'create_analysis') {\n if (!symbol) validationErrors.push('symbol is required.');\n if (db === null || db < 0 || db > 99999) validationErrors.push('analysisref/db must be between 0 and 99999.');\n if (!tf || tf <= 0) validationErrors.push('timeframe must be a valid timeframe label or minute value.');\n if (!['buy', 'sell'].includes(side)) validationErrors.push('side must be buy or sell.');\n if (!startTime) validationErrors.push('start_time is required.');\n if (!analysisName) validationErrors.push('analysis_name is required.');\n}\n\nreturn {\n json: {\n api_key: rawApiKey || 'smc_sk_live_example',\n is_sample_api: isSampleApi,\n action,\n analysis_id: analysisId,\n symbol,\n market_type: marketType,\n db,\n tf,\n tf_str: tfStr,\n side,\n start_time: startTime,\n analysis_name: analysisName,\n publish_state: publishState,\n active,\n confirm,\n dry_run: dryRun,\n limit,\n offset,\n ids,\n dbs,\n view,\n api_base_url: apiBaseUrl,\n docs_url: apiBaseUrl,\n required_permissions: ['analyses_read', 'analyses_create', 'analyses_edit', 'analyses_reanalyze', 'analyses_clear', 'analyses_delete'],\n selected_request: requests[action],\n requests,\n validation_errors: validationErrors,\n },\n};"
},
"typeVersion": 2
},
{
"id": "validation-switch",
"name": "Input Valid?",
"type": "n8n-nodes-base.switch",
"position": [
2912,
1072
],
"parameters": {
"mode": "expression",
"output": "={{ ($json.validation_errors || []).length ? 0 : 1 }}",
"numberOutputs": 2
},
"typeVersion": 3
},
{
"id": "validation-error",
"name": "Build Input Error",
"type": "n8n-nodes-base.code",
"position": [
3232,
720
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "return {\n json: {\n ok: false,\n action: $json.action,\n error: 'input_validation_failed',\n message: 'The workflow input is missing one or more required fields.',\n validation_errors: $json.validation_errors,\n docs_url: $json.docs_url,\n selected_request: $json.selected_request\n }\n};"
},
"typeVersion": 2
},
{
"id": "sample-switch",
"name": "Example API Key?",
"type": "n8n-nodes-base.switch",
"position": [
3184,
1152
],
"parameters": {
"mode": "expression",
"output": "={{ $json.is_sample_api ? 0 : 1 }}",
"numberOutputs": 2
},
"typeVersion": 3
},
{
"id": "example-output",
"name": "Example Output",
"type": "n8n-nodes-base.code",
"position": [
3360,
896
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const request = $json.selected_request || {};\nreturn {\n json: {\n ok: true,\n mode: 'example_mode',\n message: 'Example API key detected. No live SMC Screener account was changed.',\n action: $json.action,\n docs_url: $json.docs_url,\n selected_request: request,\n required_permissions: $json.required_permissions,\n workflow_capabilities: [\n { title: 'Read User Analyses', endpoint: 'GET /analyses/' },\n { title: 'Create Analysis', endpoint: 'POST /analyses/' },\n { title: 'Update Analysis', endpoint: 'PATCH /analyses/{analysis_id}/' },\n { title: 'Reanalyze Analysis', endpoint: 'POST /analyses/{analysis_id}/reanalyze/' },\n { title: 'Clear Analysis Data', endpoint: 'POST /analyses/{analysis_id}/clear/' },\n { title: 'Delete Analysis', endpoint: 'DELETE /analyses/{analysis_id}/' },\n { title: 'Runtime Status', endpoint: 'GET /analyses/runtime-status/' }\n ],\n expected_error_messages: [\n { case: 'Invalid or missing API key', error: 'invalidapikey', note: 'Use a real API key created by the user.' },\n { case: 'Missing analysis_id', error: 'input_validation_failed', note: 'Required for get, update, reanalyze, clear, and delete actions.' },\n { case: 'Clear/delete without confirm=true', error: 'confirmrequired', note: 'The API requires an explicit confirmation flag.' },\n { case: 'Analysis not found', error: 'analysisnotfound', note: 'The analysis must belong to the API-key owner.' },\n { case: 'Plan not eligible', error: 'analysisultrarequired', note: 'Analysis API actions require the Ultra plan.' }\n ]\n }\n};"
},
"typeVersion": 2
},
{
"id": "action-router",
"name": "Action Router",
"type": "n8n-nodes-base.switch",
"position": [
3472,
1072
],
"parameters": {
"mode": "expression",
"output": "={{ $json.action === 'list_analyses' ? 0 : ($json.action === 'get_analysis' ? 1 : ($json.action === 'create_analysis' ? 2 : ($json.action === 'update_analysis' ? 3 : ($json.action === 'reanalyze_analysis' ? 4 : ($json.action === 'clear_analysis' ? 5 : ($json.action === 'delete_analysis' ? 6 : 7)))))) }}",
"numberOutputs": 8
},
"typeVersion": 3
},
{
"id": "get-list",
"name": "GET User Analyses",
"type": "n8n-nodes-base.httpRequest",
"position": [
3712,
-1328
],
"parameters": {
"url": "={{ $json.requests.list_analyses.url }}",
"options": {
"response": {
"response": {
"neverError": true,
"responseFormat": "json"
}
}
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "={{ 'Bearer ' + $json.api_key }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "summary-list",
"name": "Build Analyses List Summary",
"type": "n8n-nodes-base.code",
"position": [
4032,
-1328
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const base = $('Normalize Analysis Input').first().json;\nconst response = $json;\nreturn {\n json: {\n ok: response.ok !== false,\n action: 'list_analyses',\n title: 'Read User Analyses',\n endpoint: (base.requests['list_analyses'] || {}).endpoint,\n docs_url: base.docs_url,\n request: base.requests['list_analyses'],\n api_response: response,\n error_note: response.ok === false ? 'The API returned an error payload. Check api_response.error and api_response.message.' : null\n }\n};"
},
"typeVersion": 2
},
{
"id": "get-detail",
"name": "GET Analysis Detail",
"type": "n8n-nodes-base.httpRequest",
"position": [
3728,
-880
],
"parameters": {
"url": "={{ $json.requests.get_analysis.url }}",
"options": {
"response": {
"response": {
"neverError": true,
"responseFormat": "json"
}
}
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "={{ 'Bearer ' + $json.api_key }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "summary-detail",
"name": "Build Analysis Detail Summary",
"type": "n8n-nodes-base.code",
"position": [
4032,
-880
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const base = $('Normalize Analysis Input').first().json;\nconst response = $json;\nreturn {\n json: {\n ok: response.ok !== false,\n action: 'get_analysis',\n title: 'Get One Analysis',\n endpoint: (base.requests['get_analysis'] || {}).endpoint,\n docs_url: base.docs_url,\n request: base.requests['get_analysis'],\n api_response: response,\n error_note: response.ok === false ? 'The API returned an error payload. Check api_response.error and api_response.message.' : null\n }\n};"
},
"typeVersion": 2
},
{
"id": "post-create",
"name": "POST Create Analysis",
"type": "n8n-nodes-base.httpRequest",
"position": [
3728,
-384
],
"parameters": {
"url": "={{ $json.requests.create_analysis.url }}",
"method": "POST",
"options": {
"response": {
"response": {
"neverError": true,
"responseFormat": "json"
}
}
},
"jsonBody": "={{ $json.requests.create_analysis.body }}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "={{ 'Bearer ' + $json.api_key }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "summary-create",
"name": "Build Create Summary",
"type": "n8n-nodes-base.code",
"position": [
4032,
-384
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const base = $('Normalize Analysis Input').first().json;\nconst response = $json;\nreturn {\n json: {\n ok: response.ok !== false,\n action: 'create_analysis',\n title: 'Create Analysis',\n endpoint: (base.requests['create_analysis'] || {}).endpoint,\n docs_url: base.docs_url,\n request: base.requests['create_analysis'],\n api_response: response,\n error_note: response.ok === false ? 'The API returned an error payload. Check api_response.error and api_response.message.' : null\n }\n};"
},
"typeVersion": 2
},
{
"id": "patch-update",
"name": "PATCH Update Analysis",
"type": "n8n-nodes-base.httpRequest",
"position": [
3728,
80
],
"parameters": {
"url": "={{ $json.requests.update_analysis.url }}",
"method": "PATCH",
"options": {
"response": {
"response": {
"neverError": true,
"responseFormat": "json"
}
}
},
"jsonBody": "={{ $json.requests.update_analysis.body }}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "={{ 'Bearer ' + $json.api_key }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "summary-update",
"name": "Build Update Summary",
"type": "n8n-nodes-base.code",
"position": [
4016,
80
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const base = $('Normalize Analysis Input').first().json;\nconst response = $json;\nreturn {\n json: {\n ok: response.ok !== false,\n action: 'update_analysis',\n title: 'Update Analysis',\n endpoint: (base.requests['update_analysis'] || {}).endpoint,\n docs_url: base.docs_url,\n request: base.requests['update_analysis'],\n api_response: response,\n error_note: response.ok === false ? 'The API returned an error payload. Check api_response.error and api_response.message.' : null\n }\n};"
},
"typeVersion": 2
},
{
"id": "post-reanalyze",
"name": "POST Reanalyze Analysis",
"type": "n8n-nodes-base.httpRequest",
"position": [
3728,
528
],
"parameters": {
"url": "={{ $json.requests.reanalyze_analysis.url }}",
"method": "POST",
"options": {
"response": {
"response": {
"neverError": true,
"responseFormat": "json"
}
}
},
"jsonBody": "={{ $json.requests.reanalyze_analysis.body }}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "={{ 'Bearer ' + $json.api_key }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "summary-reanalyze",
"name": "Build Reanalysis Queue Summary",
"type": "n8n-nodes-base.code",
"position": [
4016,
528
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const base = $('Normalize Analysis Input').first().json;\nconst response = $json;\nreturn {\n json: {\n ok: response.ok !== false,\n action: 'reanalyze_analysis',\n title: 'Reanalyze Analysis',\n endpoint: (base.requests['reanalyze_analysis'] || {}).endpoint,\n docs_url: base.docs_url,\n request: base.requests['reanalyze_analysis'],\n api_response: response,\n error_note: response.ok === false ? 'The API returned an error payload. Check api_response.error and api_response.message.' : null\n }\n};"
},
"typeVersion": 2
},
{
"id": "post-clear",
"name": "POST Clear Analysis",
"type": "n8n-nodes-base.httpRequest",
"position": [
3712,
1040
],
"parameters": {
"url": "={{ $json.requests.clear_analysis.url }}",
"method": "POST",
"options": {
"response": {
"response": {
"neverError": true,
"responseFormat": "json"
}
}
},
"jsonBody": "={{ $json.requests.clear_analysis.body }}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "={{ 'Bearer ' + $json.api_key }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "summary-clear",
"name": "Build Clear Summary",
"type": "n8n-nodes-base.code",
"position": [
4016,
1040
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const base = $('Normalize Analysis Input').first().json;\nconst response = $json;\nreturn {\n json: {\n ok: response.ok !== false,\n action: 'clear_analysis',\n title: 'Clear Analysis Data',\n endpoint: (base.requests['clear_analysis'] || {}).endpoint,\n docs_url: base.docs_url,\n request: base.requests['clear_analysis'],\n api_response: response,\n error_note: response.ok === false ? 'The API returned an error payload. Check api_response.error and api_response.message.' : null\n }\n};"
},
"typeVersion": 2
},
{
"id": "delete-analysis",
"name": "DELETE Analysis",
"type": "n8n-nodes-base.httpRequest",
"position": [
3712,
1472
],
"parameters": {
"url": "={{ $json.requests.delete_analysis.url }}",
"method": "DELETE",
"options": {
"response": {
"response": {
"neverError": true,
"responseFormat": "json"
}
}
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "={{ 'Bearer ' + $json.api_key }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "summary-delete",
"name": "Build Delete Summary",
"type": "n8n-nodes-base.code",
"position": [
4032,
1472
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const base = $('Normalize Analysis Input').first().json;\nconst response = $json;\nreturn {\n json: {\n ok: response.ok !== false,\n action: 'delete_analysis',\n title: 'Delete Analysis',\n endpoint: (base.requests['delete_analysis'] || {}).endpoint,\n docs_url: base.docs_url,\n request: base.requests['delete_analysis'],\n api_response: response,\n error_note: response.ok === false ? 'The API returned an error payload. Check api_response.error and api_response.message.' : null\n }\n};"
},
"typeVersion": 2
},
{
"id": "get-runtime",
"name": "GET Runtime Status",
"type": "n8n-nodes-base.httpRequest",
"position": [
3712,
1904
],
"parameters": {
"url": "={{ $json.requests.runtime_status.url }}",
"options": {
"response": {
"response": {
"neverError": true,
"responseFormat": "json"
}
}
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "={{ 'Bearer ' + $json.api_key }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "summary-runtime",
"name": "Build Runtime Status Summary",
"type": "n8n-nodes-base.code",
"position": [
4032,
1904
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const base = $('Normalize Analysis Input').first().json;\nconst response = $json;\nreturn {\n json: {\n ok: response.ok !== false,\n action: 'runtime_status',\n title: 'Runtime Status',\n endpoint: (base.requests['runtime_status'] || {}).endpoint,\n docs_url: base.docs_url,\n request: base.requests['runtime_status'],\n api_response: response,\n error_note: response.ok === false ? 'The API returned an error payload. Check api_response.error and api_response.message.' : null\n }\n};"
},
"typeVersion": 2
}
],
"active": true,
"settings": {
"timezone": "UTC",
"binaryMode": "separate",
"callerPolicy": "workflowsFromSameOwner",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "6bfa669d-8348-443c-9d22-5d609ab2771d",
"nodeGroups": [],
"connections": {
"Input Valid?": {
"main": [
[
{
"node": "Build Input Error",
"type": "main",
"index": 0
}
],
[
{
"node": "Example API Key?",
"type": "main",
"index": 0
}
]
]
},
"Action Router": {
"main": [
[
{
"node": "GET User Analyses",
"type": "main",
"index": 0
}
],
[
{
"node": "GET Analysis Detail",
"type": "main",
"index": 0
}
],
[
{
"node": "POST Create Analysis",
"type": "main",
"index": 0
}
],
[
{
"node": "PATCH Update Analysis",
"type": "main",
"index": 0
}
],
[
{
"node": "POST Reanalyze Analysis",
"type": "main",
"index": 0
}
],
[
{
"node": "POST Clear Analysis",
"type": "main",
"index": 0
}
],
[
{
"node": "DELETE Analysis",
"type": "main",
"index": 0
}
],
[
{
"node": "GET Runtime Status",
"type": "main",
"index": 0
}
]
]
},
"Manual Trigger": {
"main": [
[
{
"node": "Manual Test Payload",
"type": "main",
"index": 0
}
]
]
},
"DELETE Analysis": {
"main": [
[
{
"node": "Build Delete Summary",
"type": "main",
"index": 0
}
]
]
},
"Example API Key?": {
"main": [
[
{
"node": "Example Output",
"type": "main",
"index": 0
}
],
[
{
"node": "Action Router",
"type": "main",
"index": 0
}
]
]
},
"GET User Analyses": {
"main": [
[
{
"node": "Build Analyses List Summary",
"type": "main",
"index": 0
}
]
]
},
"SMC_Analysis_Form": {
"main": [
[
{
"node": "Normalize Analysis Input",
"type": "main",
"index": 0
}
]
]
},
"GET Runtime Status": {
"main": [
[
{
"node": "Build Runtime Status Summary",
"type": "main",
"index": 0
}
]
]
},
"GET Analysis Detail": {
"main": [
[
{
"node": "Build Analysis Detail Summary",
"type": "main",
"index": 0
}
]
]
},
"Manual Test Payload": {
"main": [
[
{
"node": "Normalize Analysis Input",
"type": "main",
"index": 0
}
]
]
},
"POST Clear Analysis": {
"main": [
[
{
"node": "Build Clear Summary",
"type": "main",
"index": 0
}
]
]
},
"POST Create Analysis": {
"main": [
[
{
"node": "Build Create Summary",
"type": "main",
"index": 0
}
]
]
},
"PATCH Update Analysis": {
"main": [
[
{
"node": "Build Update Summary",
"type": "main",
"index": 0
}
]
]
},
"POST Reanalyze Analysis": {
"main": [
[
{
"node": "Build Reanalysis Queue Summary",
"type": "main",
"index": 0
}
]
]
},
"Normalize Analysis Input": {
"main": [
[
{
"node": "Input Valid?",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow uses an n8n Form (or manual test payload) to call the SMC Screener Analysis API, letting you list, fetch, create, update, reanalyze, clear, delete analyses, and check runtime status, returning a structured response summary for each action. Receives inputs from an…
Source: https://n8n.io/workflows/16153/ — 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.
spy tool. Uses gmailTool, httpRequest, formTrigger, stopAndError. Event-driven trigger; 52 nodes.
Echo Brand Voice Analysis (Processor) - TASK-074 Dec 10 Fix. Uses formTrigger, httpRequest, executeWorkflowTrigger, moveBinaryData. Event-driven trigger; 40 nodes.
Streamline your content pipeline by bridging Notion and Instagram with a professional "review-before-publish" safeguard. This workflow allows team members to submit content via a simple form, generate
🎥 Analyze YouTube Video for Summaries, Transcripts & Content + Google Gemini AI. Uses stickyNote, httpRequest, googleDrive, gmail. Event-driven trigger; 33 nodes.
This workflow audits a list of URLs from a CSV upload or an XML sitemap using the Google PageSpeed Insights API, writes Lighthouse and Core Web Vitals metrics into a new Google Sheets report, and emai