{
  "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
          }
        ]
      ]
    }
  }
}