{ "kind": "open-flow-workflow", "version": 1, "name": "Notify Qualified Form Leads in Slack", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_4f324788c5d0e402": { "name": "Receive a lead", "kind": "webhook", "bodyFields": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "email" } ], "method": "POST" }, "n_e65259e9a6daf0a6": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_4f324788c5d0e402", "output": "body" } ] } }, "name": "Validate email", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "body" } ], "outputs": [ { "jsonSchema": { "type": "string", "format": "email", "description": "The email address to verify." }, "nullable": false, "handle": "email" } ], "name": "Validate email", "moduleId": "n_40963b3f85022ddc", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_fbe3e02ac84e68f5": { "inputs": { "email": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_e65259e9a6daf0a6", "output": "email" } ] } }, "name": "Verify email with Hunter", "kind": "task", "task": { "inputs": [ { "description": "The email address to verify.", "jsonSchema": { "type": "string", "format": "email", "description": "The email address to verify." }, "nullable": false, "handle": "email" } ], "outputs": [ { "description": "An arbitrary JSON object returned by Hunter.", "jsonSchema": { "type": "object", "properties": {}, "additionalProperties": true, "description": "An arbitrary JSON object returned by Hunter." }, "nullable": false, "handle": "output" } ], "name": "Verify email with Hunter", "executor": { "kind": "connector", "action": "hunter.email_verifier", "outputMode": "value" } } }, "n_9e74a3ad05b3e8f2": { "inputs": { "response": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_fbe3e02ac84e68f5", "output": "output" } ] }, "email": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_e65259e9a6daf0a6", "output": "email" } ] } }, "name": "Check the verification", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "object", "properties": {}, "additionalProperties": true, "description": "An arbitrary JSON object returned by Hunter." }, "nullable": false, "handle": "response" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "email" } ], "outputs": [ { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "valid" } ], "name": "Check the verification", "moduleId": "n_a565e06ef15f7838", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_2340286195b22bcf": { "inputs": {}, "name": "Email valid?", "kind": "condition", "matchMode": "first", "cases": [ { "output": "yes", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_9e74a3ad05b3e8f2", "output": "valid" } }, "operator": "isTrue" } ] } ] } ] }, "n_af832d59c83980c7": { "inputs": { "url": { "kind": "value", "value": "https://api.madkudu.com/v1/persons" }, "query.email": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_e65259e9a6daf0a6", "output": "email" } ] }, "auth.token": { "kind": "unset" } }, "name": "Look up customer fit", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": { "anyOf": [ { "type": [ "string", "number", "boolean" ] }, { "type": "array", "items": { "type": [ "string", "number", "boolean" ] } } ] }, "nullable": true, "handle": "query.email" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "auth.token" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Look up customer fit", "executor": { "method": "GET", "query": { "mode": "fields", "names": [ "email" ] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "none", "authentication": { "type": "apiKey", "name": "Authorization", "in": "header" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_8a028f6bd912d6d0": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_af832d59c83980c7", "output": "body" } ] }, "email": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_e65259e9a6daf0a6", "output": "email" } ] } }, "name": "Check customer fit", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "email" } ], "outputs": [ { "jsonSchema": { "type": "number" }, "nullable": false, "handle": "score" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "qualified" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "text" } ], "name": "Check customer fit", "moduleId": "n_51a1e6a5ff09f595", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_fc4f51d85db5f538": { "inputs": {}, "name": "Score above 60?", "kind": "condition", "matchMode": "first", "cases": [ { "output": "yes", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_8a028f6bd912d6d0", "output": "qualified" } }, "operator": "isTrue" } ] } ] } ] }, "n_9a093cd6324a6096": { "inputs": { "channelId": { "kind": "value", "value": "YOUR_SLACK_CHANNEL_ID" }, "text": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_8a028f6bd912d6d0", "output": "text" } ] } }, "name": "Notify Slack", "kind": "task", "task": { "inputs": [ { "description": "The Slack conversation or channel ID.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The Slack conversation or channel ID." }, "nullable": false, "handle": "channelId" }, { "description": "Plain text message content. When blocks are provided, Slack uses this as notification and accessibility fallback text.", "jsonSchema": { "type": "string", "description": "Plain text message content. When blocks are provided, Slack uses this as notification and accessibility fallback text." }, "nullable": true, "handle": "text", "value": null }, { "description": "Slack Block Kit blocks to render in the message.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "A Slack Block Kit block object. Pass the block exactly as Slack documents it." }, "minItems": 1, "description": "Slack Block Kit blocks to render in the message." }, "nullable": true, "handle": "blocks", "value": null }, { "description": "Slack legacy attachments to include in the message.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "A Slack legacy attachment object. Prefer blocks for new messages when possible." }, "minItems": 1, "description": "Slack legacy attachments to include in the message." }, "nullable": true, "handle": "attachments", "value": null }, { "description": "Whether Slack should unfurl links in the message.", "jsonSchema": { "type": "boolean", "description": "Whether Slack should unfurl links in the message." }, "nullable": true, "handle": "unfurlLinks", "value": null }, { "description": "Whether Slack should unfurl media in the message.", "jsonSchema": { "type": "boolean", "description": "Whether Slack should unfurl media in the message." }, "nullable": true, "handle": "unfurlMedia", "value": null }, { "description": "Slack message metadata to attach to the message.", "jsonSchema": { "type": "object", "properties": {}, "additionalProperties": true, "description": "Slack message metadata to attach to the message." }, "nullable": true, "handle": "metadata", "value": null } ], "outputs": [ { "description": "The timestamp identifier of the posted message.", "jsonSchema": { "type": "string", "description": "The timestamp identifier of the posted message." }, "nullable": false, "handle": "ts" }, { "description": "The channel ID where the message was posted.", "jsonSchema": { "type": "string", "description": "The channel ID where the message was posted." }, "nullable": false, "handle": "channelId" } ], "name": "Notify Slack", "executor": { "kind": "connector", "action": "slack.post_message" } } } }, "edges": [ { "source": "n_4f324788c5d0e402", "target": "n_e65259e9a6daf0a6" }, { "source": "n_e65259e9a6daf0a6", "target": "n_fbe3e02ac84e68f5" }, { "source": "n_fbe3e02ac84e68f5", "target": "n_9e74a3ad05b3e8f2" }, { "source": "n_9e74a3ad05b3e8f2", "target": "n_2340286195b22bcf" }, { "source": "n_2340286195b22bcf", "target": "n_af832d59c83980c7", "sourceHandle": "yes" }, { "source": "n_af832d59c83980c7", "target": "n_8a028f6bd912d6d0" }, { "source": "n_8a028f6bd912d6d0", "target": "n_fc4f51d85db5f538" }, { "source": "n_fc4f51d85db5f538", "target": "n_9a093cd6324a6096", "sourceHandle": "yes" } ] } }, "modules": { "n_40963b3f85022ddc": { "name": "Validate email", "imports": [], "source": "export default function main({body}) {\n const email = body?.email;\n if (typeof email !== 'string' || !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email.trim())) throw Error('Provide a valid email address');\n return {email:email.trim()};\n}\n" }, "n_a565e06ef15f7838": { "name": "Check the verification", "imports": [], "source": "export default function main({response,email}) {\n const data=response?.data;\n if (!data || typeof data.status !== 'string' || typeof data.email !== 'string' || data.email.toLowerCase() !== email.toLowerCase()) throw Error('Hunter returned an incomplete or mismatched assessment');\n if (!['valid','invalid','accept_all','webmail','disposable','unknown'].includes(data.status)) throw Error('Hunter returned an unexpected status');\n return {valid:data.status === 'valid'};\n}\n" }, "n_51a1e6a5ff09f595": { "name": "Check customer fit", "imports": [], "source": "export default function main({body,email}) {\n const fit=body?.properties?.customer_fit,signals=fit?.top_signals_formated ?? fit?.top_signals_formatted;\n if(!fit||typeof fit.score!=='number'||!Number.isFinite(fit.score)||typeof signals!=='string')throw Error('MadKudu returned an incomplete customer fit');\n if(typeof body.email!=='string'||body.email.toLowerCase()!==email.toLowerCase())throw Error('MadKudu returned a different email');\n const optional=v=>{if(v==null)return '';if(typeof v!=='string')throw Error('Invalid lead detail');return v.replaceAll('&','&').replaceAll('<','<').replaceAll('>','>')};\n const p=body.properties,c=body.company?.properties??{},l=c.location??{};\n const text=`⭐ Got a hot lead for you ${optional(p.first_name)} ${optional(p.last_name)} from ${optional(c.name)} (${optional(c.domain)}) based out of ${optional(l.state)}, ${optional(l.country)}.\\n\\n\\n${optional(signals)}`;\n if(text.length>40000)throw Error('Slack message exceeds the size limit');\n return {score:fit.score,qualified:fit.score>60,text};\n}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }