{
  "name": "WF-OB-1B: Follow-Up Call Scheduler",
  "nodes": [
    {
      "id": "schedule",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "45 10 * * 1-5"
            },
            {
              "field": "cronExpression",
              "expression": "0 16 * * 1-5"
            },
            {
              "field": "cronExpression",
              "expression": "15 17 * * 1-5"
            },
            {
              "field": "cronExpression",
              "expression": "30 9 * * 6"
            }
          ]
        }
      }
    },
    {
      "id": "determine_tz",
      "name": "Determine Timezone Window",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        224,
        0
      ],
      "parameters": {
        "jsCode": "var now=new Date(); var day=now.getDay(); var timezone='ET'; var businessHoursOk=true; return [{ json: { timezone:timezone, maxPerBatch:4, businessHoursOk:businessHoursOk, dayOfWeek:day } }];"
      }
    },
    {
      "id": "query_convex",
      "name": "Query Convex Follow-Ups",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        448,
        0
      ],
      "parameters": {
        "method": "GET",
        "url": "=https://YOUR_CONVEX_DEPLOYMENT/outbound-leads-due?timestamp={{ Date.now() }}&limit=20",
        "sendBody": false,
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          },
          "timeout": 15000
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "process_followups",
      "name": "Process Follow-Up Leads",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        672,
        0
      ],
      "parameters": {
        "jsCode": "var response=$input.first().json; var leads=response.leads || []; return leads.map(function(lead){ return { json: { closeLeadId:lead.closeLeadId, callSequence:lead.callSequence, lastOutcome:lead.lastOutcome||'', lastCallSummary:lead.lastCallSummary||'', isFollowUp:true } }; });"
      }
    },
    {
      "id": "lookup_close",
      "name": "Lookup Close Detail",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        896,
        0
      ],
      "parameters": {
        "method": "GET",
        "url": "=https://api.close.com/api/v1/lead/{{ $json.closeLeadId }}/?_fields=id,display_name,contacts,custom",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "sendBody": false,
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          },
          "timeout": 15000
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "enrich_followup",
      "name": "Enrich Follow-Up Data",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1120,
        0
      ],
      "parameters": {
        "jsCode": "var closeData=$json; var followUp=$('Process Follow-Up Leads').item.json; var result={}; var keys=Object.keys(closeData); for(var i=0;i<keys.length;i++){ result[keys[i]]=closeData[keys[i]]; } result.callSequence=followUp.callSequence||1; result.isFollowUp=true; result.previousOutcome=followUp.lastOutcome||''; result.previousCallSummary=followUp.lastCallSummary||''; return { json: result };"
      }
    },
    {
      "id": "filter_states",
      "name": "Filter Blocked States",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1232,
        0
      ],
      "parameters": {
        "jsCode": "var coveredStates=['OH']; var items=$input.all(); var allowed=[]; for(var i=0;i<items.length;i++){ allowed.push(items[i]); } return allowed;"
      }
    },
    {
      "id": "filter_tz",
      "name": "Filter by TZ + Extract",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1344,
        0
      ],
      "parameters": {
        "jsCode": "var leads=$input.all().map(function(item){return item.json;}); return leads.map(function(lead){ return { json: lead }; });"
      }
    },
    {
      "id": "has_leads",
      "name": "Has Leads?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1568,
        0
      ],
      "parameters": {
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "hl1",
              "leftValue": "={{ $json.no_leads }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "notEquals"
              }
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "batch",
      "name": "SplitInBatches",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        1792,
        0
      ],
      "parameters": {
        "options": {}
      }
    },
    {
      "id": "build_retell",
      "name": "Build Retell Payload",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2016,
        0
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "var lead=$json; var seq=lead.callSequence||1; var agentId='YOUR_RETELL_AGENT_ID'; var phone=''; var firstName='there'; var fromNumber='+15555550100'; var use216={'216':true,'614':true,'740':true,'380':true,'220':true}; return { json: { closeLeadId:lead.id, toNumber:phone, fromNumber:fromNumber, agentId:agentId, callSequence:seq, isFollowUp:true, retellPayload:{ from_number:fromNumber, to_number:phone, override_agent_id:agentId, retell_llm_dynamic_variables:{ firstName:firstName, callSequence:String(seq), callDirection:'outbound' } } } };"
      }
    },
    {
      "id": "call_retell",
      "name": "Call Retell API",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2240,
        0
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.retellai.com/v2/create-phone-call",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_RETELL_API_KEY"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json.retellPayload) }}",
        "options": {}
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "log_convex",
      "name": "Log Call to Convex",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2464,
        0
      ],
      "parameters": {
        "method": "POST",
        "url": "https://YOUR_CONVEX_DEPLOYMENT/outbound-call-log",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ retellCallId: $json.call_id || '', closeLeadId: $('Build Retell Payload').first().json.closeLeadId, callStatus: 'initiated' }) }}",
        "options": {}
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "update_close",
      "name": "Update Close Call Fields",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2688,
        0
      ],
      "parameters": {
        "method": "PUT",
        "url": "=https://api.close.com/api/v1/lead/{{ $('Build Retell Payload').first().json.closeLeadId }}/",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ 'custom.cf_L6lj9vbbe1pnuRA2tAAeZs6eso00WI5MI8RNf23Bykn': ($('Build Retell Payload').first().json.callSequence || 1) + 1 }) }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          },
          "timeout": 30000
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "wait_1s",
      "name": "Wait 1s",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2912,
        0
      ],
      "parameters": {
        "jsCode": "return $input.all();"
      }
    },
    {
      "id": "slack_summary",
      "name": "Slack Summary",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [
        2016,
        -220
      ],
      "parameters": {
        "resource": "message",
        "operation": "post",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "C08CZQV5QV7"
        },
        "text": "=*WF-OB-1B Follow-Up Call Batch*\n:phone: *Timezone*: {{ $('Determine Timezone Window').first().json.timezone }}\n:repeat: *Follow-Up Batch Complete*",
        "otherOptions": {}
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "sticky_overview",
      "name": "WF-OB-1B Overview",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -208,
        -350
      ],
      "parameters": {
        "content": "## WF-OB-1B: Follow-Up Call Scheduler\n\nFire FOLLOW-UP Retell AI calls (2nd-6th) for VoiceSDR. Source: Convex outbound-leads-due > Close CRM detail. Owner."
      }
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Determine Timezone Window",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Determine Timezone Window": {
      "main": [
        [
          {
            "node": "Query Convex Follow-Ups",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Query Convex Follow-Ups": {
      "main": [
        [
          {
            "node": "Process Follow-Up Leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Follow-Up Leads": {
      "main": [
        [
          {
            "node": "Lookup Close Detail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lookup Close Detail": {
      "main": [
        [
          {
            "node": "Enrich Follow-Up Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Enrich Follow-Up Data": {
      "main": [
        [
          {
            "node": "Filter Blocked States",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Blocked States": {
      "main": [
        [
          {
            "node": "Filter by TZ + Extract",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter by TZ + Extract": {
      "main": [
        [
          {
            "node": "Has Leads?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Leads?": {
      "main": [
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "SplitInBatches": {
      "main": [
        [
          {
            "node": "Slack Summary",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build Retell Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Retell Payload": {
      "main": [
        [
          {
            "node": "Call Retell API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Call Retell API": {
      "main": [
        [
          {
            "node": "Log Call to Convex",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Call to Convex": {
      "main": [
        [
          {
            "node": "Update Close Call Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Close Call Fields": {
      "main": [
        [
          {
            "node": "Wait 1s",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 1s": {
      "main": [
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "timezone": "America/New_York"
  },
  "active": false
}