{
  "name": "DocuSign Connect Listener (Part 2 of 2)",
  "nodes": [
    {
      "name": "DocuSign Connect Listener",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -368,
        -1328
      ],
      "parameters": {
        "path": "docusign-connect",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "name": "If Envelope Completed",
      "type": "n8n-nodes-base.if",
      "position": [
        -144,
        -1328
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "YOUR-ID-HERE",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ (($json.body && $json.body.event) === 'envelope-completed') || ($json.body && $json.body.data && $json.body.data.envelopeSummary && $json.body.data.envelopeSummary.status === 'completed') || ($json.event === 'envelope-completed') || ($json.status === 'completed') }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "name": "Fetch Assessment by ID",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        128,
        -1344
      ],
      "parameters": {
        "url": "=https://YOUR-PROJECT.supabase.co/rest/v1/assessments?select=*&contract_envelope_id=eq.{{ $json.body && $json.body.data ? $json.body.data.envelopeId : ($json.data ? $json.data.envelopeId : $json.envelopeId) }}&limit=1",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "supabaseApi"
      },
      "typeVersion": 4.4
    },
    {
      "name": "Normalize Assessment Data",
      "type": "n8n-nodes-base.code",
      "position": [
        336,
        -1344
      ],
      "parameters": {
        "jsCode": "// Shape-agnostic: Supabase REST may arrive as an array, a single row object, or split items.\nconst items = $input.all();\nlet row = null;\nfor (const it of items) {\n  const j = it.json;\n  if (Array.isArray(j)) { if (j.length && j[0] && j[0].id) { row = j[0]; break; } }\n  else if (j && j.id) { row = j; break; }\n}\nconst wh = ($node[\"DocuSign Connect Listener\"] && $node[\"DocuSign Connect Listener\"].json) || {};\nconst envId = (wh.body && wh.body.data && wh.body.data.envelopeId) || (wh.data && wh.data.envelopeId) || wh.envelopeId || null;\nif (!row) {\n  return [{ json: { found: false, reason: \"No assessment row found for envelopeId\", envelopeId: envId } }];\n}\nreturn [{ json: { found: true, assessment: row, envelopeId: envId } }];"
      },
      "typeVersion": 2
    },
    {
      "name": "If Assessment Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        544,
        -1344
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "YOUR-ID-HERE",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.found }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "name": "Update Contract Status in Supabase",
      "type": "n8n-nodes-base.supabase",
      "position": [
        784,
        -1360
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "id",
              "keyValue": "={{ $json.assessment.id }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "assessments",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "contract_status",
              "fieldValue": "completed"
            },
            {
              "fieldId": "contract_envelope_id",
              "fieldValue": "={{ $json.envelopeId }}"
            },
            {
              "fieldId": "contract_signed_at",
              "fieldValue": "={{ $node[\"DocuSign Connect Listener\"].json.completedDateTime ?? $node[\"DocuSign Connect Listener\"].json.statusDateTime ?? new Date().toISOString() }}"
            }
          ]
        },
        "operation": "update"
      },
      "typeVersion": 1
    },
    {
      "name": "Upsert Client in Supabase",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        976,
        -1360
      ],
      "parameters": {
        "url": "https://YOUR-PROJECT.supabase.co/rest/v1/clients?on_conflict=assessment_id",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ assessment_id: $('Normalize Assessment Data').item.json.assessment.id, business_name: $('Normalize Assessment Data').item.json.assessment.business_name, primary_contact_name: $('Normalize Assessment Data').item.json.assessment.contact_name, primary_contact_email: $('Normalize Assessment Data').item.json.assessment.contact_email, docusign_envelope_id: $('Normalize Assessment Data').item.json.envelopeId, contract_signed_at: new Date().toISOString(), status: 'active' }) }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Prefer",
              "value": "resolution=merge-duplicates,return=representation"
            }
          ]
        },
        "nodeCredentialType": "supabaseApi"
      },
      "typeVersion": 4.2
    },
    {
      "name": "Create Onboarding Session in Supabase",
      "type": "n8n-nodes-base.supabase",
      "position": [
        240,
        -768
      ],
      "parameters": {
        "tableId": "onboarding_sessions",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "client_id",
              "fieldValue": "={{ $node[\"Upsert Client in Supabase\"].json.id }}"
            },
            {
              "fieldId": "assessment_id",
              "fieldValue": "={{ $node[\"Normalize Assessment Data\"].json.assessment.id }}"
            },
            {
              "fieldId": "assigned_to_name",
              "fieldValue": "={{ $node[\"Normalize Assessment Data\"].json.assessment.contact_name }}"
            },
            {
              "fieldId": "assigned_to_email",
              "fieldValue": "={{ $node[\"Normalize Assessment Data\"].json.assessment.contact_email }}"
            },
            {
              "fieldId": "initiated_by_email",
              "fieldValue": "={{ $node[\"Normalize Assessment Data\"].json.assessment.contact_email }}"
            },
            {
              "fieldId": "status",
              "fieldValue": "created"
            },
            {
              "fieldId": "resume_token",
              "fieldValue": "={{ $node[\"Generate Session Token\"].json.resume_token }}"
            },
            {
              "fieldId": "expires_at",
              "fieldValue": "={{ new Date(Date.now() + 1000 * 60 * 60 * 24 * 30).toISOString() }}"
            },
            {
              "fieldId": "answers_json",
              "fieldValue": "={{ {} }}"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "name": "Generate Session Token",
      "type": "n8n-nodes-base.code",
      "position": [
        48,
        -768
      ],
      "parameters": {
        "jsCode": "let resume_token;\ntry { resume_token = crypto.randomUUID(); }\ncatch (e) {\n  resume_token = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (ch) => {\n    const r = Math.random() * 16 | 0; const v = ch === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16);\n  });\n}\nreturn [{ json: { resume_token } }];"
      },
      "typeVersion": 2
    },
    {
      "name": "Send Onboarding Invite via Outlook",
      "type": "n8n-nodes-base.microsoftOutlook",
      "position": [
        608,
        -768
      ],
      "parameters": {
        "subject": "={{ $('Normalize Assessment Data').item.json.assessment.is_pilot ? 'Your Company Pilot, Onboarding Questionnaire' : 'Welcome to Your Company, Let\u2019s Get You Onboarded' }}",
        "bodyContent": "=<p>Hi {{ $node[\"Normalize Assessment Data\"].json.assessment.contact_name }},</p>\n\n<p>\n{{ $('Normalize Assessment Data').item.json.assessment.is_pilot ? 'Thank you for joining the Use-Case Pilot. Your onboarding is now ready.' : 'Thank you for signing your agreement with Your Company. Your onboarding is now ready.' }}\n</p>\n\n<p>\nPlease use the link below to complete your onboarding questionnaire:\n</p>\n\n<p>\n<a href=\"https://your-domain.com/onboarding?token={{ $node['Generate Session Token'].json.resume_token }}\">\n  Start Onboarding\n</a>\n</p>\n\n<p>\nThis form is simple and can be completed in stages. If you need to stop at any time, your progress can be resumed later using the same link.\n</p>\n\n<p>\nIf someone else on your team should complete onboarding, the form will give you the option to delegate it.\n</p>\n\n<p>\nBest regards,<br/>\n<strong>Your Company</strong><br/>\nyou@your-domain.com\n</p>",
        "toRecipients": "={{ $node[\"Normalize Assessment Data\"].json.assessment.contact_email }}",
        "additionalFields": {
          "from": "user@example.com",
          "bodyContentType": "html"
        }
      },
      "typeVersion": 2
    },
    {
      "name": "Wait 24 Hours Before Invite",
      "type": "n8n-nodes-base.wait",
      "position": [
        416,
        -768
      ],
      "parameters": {
        "unit": "hours",
        "amount": 24
      },
      "typeVersion": 1.1
    },
    {
      "name": "Send Internal Notification via Gmail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        784,
        -768
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "=<p>Hi our team,</p>\n\n<p>\nA new onboarding invite was successfully sent to the client.\n</p>\n\n<p><strong>Client:</strong> {{ $node[\"Normalize Assessment Data\"].json.assessment.business_name }}<br/>\n<strong>Primary Contact:</strong> {{ $node[\"Normalize Assessment Data\"].json.assessment.contact_name }}<br/>\n<strong>Email:</strong> {{ $node[\"Normalize Assessment Data\"].json.assessment.contact_email }}<br/>\n<strong>Assessment ID / Contract ID:</strong> {{ $node[\"Normalize Assessment Data\"].json.assessment.id }}<br/>\n<strong>DocuSign Envelope ID:</strong> {{ $json.envelopeId || $node[\"Normalize Assessment Data\"].json.envelopeId || $node[\"DocuSign Connect Listener\"].json.envelopeId }}<br/>\n<strong>Onboarding Session Status:</strong> created\n</p>\n\n<p>\n<strong>Client onboarding link:</strong><br/>\n<a href=\"https://your-domain.com/onboarding?token={{ $node['Generate Session Token'].json.resume_token }}\">\n  https://your-domain.com/onboarding?token={{ $node['Generate Session Token'].json.resume_token }}\n</a>\n</p>\n\n<p>\nThis onboarding invite was scheduled and sent 24 hours after contract completion.\n</p>\n\n<p>\nBest,<br/>\nYour Company\n</p>",
        "options": {
          "appendAttribution": true
        },
        "subject": "=New client onboarding sent, {{ $node[\"Normalize Assessment Data\"].json.assessment.business_name }}"
      },
      "typeVersion": 2.2
    },
    {
      "name": "Create Welcome Email Draft",
      "type": "n8n-nodes-base.httpRequest",
      "maxTries": 4,
      "position": [
        -352,
        -768
      ],
      "parameters": {
        "url": "https://api.anthropic.com/v1/messages",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ model: \"claude-sonnet-4-6\", max_tokens: 1000, messages: [{ role: \"user\", content: \"You are writing a new client welcome email for Your Company, an AI-driven IT solutions company in Central Florida. Write a warm, professional, and energetic welcome email to a business owner who just signed their agreement.\\n\\nClient name: \" + (($('Normalize Assessment Data').item.json.assessment.contact_name) || \"\") + \"\\nBusiness name: \" + (($('Normalize Assessment Data').item.json.assessment.business_name) || \"\") + \"\\nServices recommended: \" + ((() => { const s = $('Normalize Assessment Data').item.json.assessment.recommended_services; if (Array.isArray(s)) return s.join(', '); if (typeof s === 'string') { try { const p = JSON.parse(s); return Array.isArray(p) ? p.join(', ') : s; } catch (e) { return s; } } return s ? String(s) : ''; })()) + \"\\n\\nRules:\\n- Maximum 4 sentences\\n- Warm, confident, personal tone\\n- Reference their business name naturally\\n- Make them feel they made the right decision\\n- Mention our team is their direct point of contact\\n- Never make specific outcome guarantees\\n- Plain text only, no markdown, no asterisks, no bold\\n- Do NOT start with a greeting, the email template already includes Hi [name]\\n- Sign off as: Your Name, Your Company\\n\\nReturn ONLY the email body text. No subject line. Nothing else.\" }] }) }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "anthropic-version",
              "value": "2023-06-01"
            },
            {
              "name": "content-type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "anthropicApi"
      },
      "retryOnFail": true,
      "typeVersion": 4.4,
      "waitBetweenTries": 5000
    },
    {
      "name": "Send Welcome Email via Outlook",
      "type": "n8n-nodes-base.microsoftOutlook",
      "position": [
        -160,
        -768
      ],
      "parameters": {
        "subject": "=Welcome to Your Company, {{ $('Normalize Assessment Data').item.json.assessment.business_name }}",
        "bodyContent": "=<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; color: #1a1a2e;\">\n\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n    <tr>\n      <td style=\"background: #1B4F8A; padding: 24px 32px; border-radius: 8px 8px 0 0;\">\n        <h1 style=\"color: #ffffff; margin: 0; font-size: 22px;\">Welcome to Your Company!</h1>\n        <p style=\"color: #DDDDDD; margin: 4px 0 0; font-size: 14px;\">\n          AI-Powered IT Solutions | Central Florida\n        </p>\n      </td>\n    </tr>\n  </table>\n\n  <div style=\"padding: 32px;\">\n    <p style=\"font-size: 16px;\">\n      Hi {{ $('Normalize Assessment Data').item.json.assessment.contact_name }},\n    </p>\n\n    <p style=\"line-height: 1.8;\">\n      {{ $('Create Welcome Email Draft').item.json.content[0].text.replace(/\\n/g, '<br/>') }}\n    </p>\n\n    <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin: 24px 0;\">\n      <tr>\n        <td style=\"background: #EBF2FB; border-left: 4px solid #1B4F8A; border-radius: 8px; padding: 20px 24px;\">\n          <p style=\"margin: 8px 0;\"><strong>Your Business:</strong> {{ $('Normalize Assessment Data').item.json.assessment.business_name }}</p>\n          <p style=\"margin: 8px 0;\"><strong>Your Point of Contact:</strong> Your Name</p>\n          <p style=\"margin: 8px 0;\"><strong>Direct Email:</strong> you@your-domain.com</p>\n          <p style=\"margin: 8px 0;\"><strong>Website:</strong> your-domain.com</p>\n        </td>\n      </tr>\n    </table>\n\n    <div style=\"text-align: center; margin: 32px 0;\">\n      <a href=\"https://your-domain.com\"\n         style=\"background: #F97316; color: #ffffff; padding: 14px 32px;\n                border-radius: 8px; text-decoration: none; font-weight: bold;\n                font-size: 16px;\">\n        Visit Our Portal\n      </a>\n    </div>\n\n    <p style=\"margin-top: 32px; color: #666666; font-size: 13px;\">\n      Your Company Inc.<br/>\n      Automate. Relentlessly. Ruthlessly.\u2122\n    </p>\n  </div>\n\n</div>",
        "toRecipients": "={{ $('Normalize Assessment Data').item.json.assessment.contact_email }}",
        "additionalFields": {
          "from": "user@example.com",
          "bccRecipients": "user@example.com",
          "bodyContentType": "html"
        }
      },
      "typeVersion": 2
    },
    {
      "name": "Record Draft Email Cost",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        -160,
        -592
      ],
      "parameters": {
        "mode": "each",
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR-COST-LOG-SUBWORKFLOW-ID"
        },
        "workflowInputs": {
          "value": {
            "model": "={{ $('Create Welcome Email Draft').item.json.model || '' }}",
            "provider": "anthropic",
            "node_name": "Draft Welcome Email",
            "request_id": "={{ $('Create Welcome Email Draft').item.json.id || '' }}",
            "agent_label": "",
            "input_tokens": "={{ $('Create Welcome Email Draft').item.json.usage?.input_tokens || 0 }}",
            "output_tokens": "={{ $('Create Welcome Email Draft').item.json.usage?.output_tokens || 0 }}",
            "workflow_name": "={{ $workflow.name }}"
          },
          "mappingMode": "defineBelow"
        }
      },
      "typeVersion": 1.3
    },
    {
      "name": "If Client Is Pilot",
      "type": "n8n-nodes-base.if",
      "position": [
        1152,
        -1360
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "YOUR-ID-HERE",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ String($('Normalize Assessment Data').item.json.assessment.is_pilot) === 'true' }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "name": "Send Pilot Welcome via Outlook",
      "type": "n8n-nodes-base.microsoftOutlook",
      "position": [
        -160,
        -944
      ],
      "parameters": {
        "subject": "=Welcome to the Use-Case Pilot, {{ $('Normalize Assessment Data').item.json.assessment.business_name }}",
        "bodyContent": "=<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; color: #1a1a2e;\">\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n    <tr><td style=\"background: #1B4F8A; padding: 24px 32px; border-radius: 8px 8px 0 0;\">\n      <h1 style=\"color:#fff; margin:0; font-size:22px;\">Welcome to the Use-Case Pilot!</h1>\n      <p style=\"color:#DDD; margin:4px 0 0; font-size:14px;\">AI-Powered Automation | Central Florida</p>\n    </td></tr>\n  </table>\n  <div style=\"padding: 32px; font-size:15px; line-height:1.6;\">\n    <p>Hi {{ $('Normalize Assessment Data').item.json.assessment.contact_name }},</p>\n    <p>You're in. {{ $('Normalize Assessment Data').item.json.assessment.business_name }} is officially part of the Use-Case Pilot. This is a focused, no-charge pilot where we build one real automation for your business so you can see the value before deciding anything.</p>\n    <p>Here is what happens next:</p>\n    <ul style=\"color:#333;\">\n      <li>We start building your use-case (up to three automations) within about two weeks.</li>\n      <li>You run it for a 60-day evaluation. Real workflow, real data.</li>\n      <li>It costs you nothing, and you own what we build.</li>\n    </ul>\n    <p>Within the next business day you will receive a short onboarding questionnaire so we can scope your pilot route correctly. That is the only thing we need from you to get started.</p>\n    <p>Let's build something that actually saves you time.</p>\n    <div style=\"background:#eef2f8; border-left:4px solid #1B4F8A; padding:16px 20px; margin:24px 0; font-size:14px;\">\n      <p style=\"margin:0 0 6px;\"><strong>Your Business:</strong> {{ $('Normalize Assessment Data').item.json.assessment.business_name }}</p>\n      <p style=\"margin:0 0 6px;\"><strong>Program:</strong> Use-Case Pilot (60-day, no charge)</p>\n      <p style=\"margin:0 0 6px;\"><strong>Your Point of Contact:</strong> Your Company Team</p>\n      <p style=\"margin:0;\"><strong>Website:</strong> your-domain.com</p>\n    </div>\n  </div>\n  <div style=\"padding:0 32px 24px; color:#888; font-size:12px;\">Your Company Inc.<br/>Automate. Relentlessly. Ruthlessly.&trade;</div>\n</div>",
        "toRecipients": "={{ $('Normalize Assessment Data').item.json.assessment.contact_email }}",
        "additionalFields": {
          "from": "user@example.com",
          "bccRecipients": "user@example.com",
          "bodyContentType": "html"
        }
      },
      "typeVersion": 2
    },
    {
      "name": "Build Stripe Parameters",
      "type": "n8n-nodes-base.code",
      "onError": "continueErrorOutput",
      "position": [
        1040,
        -768
      ],
      "parameters": {
        "jsCode": "const a = $('Normalize Assessment Data').item.json.assessment || {};\nconst toCents = (v) => Math.round(Number(String(v ?? '').replace(/[^0-9.]/g, '')) * 100) || 0;\nreturn [{ json: {\n  name: a.business_name || a.contact_name || 'New Client',\n  email: a.contact_email || '',\n  contact_name: a.contact_name || '',\n  retainer_cents: toCents(a.proposal_monthly_retainer),\n  setup_cents: toCents(a.proposal_one_time_fee)\n} }];"
      },
      "typeVersion": 2
    },
    {
      "name": "Create Customer in Stripe",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "maxTries": 2,
      "position": [
        1232,
        -768
      ],
      "parameters": {
        "url": "https://api.stripe.com/v1/customers",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "name",
              "value": "={{ $json.name }}"
            },
            {
              "name": "email",
              "value": "={{ $json.email }}"
            }
          ]
        },
        "nodeCredentialType": "stripeApi"
      },
      "retryOnFail": true,
      "typeVersion": 4.2,
      "waitBetweenTries": 2000
    },
    {
      "name": "Create Checkout in Stripe",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "maxTries": 2,
      "position": [
        1440,
        -768
      ],
      "parameters": {
        "url": "https://api.stripe.com/v1/checkout/sessions",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "mode",
              "value": "subscription"
            },
            {
              "name": "customer",
              "value": "={{ $('Create Customer in Stripe').item.json.id }}"
            },
            {
              "name": "success_url",
              "value": "https://your-domain.com/portal?checkout=success"
            },
            {
              "name": "cancel_url",
              "value": "https://your-domain.com/portal?checkout=cancel"
            },
            {
              "name": "line_items[0][price_data][currency]",
              "value": "usd"
            },
            {
              "name": "line_items[0][price_data][product_data][name]",
              "value": "Your Company Monthly Retainer"
            },
            {
              "name": "line_items[0][price_data][recurring][interval]",
              "value": "month"
            },
            {
              "name": "line_items[0][price_data][unit_amount]",
              "value": "={{ $('Build Stripe Parameters').item.json.retainer_cents }}"
            },
            {
              "name": "line_items[0][quantity]",
              "value": "1"
            },
            {
              "name": "line_items[1][price_data][currency]",
              "value": "usd"
            },
            {
              "name": "line_items[1][price_data][product_data][name]",
              "value": "One-Time Setup Fee"
            },
            {
              "name": "line_items[1][price_data][unit_amount]",
              "value": "={{ $('Build Stripe Parameters').item.json.setup_cents }}"
            },
            {
              "name": "line_items[1][quantity]",
              "value": "1"
            },
            {
              "name": "payment_method_types[0]",
              "value": "card"
            },
            {
              "name": "payment_method_types[1]",
              "value": "us_bank_account"
            }
          ]
        },
        "nodeCredentialType": "stripeApi"
      },
      "retryOnFail": true,
      "typeVersion": 4.2,
      "waitBetweenTries": 2000
    },
    {
      "name": "Save Customer ID in Supabase",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        1632,
        -768
      ],
      "parameters": {
        "url": "=https://YOUR-PROJECT.supabase.co/rest/v1/clients?id=eq.{{ $('Upsert Client in Supabase').item.json.id }}",
        "method": "PATCH",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ stripe_customer_id: $('Create Customer in Stripe').item.json.id }) }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Prefer",
              "value": "return=minimal"
            }
          ]
        },
        "nodeCredentialType": "supabaseApi"
      },
      "typeVersion": 4.2
    },
    {
      "name": "Send Payment Link via Outlook",
      "type": "n8n-nodes-base.microsoftOutlook",
      "onError": "continueErrorOutput",
      "position": [
        1824,
        -768
      ],
      "parameters": {
        "subject": "=Complete your setup, Your Company",
        "bodyContent": "=<div style=\"font-family: Arial, sans-serif; max-width:600px; margin:0 auto; color:#1a1a2e;\">\n  <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr><td style=\"background:#1B4F8A; padding:24px 32px; border-radius:8px 8px 0 0;\">\n    <h1 style=\"color:#fff; margin:0; font-size:22px;\">You're all set, one last step</h1>\n    <p style=\"color:#DDD; margin:4px 0 0; font-size:14px;\">Your Company | Billing</p>\n  </td></tr></table>\n  <div style=\"padding:32px; font-size:15px; line-height:1.7;\">\n    <p>Hi {{ $('Normalize Assessment Data').item.json.assessment.contact_name }},</p>\n    <p>Thank you for signing your agreement with Your Company. To activate your services, please complete your secure payment setup below. You can pay by card or by bank transfer (ACH).</p>\n    <div style=\"text-align:center; margin:32px 0;\"><a href=\"{{ $('Create Checkout in Stripe').item.json.url }}\" style=\"background:#F97316; color:#fff; padding:14px 32px; border-radius:8px; text-decoration:none; font-weight:bold; font-size:16px;\">Complete Payment Setup</a></div>\n    <p style=\"color:#666; font-size:13px;\">This is a secure checkout powered by Stripe. If you have any questions, just reply to this email.</p>\n    <p style=\"margin-top:24px; color:#666; font-size:13px;\">Your Company Inc.<br/>Automate. Relentlessly. Ruthlessly.&trade;</p>\n  </div>\n</div>",
        "toRecipients": "={{ $('Normalize Assessment Data').item.json.assessment.contact_email }}",
        "additionalFields": {
          "from": "user@example.com",
          "bccRecipients": "user@example.com",
          "bodyContentType": "html"
        }
      },
      "typeVersion": 2
    },
    {
      "name": "Fetch Signed Contract via HTTP",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        1360,
        -1360
      ],
      "parameters": {
        "url": "https://YOUR-N8N-INSTANCE/webhook/docusign/fetch-signed-contract",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ envelope_id: $('Normalize Assessment Data').item.json.envelopeId, client_id: $('Upsert Client in Supabase').item.json.id }) }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "x-fetch-token",
              "value": "YOUR-FETCH-TOKEN"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "name": "Sticky: Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -928,
        -1536
      ],
      "parameters": {
        "width": 484,
        "height": 762,
        "content": "## DocuSign Connect listener (part 2 of 2)\n\nThe receiving half almost nobody publishes. A DocuSign Connect webhook fires on envelope events; when a contract is signed this records it, creates the client, sends a welcome, kicks off onboarding, and (for non-pilot deals) starts billing by creating a Stripe customer plus a checkout session and emailing the client their payment link. Pair with **DocuSign Send Envelope** (part 1) for the full lifecycle.\n\n### Setup (replace before running)\n- Point your **DocuSign Connect** config at this workflow's webhook URL\n- Credentials: database (Supabase), email (Outlook + Gmail), Anthropic (Claude) for the welcome draft, and **Stripe** for billing\n- In the Stripe checkout node set your own success and cancel URLs and product wording; the price is read from the deal record\n- Replace the `YOUR-PROJECT.supabase.co` and other `YOUR-...` placeholders\n\n### Customization\n- Swap the Claude-drafted welcome for a fixed template, or adjust its tone in the draft node\n- Change the onboarding wait (24 hours) to fit your cadence\n- In the Stripe checkout, edit the product wording, add a coupon, or adjust the line items\n- The cost-logging node is optional, delete it if you do not track token spend"
      },
      "typeVersion": 1
    },
    {
      "name": "Sticky: 1 Receive",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -416,
        -1536
      ],
      "parameters": {
        "color": 7,
        "width": 470,
        "height": 386,
        "content": "## 1. Receive the signed event\n**DocuSign Connect Listener** receives DocuSign Connect events. **If Envelope Completed** continues only when the contract is actually signed."
      },
      "typeVersion": 1
    },
    {
      "name": "Sticky: 2 Match",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        80,
        -1536
      ],
      "parameters": {
        "color": 7,
        "width": 620,
        "height": 386,
        "content": "## 2. Match the deal\n**Fetch Assessment by ID** and **Normalize Assessment Data** look up the original deal in your database; **If Assessment Exists** guards against unknown envelopes."
      },
      "typeVersion": 1
    },
    {
      "name": "Sticky: 3 Record",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        -1536
      ],
      "parameters": {
        "color": 7,
        "width": 814,
        "height": 390,
        "content": "## 3. Record and branch\n**Update Contract Status in Supabase** and **Upsert Client in Supabase** save the signed deal. **If Client Is Pilot** splits pilot vs standard, and **Fetch Signed Contract via HTTP** pulls the signed PDF."
      },
      "typeVersion": 1
    },
    {
      "name": "Sticky: 4 Welcome + onboarding",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -416,
        -1120
      ],
      "parameters": {
        "color": 7,
        "width": 1384,
        "height": 700,
        "content": "## 4. Welcome and onboarding\nSend the welcome email (**Create Welcome Email Draft** + **Send Welcome Email via Outlook** for standard, **Send Pilot Welcome via Outlook** for pilots; **Record Draft Email Cost** logs token usage). **Generate Session Token** and **Create Onboarding Session in Supabase**, then after **Wait 24 Hours Before Invite** send **Send Onboarding Invite via Outlook** plus a **Send Internal Notification via Gmail**."
      },
      "typeVersion": 1
    },
    {
      "name": "Sticky: 5 Start billing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        992,
        -1120
      ],
      "parameters": {
        "color": 7,
        "width": 1052,
        "height": 698,
        "content": "## 5. Start billing (Stripe)\nOn the standard (non-pilot) branch, payment kicks off. **Build Stripe Parameters** reads the setup fee and monthly retainer from the deal. **Create Customer in Stripe** then **Create Checkout in Stripe** build a subscription checkout (one-time setup fee plus the recurring retainer). **Save Customer ID in Supabase** writes it back, and **Send Payment Link via Outlook** emails the client their branded checkout link."
      },
      "typeVersion": 1
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "If Client Is Pilot": {
      "main": [
        [
          {
            "node": "Send Pilot Welcome via Outlook",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Welcome Email Draft",
            "type": "main",
            "index": 0
          },
          {
            "node": "Build Stripe Parameters",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Assessment Exists": {
      "main": [
        [
          {
            "node": "Update Contract Status in Supabase",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "If Envelope Completed": {
      "main": [
        [
          {
            "node": "Fetch Assessment by ID",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Fetch Assessment by ID": {
      "main": [
        [
          {
            "node": "Normalize Assessment Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Session Token": {
      "main": [
        [
          {
            "node": "Create Onboarding Session in Supabase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Stripe Parameters": {
      "main": [
        [
          {
            "node": "Create Customer in Stripe",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Checkout in Stripe": {
      "main": [
        [
          {
            "node": "Save Customer ID in Supabase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Customer in Stripe": {
      "main": [
        [
          {
            "node": "Create Checkout in Stripe",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DocuSign Connect Listener": {
      "main": [
        [
          {
            "node": "If Envelope Completed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Assessment Data": {
      "main": [
        [
          {
            "node": "If Assessment Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upsert Client in Supabase": {
      "main": [
        [
          {
            "node": "If Client Is Pilot",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Signed Contract via HTTP",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Welcome Email Draft": {
      "main": [
        [
          {
            "node": "Record Draft Email Cost",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send Welcome Email via Outlook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 24 Hours Before Invite": {
      "main": [
        [
          {
            "node": "Send Onboarding Invite via Outlook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Customer ID in Supabase": {
      "main": [
        [
          {
            "node": "Send Payment Link via Outlook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Pilot Welcome via Outlook": {
      "main": [
        [
          {
            "node": "Generate Session Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Welcome Email via Outlook": {
      "main": [
        [
          {
            "node": "Generate Session Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Onboarding Invite via Outlook": {
      "main": [
        [
          {
            "node": "Send Internal Notification via Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Contract Status in Supabase": {
      "main": [
        [
          {
            "node": "Upsert Client in Supabase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Onboarding Session in Supabase": {
      "main": [
        [
          {
            "node": "Wait 24 Hours Before Invite",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}