AutomationFlowsData & Sheets › Wm-state-engine.n8n-import (redis)

Wm-state-engine.n8n-import (redis)

Wm-State-Engine.N8N-Import. Uses redis, postgres. Webhook trigger; 17 nodes.

Webhook trigger★★★★☆ complexity17 nodesRedisPostgres
Data & Sheets Trigger: Webhook Nodes: 17 Complexity: ★★★★☆ Added:

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 →

Download .json
{
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "wm-state-engine",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "03cf3e82-c894-477f-a379-c388cf24a74d",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const body = $json.body || {};\nconst tel = String(body.tel || '').replace(/\\D/g, '');\nif (!tel || tel.length < 10) {\n  return { json: { ok: false, error: 'invalid_phone', tel } };\n}\nconst action = String(body.action || '').toLowerCase();\nconst VALID_ACTIONS = ['get','transition','pause_bot','resume_bot','clear','schedule_action','cancel_scheduled_action'];\nif (!VALID_ACTIONS.includes(action)) {\n  return { json: { ok: false, error: 'invalid_action', action } };\n}\nreturn { json: { ok: true, tel, action, params: body.params || {}, now_ms: Date.now(), now_iso: new Date().toISOString() } };"
      },
      "id": "8bff8d4e-ee52-4138-82e7-70007ef2df15",
      "name": "Parse Input",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        224,
        0
      ]
    },
    {
      "parameters": {
        "operation": "get",
        "propertyName": "state_raw",
        "key": "=lead:{{ $json.tel }}:state",
        "options": {}
      },
      "id": "901597db-26f0-4580-87cf-17263c466295",
      "name": "Redis GET State",
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        448,
        0
      ],
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const up = $('Parse Input').item.json;\nconst raw = $json.state_raw;\nlet state = null;\ntry { state = raw ? (typeof raw === 'string' ? JSON.parse(raw) : raw) : null; } catch(e) { state = null; }\nconst state_existed = !!state && typeof state === 'object' && !Array.isArray(state);\nif (!state_existed) {\n  state = {\n    schema_version: 2, phone: up.tel, created_at: up.now_iso, updated_at: up.now_iso, version: 0,\n    bot: { enabled: true, paused_until_ms: 0, paused_reason: null },\n    lead_profile: { name_confirmed: false, name_for_use: null, push_name: null, supabase_lead_id: null, ihelp_contact_id: null },\n    stage: { current_id: null, updated_at: null },\n    journey: { step: 'new', entered_at_ms: up.now_ms, history: [] },\n    prova: { form_sent: false, form_sent_at_ms: 0, form_completed: false, attempt: 0, reprova_count: 0, tally_submission_id: null, answers: null, evaluation: null },\n    scheduled_action: { kind: null, due_at_ms: 0, attempt: 0, cancelled_at_ms: 0 },\n    dedupe: { outgoing_ia_msg_ids: [] }\n  };\n}\nreturn { json: { tel: up.tel, action: up.action, params: up.params, now_ms: up.now_ms, now_iso: up.now_iso, state, state_existed } };"
      },
      "id": "2cff1561-32f0-47e2-87ee-652ae03ef19d",
      "name": "Hydrate State",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        672,
        0
      ]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 1
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "get",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "c1"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "get"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 1
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "transition",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "c2"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "transition"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 1
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "pause_bot",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "c3"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "pause_bot"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 1
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "resume_bot",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "c4"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "resume_bot"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 1
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "clear",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "c5"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "clear"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 1
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "schedule_action",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "c6"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "schedule_action"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 1
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "cancel_scheduled_action",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "c7"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "cancel_scheduled_action"
            }
          ]
        },
        "options": {}
      },
      "id": "c462cfc9-e61e-4e96-95e5-47af744ef06d",
      "name": "Switch Action",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        880,
        0
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "return { json: { ok: true, tel: $json.tel, state: $json.state, state_existed: $json.state_existed, needs_write: false, log_transition: false } };"
      },
      "id": "332b0ad8-90f5-4d77-917d-e0fd82374958",
      "name": "Action Get",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1104,
        0
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const { state, params, now_ms, now_iso } = $json;\nconst intent = String(params.intent || '');\nconst currentStep = state.journey.step;\n\nconst TRANSITIONS = {\n  'new': {\n    'has_push_name':     { to: 'abertura_enviada', actions: ['send_audio_1','send_audio_2','send_aulas_link','move_stage_706'] },\n    'needs_name':        { to: 'apresentando',     actions: [] }\n  },\n  'apresentando': {\n    'name_extracted':    { to: 'abertura_enviada', actions: ['send_audio_1','send_audio_2','send_aulas_link','move_stage_706'] },\n    'followup_final':    { to: 'encerrado_inativo', actions: ['apply_tag_inativo_apresentacao'] }\n  },\n  'abertura_enviada': {\n    'any_msg':           { to: 'aguardando_aulas', actions: [] }\n  },\n  'aguardando_aulas': {\n    'schedule_tomorrow': { to: 'agendado_amanha_8h', actions: [] },\n    'aulas_done':        { to: 'aulas_concluidas',   actions: [] },\n    'followup_final':    { to: 'encaminhado_humano', actions: [] }\n  },\n  'agendado_amanha_8h': {\n    'wake':              { to: 'aguardando_aulas', actions: [] }\n  },\n  'aulas_concluidas': {\n    'send_tally':        { to: 'aguardando_form', actions: ['send_tally_link','move_stage_707'] }\n  },\n  'aguardando_form': {\n    'tally_approved':        { to: 'aprovado',          actions: ['move_stage_708','apply_tags_profile','apply_tag_prova_aprovada','apply_tag_prova_finalizada'] },\n    'tally_reprovado_once':  { to: 'aguardando_revisao', actions: ['move_stage_711','apply_tags_profile','apply_tag_prova_reprovada'] },\n    'tally_reprovado_block': { to: 'bloqueado_humano',   actions: ['move_stage_711','apply_tag_prova_reprovada'] },\n    'followup_final':        { to: 'bloqueado_humano',   actions: [] }\n  },\n  'aguardando_revisao': {\n    'retry':             { to: 'aguardando_form',     actions: ['send_tally_link'] },\n    'followup_final':    { to: 'bloqueado_humano',    actions: [] }\n  }\n};\n\nconst allowed = TRANSITIONS[currentStep] || {};\nconst transition = allowed[intent];\n\nif (!transition) {\n  return { json: { ok: false, error: 'invalid_transition', from_step: currentStep, to_step: null, intent, tel: $json.tel, state, needs_write: false, log_transition: true, log_trigger: 'rejected' } };\n}\n\nconst nextStep = transition.to;\nconst newState = JSON.parse(JSON.stringify(state));\nnewState.journey.step = nextStep;\nnewState.journey.entered_at_ms = now_ms;\nnewState.journey.history = (newState.journey.history || []).concat([{ step: currentStep, at_ms: state.journey.entered_at_ms }]);\nif (newState.journey.history.length > 20) newState.journey.history = newState.journey.history.slice(-20);\nnewState.updated_at = now_iso;\nnewState.version = (state.version || 0) + 1;\n\nif (nextStep === 'aguardando_form') {\n  newState.prova.form_sent = true;\n  newState.prova.form_sent_at_ms = now_ms;\n  newState.prova.attempt = (newState.prova.attempt || 0) + 1;\n}\nif (intent === 'tally_reprovado_once' || intent === 'tally_reprovado_block') {\n  newState.prova.reprova_count = (newState.prova.reprova_count || 0) + 1;\n}\nif (nextStep === 'aprovado' || nextStep === 'bloqueado_humano' || nextStep === 'encerrado_inativo' || nextStep === 'encaminhado_humano') {\n  newState.bot.enabled = false;\n  newState.bot.paused_reason = nextStep;\n}\n\n\n// Persist lead profile from params\nif (params && params.push_name) {\n  newState.lead_profile.push_name = String(params.push_name).slice(0, 80);\n}\nif (params && params.name_for_use) {\n  newState.lead_profile.name_for_use = String(params.name_for_use).slice(0, 60);\n  newState.lead_profile.name_confirmed = true;\n}\n\nreturn { json: { ok: true, tel: $json.tel, from_step: currentStep, to_step: nextStep, actions: transition.actions, state: newState, needs_write: true, log_transition: true, log_trigger: 'accepted' } };"
      },
      "id": "5f484cd4-fa06-42e2-885f-e7fa428bce89",
      "name": "Action Transition",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1328,
        0
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const { state, params, now_ms, now_iso } = $json;\nconst duration_ms = Number(params.duration_ms || 900000);\nconst reason = String(params.reason || 'human_typed');\nconst newState = JSON.parse(JSON.stringify(state));\nnewState.bot.paused_until_ms = now_ms + duration_ms;\nnewState.bot.paused_reason = reason;\nnewState.updated_at = now_iso;\nnewState.version = (state.version || 0) + 1;\nreturn { json: { ok: true, tel: $json.tel, state: newState, needs_write: true, log_transition: false, paused_until_ms: newState.bot.paused_until_ms } };"
      },
      "id": "e9d31617-245d-442e-a724-7dd9f36c4365",
      "name": "Action Pause Bot",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1552,
        0
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const { state, now_iso } = $json;\nconst newState = JSON.parse(JSON.stringify(state));\nnewState.bot.paused_until_ms = 0;\nnewState.bot.paused_reason = null;\nnewState.bot.enabled = true;\nnewState.updated_at = now_iso;\nnewState.version = (state.version || 0) + 1;\nreturn { json: { ok: true, tel: $json.tel, state: newState, needs_write: true, log_transition: false } };"
      },
      "id": "49b3be6e-24ae-4b29-bf36-d45dc32dc7aa",
      "name": "Action Resume Bot",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1760,
        0
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const { state, params, now_ms, now_iso, tel } = $json;\nconst scope = String(params.scope || 'state_only');\nlet newState;\nif (scope === 'state_only' || scope === 'total') {\n  newState = {\n    schema_version: 2, phone: tel, created_at: now_iso, updated_at: now_iso, version: 0,\n    bot: { enabled: true, paused_until_ms: 0, paused_reason: null },\n    lead_profile: { name_confirmed: false, name_for_use: null, push_name: null, supabase_lead_id: null, ihelp_contact_id: null },\n    stage: { current_id: null, updated_at: null },\n    journey: { step: 'new', entered_at_ms: now_ms, history: [] },\n    prova: { form_sent: false, form_sent_at_ms: 0, form_completed: false, attempt: 0, reprova_count: 0, tally_submission_id: null, answers: null, evaluation: null },\n    scheduled_action: { kind: null, due_at_ms: 0, attempt: 0, cancelled_at_ms: 0 },\n    dedupe: { outgoing_ia_msg_ids: [] }\n  };\n} else {\n  newState = JSON.parse(JSON.stringify(state));\n  newState.scheduled_action = { kind: null, due_at_ms: 0, attempt: 0, cancelled_at_ms: 0 };\n  newState.dedupe = { outgoing_ia_msg_ids: [] };\n  newState.updated_at = now_iso;\n  newState.version = (state.version || 0) + 1;\n}\nreturn { json: { ok: true, tel, state: newState, needs_write: true, log_transition: false, scope } };"
      },
      "id": "a5ae8f58-0fd2-409f-bb5b-e75ef05978aa",
      "name": "Action Clear",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1984,
        0
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const { state, params, now_iso } = $json;\nconst newState = JSON.parse(JSON.stringify(state));\nnewState.scheduled_action = {\n  kind: String(params.kind || ''),\n  due_at_ms: Number(params.due_at_ms || 0),\n  attempt: Number(params.attempt || 0),\n  cancelled_at_ms: 0\n};\nnewState.updated_at = now_iso;\nnewState.version = (state.version || 0) + 1;\nreturn { json: { ok: true, tel: $json.tel, state: newState, needs_write: true, log_transition: false } };"
      },
      "id": "3812ad43-e874-4308-91d8-5458f1edb4dd",
      "name": "Action Schedule",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2208,
        0
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const { state, now_iso, now_ms } = $json;\nconst newState = JSON.parse(JSON.stringify(state));\nnewState.scheduled_action = { ...(newState.scheduled_action || {}), cancelled_at_ms: now_ms };\nnewState.updated_at = now_iso;\nnewState.version = (state.version || 0) + 1;\nreturn { json: { ok: true, tel: $json.tel, state: newState, needs_write: true, log_transition: false } };"
      },
      "id": "e3770346-fc56-4b04-bfeb-f741f0669dde",
      "name": "Action Cancel Schedule",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2432,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "nw",
              "leftValue": "={{ $json.needs_write }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "801037a5-2029-4a4c-b152-f5ea4e60619d",
      "name": "IF Needs Write",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        2640,
        0
      ]
    },
    {
      "parameters": {
        "operation": "set",
        "key": "=lead:{{ $json.tel }}:state",
        "value": "={{ JSON.stringify($json.state) }}",
        "expire": true,
        "ttl": 604800
      },
      "id": "1b828e0c-c371-440e-ac46-ec3b8f4068f4",
      "name": "Redis SET State",
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        2864,
        0
      ],
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "lt",
              "leftValue": "={{ $json.log_transition }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "f5a79d59-4231-46a4-af3d-07e4a0f1a491",
      "name": "IF Log Transition",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        3088,
        0
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "=INSERT INTO wm_state_log (phone, from_step, to_step, trigger, trigger_payload) VALUES ('{{ $json.tel }}', {{ $json.from_step ? \"'\" + $json.from_step + \"'\" : 'NULL' }}, '{{ $json.to_step || $json.from_step }}', '{{ $json.log_trigger }}', '{{ JSON.stringify({intent: $json.params?.intent || null, error: $json.error || null}).replace(/'/g, \"''\") }}'::jsonb);",
        "options": {}
      },
      "id": "795893a5-5c44-4ba9-88c5-ad4e55edb34e",
      "name": "Postgres Log Transition",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        3312,
        0
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Find the action output that ran\nconst actionNames = ['Action Get','Action Transition','Action Pause Bot','Action Resume Bot','Action Clear','Action Schedule','Action Cancel Schedule'];\nlet src = $json;\nfor (const n of actionNames) {\n  try {\n    const node = $(n);\n    if (node && node.isExecuted) { src = node.item.json; break; }\n  } catch(e) {}\n}\nreturn { json: {\n  ok: src.ok !== false,\n  tel: src.tel,\n  state: src.state,\n  extra: {\n    from_step: src.from_step,\n    to_step: src.to_step,\n    actions: src.actions,\n    error: src.error,\n    paused_until_ms: src.paused_until_ms,\n    scope: src.scope,\n    state_existed: src.state_existed\n  }\n} };"
      },
      "id": "82323b4f-910b-4465-ae3c-766f276c7b57",
      "name": "Respond OK",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3520,
        0
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Parse Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Input": {
      "main": [
        [
          {
            "node": "Redis GET State",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Redis GET State": {
      "main": [
        [
          {
            "node": "Hydrate State",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hydrate State": {
      "main": [
        [
          {
            "node": "Switch Action",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch Action": {
      "main": [
        [
          {
            "node": "Action Get",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Action Transition",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Action Pause Bot",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Action Resume Bot",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Action Clear",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Action Schedule",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Action Cancel Schedule",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Action Get": {
      "main": [
        [
          {
            "node": "IF Needs Write",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Action Transition": {
      "main": [
        [
          {
            "node": "IF Needs Write",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Action Pause Bot": {
      "main": [
        [
          {
            "node": "IF Needs Write",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Action Resume Bot": {
      "main": [
        [
          {
            "node": "IF Needs Write",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Action Clear": {
      "main": [
        [
          {
            "node": "IF Needs Write",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Action Schedule": {
      "main": [
        [
          {
            "node": "IF Needs Write",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Action Cancel Schedule": {
      "main": [
        [
          {
            "node": "IF Needs Write",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Needs Write": {
      "main": [
        [
          {
            "node": "Redis SET State",
            "type": "main",
            "index": 0
          },
          {
            "node": "IF Log Transition",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "IF Log Transition",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Log Transition": {
      "main": [
        [
          {
            "node": "Postgres Log Transition",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Postgres Log Transition": {
      "main": [
        [
          {
            "node": "Respond OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Wm-State-Engine.N8N-Import. Uses redis, postgres. Webhook trigger; 17 nodes.

Source: https://gist.github.com/bruunofco/55a116efb0f447da5948234bcb04ec2e — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Data & Sheets

Wm-State-Engine.N8N-Import. Uses redis, postgres. Webhook trigger; 17 nodes.

Redis, Postgres
Data & Sheets

Wm-Admin.N8N-Import. Uses postgres, httpRequest, redis. Webhook trigger; 12 nodes.

Postgres, HTTP Request, Redis
Data & Sheets

Reagendamiento_v2. Uses executeWorkflowTrigger, redis, httpRequest, n8n-nodes-evolution-api. Event-driven trigger; 89 nodes.

Execute Workflow Trigger, Redis, HTTP Request +3
Data & Sheets

This solution enables you to manage all your Notion and Todoist tasks from different workspaces as well as your calendar events in a single place. This is 2 way sync with partial support for recurring

Redis, Notion, Todoist +6
Data & Sheets

Scraping. Uses httpRequest, postgres, @apify/n8n-nodes-apify, respondToWebhook. Webhook trigger; 61 nodes.

HTTP Request, Postgres, @Apify/N8N Nodes Apify