{
  "id": "Fx0ytkSOkBSHuM35",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Lecture to WhatsApp Study Digest",
  "tags": [],
  "nodes": [
    {
      "id": "6ae5434f-7bdd-482f-a05f-e379fc8d6e41",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2000,
        -432
      ],
      "parameters": {
        "color": 4,
        "width": 572,
        "height": 1172,
        "content": "## Lecture to WhatsApp Study Digest \u2014 WayinVideo Summarization + GPT-4o-mini + Twilio + Google Sheets\n\nFor college students who want an instant study digest from any lecture video \u2014 delivered to WhatsApp in minutes. A student submits a lecture URL via form along with their WhatsApp number, subject, and whether it is an exam revision session. The WayinVideo Summarization API processes the video and extracts a full summary with highlights and tags. After a 90-second initial wait, the results endpoint is polled every 30 seconds until status is SUCCEEDED. GPT-4o-mini reads the summary and generates 5 key learning points, 3 exam-important concepts, and one never-forget line. A Code node builds the formatted WhatsApp message. Twilio sends it directly to the student's WhatsApp number. Google Sheets logs the digest for future reference.\n\n## How it works\n- **1. Form \u2014 Student Request** collects name, WhatsApp number, subject name, lecture video URL (YouTube, Zoom, Vimeo, Loom), and exam revision flag\n- **2. Code \u2014 Validate and Prepare** validates required fields, formats the phone number for Twilio WhatsApp (whatsapp:+countrycode format), and sets the exam tag\n- **3. HTTP \u2014 WayinVideo Submit Summarization** posts the video URL to the WayinVideo Summarization API with Authorization Bearer header and API version header\n- **4. Wait \u2014 90 Seconds** gives WayinVideo initial processing time before first poll\n- **5. HTTP \u2014 WayinVideo Get Summary Results** polls the results endpoint using the task ID from node 3\n- **6. IF \u2014 Summary Ready?** checks if status equals SUCCEEDED \u2014 TRUE: proceeds to AI | FALSE: 30-second retry wait then re-polls\n- **7. Wait \u2014 30 Second Retry** waits before re-polling\n- **8. AI Agent \u2014 Generate Study Digest** uses GPT-4o-mini to extract 5 key points, 3 exam-important concepts, and one never-forget line from the summary\n- **OpenAI \u2014 GPT-4o-mini Model** language model attached to the AI Agent\n- **9. Code \u2014 Build WhatsApp Message** parses the AI output sections and builds the formatted WhatsApp message with separators and labels\n- **10. HTTP \u2014 Send WhatsApp via Twilio** and **11. Google Sheets \u2014 Save Digest** run in parallel \u2014 Twilio sends the WhatsApp message, Sheets logs the record\n\n## Set up steps\n1. Sign up at wayin.ai \u2192 Dashboard \u2192 API Keys \u2192 Create new key. Replace `YOUR_WAYINVIDEO_API_KEY` in nodes 3 and 5. Supported video sources: YouTube, Zoom, Vimeo, Loom\n2. In **OpenAI \u2014 GPT-4o-mini Model** \u2014 connect your OpenAI API credential\n3. Sign up at twilio.com. For testing use the WhatsApp Sandbox: Console \u2192 Messaging \u2192 Try it Out \u2192 WhatsApp (recipients must send the join code once). Replace `YOUR_TWILIO_ACCOUNT_SID` and `YOUR_TWILIO_AUTH_TOKEN` in node 10. Replace `YOUR_TWILIO_WHATSAPP_NUMBER` in node 10 (format: +1234567890)\n4. In **11. Google Sheets \u2014 Save Digest** \u2014 connect Google Sheets OAuth2 credential and replace `YOUR_GOOGLE_SHEET_ID`. Create a sheet tab named Lecture Digests with columns: Student, Phone, Subject, Video URL, Key Points, Exam Concepts, Exam Tag, Date"
      },
      "typeVersion": 1
    },
    {
      "id": "2be14fcf-c8f9-4caa-810c-327d6d3894f5",
      "name": "Section \u2014 Student Request Form and Data Preparation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1360,
        -112
      ],
      "parameters": {
        "color": 5,
        "width": 420,
        "height": 388,
        "content": "## Student Request Form and Data Preparation\nForm collects lecture URL, WhatsApp number, subject, and exam flag. Code validates inputs and formats the phone number for Twilio WhatsApp delivery."
      },
      "typeVersion": 1
    },
    {
      "id": "65830ab0-f5a8-4e92-bece-17ab619b641b",
      "name": "Section \u2014 WayinVideo Summarization Submit and Poll Loop",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -848,
        -176
      ],
      "parameters": {
        "color": 6,
        "width": 1012,
        "height": 676,
        "content": "## WayinVideo Summarization Submit and Poll Loop\nHTTP posts the video URL to WayinVideo. After 90s initial wait, results are polled every 30s until status equals SUCCEEDED. task ID referenced from node 3 output throughout the loop."
      },
      "typeVersion": 1
    },
    {
      "id": "c96a2c28-00d2-4ddd-9085-a6ee4812216f",
      "name": "Section \u2014 GPT-4o-mini Digest Generation and WhatsApp Message Build",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        288,
        -208
      ],
      "parameters": {
        "color": 6,
        "width": 420,
        "height": 772,
        "content": "## GPT-4o-mini Digest Generation and WhatsApp Message Build\nGPT-4o-mini extracts 5 key points, 3 exam concepts, and one never-forget line from the summary. Code builds the formatted WhatsApp message with section separators."
      },
      "typeVersion": 1
    },
    {
      "id": "b3fc9ebe-35c9-43f5-ba53-b9391e914438",
      "name": "Section \u2014 WhatsApp Send and Sheets Log",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        -160
      ],
      "parameters": {
        "color": 4,
        "width": 324,
        "height": 580,
        "content": "## WhatsApp Send and Sheets Log\nTwilio and Sheets run in parallel from node 9. Twilio sends the digest to the student WhatsApp number. Sheets logs the full record."
      },
      "typeVersion": 1
    },
    {
      "id": "287af505-44bc-44a2-9782-c1632a32642b",
      "name": "1. Form \u2014 Student Request",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -1328,
        48
      ],
      "parameters": {
        "options": {},
        "formTitle": "Lecture to WhatsApp Digest",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Your Name",
              "placeholder": "e.g. Rahul Sharma",
              "requiredField": true
            },
            {
              "fieldLabel": "WhatsApp Number",
              "placeholder": "With country code \u2014 e.g. +919876543210",
              "requiredField": true
            },
            {
              "fieldLabel": "Subject Name",
              "placeholder": "e.g. Thermodynamics, Machine Learning",
              "requiredField": true
            },
            {
              "fieldLabel": "Lecture Video URL",
              "placeholder": "YouTube, Zoom, Vimeo or Loom link",
              "requiredField": true
            },
            {
              "fieldLabel": "Exam Revision?",
              "placeholder": "Yes or No",
              "requiredField": true
            }
          ]
        },
        "formDescription": "Paste your professor's lecture URL. You will get 5 key points and 3 exam concepts on WhatsApp in minutes."
      },
      "typeVersion": 2.2
    },
    {
      "id": "29454c6c-f33f-4c63-8aa6-c78e06266f73",
      "name": "2. Code \u2014 Validate and Prepare",
      "type": "n8n-nodes-base.code",
      "position": [
        -1088,
        48
      ],
      "parameters": {
        "jsCode": "const row = $json;\n\nconst studentName  = (row['Your Name'] || '').trim();\nconst phoneRaw     = (row['WhatsApp Number'] || '').trim();\nconst subject      = (row['Subject Name'] || '').trim();\nconst videoUrl     = (row['Lecture Video URL'] || '').trim();\nconst examRevision = (row['Exam Revision?'] || 'No').trim();\n\nif (!studentName || !phoneRaw || !videoUrl) {\n  throw new Error('Name, WhatsApp Number, and Video URL are required.');\n}\n\nlet phone = phoneRaw.replace(/[\\s\\-\\(\\)]/g, '');\nif (!phone.startsWith('+')) phone = '+' + phone;\nconst whatsappTo = 'whatsapp:' + phone;\n\nconst examTag = examRevision.toLowerCase() === 'yes' ? 'EXAM IMPORTANT' : 'Regular Lecture';\n\nreturn [{ json: { studentName, phone, whatsappTo, subject, videoUrl, examRevision, examTag } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "f32624ba-676a-45c8-82b1-edb9059ff75c",
      "name": "3. HTTP \u2014 WayinVideo Submit Summarization",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -768,
        48
      ],
      "parameters": {
        "url": "https://wayinvideo-api.wayin.ai/api/v2/summaries",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"video_url\": \"{{ $json.videoUrl }}\",\n  \"target_lang\": \"en\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_WAYINVIDEO_API_KEY"
            },
            {
              "name": "x-wayinvideo-api-version",
              "value": "v2"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "9c9d616f-a86f-498f-9b62-86d4bcb7ad1b",
      "name": "4. Wait \u2014 90 Seconds",
      "type": "n8n-nodes-base.wait",
      "position": [
        -528,
        48
      ],
      "parameters": {
        "amount": 90
      },
      "typeVersion": 1.1
    },
    {
      "id": "f577d160-4600-461a-9903-008c2ad06517",
      "name": "5. HTTP \u2014 WayinVideo Get Summary Results",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -288,
        48
      ],
      "parameters": {
        "url": "=https://wayinvideo-api.wayin.ai/api/v2/summaries/results/{{ $('3. HTTP \u2014 WayinVideo Submit Summarization').first().json.data.id }}",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_WAYINVIDEO_API_KEY"
            },
            {
              "name": "x-wayinvideo-api-version",
              "value": "v2"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "679f39b6-78c2-4fff-afd4-b789dd42a3df",
      "name": "6. IF \u2014 Summary Ready?",
      "type": "n8n-nodes-base.if",
      "position": [
        -48,
        48
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "status-check",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.data.status }}",
              "rightValue": "SUCCEEDED"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "828375e3-2cf9-4786-b606-18cb37a72517",
      "name": "7. Wait \u2014 30 Second Retry",
      "type": "n8n-nodes-base.wait",
      "position": [
        -48,
        224
      ],
      "parameters": {
        "amount": 30
      },
      "typeVersion": 1.1
    },
    {
      "id": "f89f1767-8a75-4ff9-86e6-af0b3005190c",
      "name": "8. AI Agent \u2014 Generate Study Digest",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        336,
        32
      ],
      "parameters": {
        "text": "=Subject: {{ $('2. Code \u2014 Validate and Prepare').item.json.subject }}\n\nSummary:\n{{ $json.data.summary }}\n\nHighlights:\n{{ $json.data.highlights.map((h, i) => (i+1) + '. ' + h.desc).join('\\n') }}\n\nTags: {{ $json.data.tags.join(', ') }}",
        "options": {
          "systemMessage": "You are a college study coach. From the lecture summary provided, extract exactly:\n- 5 key learning points (one sentence each, max 20 words)\n- 3 exam-important concepts (concept name + why it is exam-important, max 20 words each)\n- One never-forget line (the single most important thing from this lecture)\n\nReturn in this EXACT format:\n\nKEY_POINTS:\n1. [point]\n2. [point]\n3. [point]\n4. [point]\n5. [point]\n\nEXAM_CONCEPTS:\n[Concept name] \u2014 [why exam important]\n[Concept name] \u2014 [why exam important]\n[Concept name] \u2014 [why exam important]\n\nNEVER_FORGET:\n[single most important line from this lecture]\n\nBe specific. Extract only from the summary provided. No invented content."
        },
        "promptType": "define"
      },
      "typeVersion": 1.9
    },
    {
      "id": "d68b10ec-7bb6-40e1-a3ae-adec3cb8d12e",
      "name": "OpenAI \u2014 GPT-4o-mini Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        336,
        208
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "e6b1a1f5-bd11-42a4-bbf1-ce78a5f934ce",
      "name": "9. Code \u2014 Build WhatsApp Message",
      "type": "n8n-nodes-base.code",
      "position": [
        576,
        32
      ],
      "parameters": {
        "jsCode": "const output = $input.first().json.output || '';\n\nconst kpMatch = output.match(/KEY_POINTS:\\s*([\\s\\S]*?)(?=\\nEXAM_CONCEPTS:|$)/);\nconst ecMatch = output.match(/EXAM_CONCEPTS:\\s*([\\s\\S]*?)(?=\\nNEVER_FORGET:|$)/);\nconst nfMatch = output.match(/NEVER_FORGET:\\s*([\\s\\S]*)$/);\n\nconst keyPoints    = kpMatch ? kpMatch[1].trim() : '';\nconst examConcepts = ecMatch ? ecMatch[1].trim() : '';\nconst neverForget  = nfMatch ? nfMatch[1].trim() : '';\n\nconst ctx = $('2. Code \u2014 Validate and Prepare').item.json;\nconst subject      = ctx.subject;\nconst examTag      = ctx.examTag;\nconst whatsappTo   = ctx.whatsappTo;\nconst studentName  = ctx.studentName;\nconst phone        = ctx.phone;\nconst videoUrl     = ctx.videoUrl;\nconst examRevision = ctx.examRevision;\n\nconst message = [\n  `*Study Digest \u2014 ${subject}*`,\n  `${examTag}`,\n  ``,\n  `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,\n  `*5 KEY POINTS*`,\n  `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,\n  keyPoints,\n  ``,\n  `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,\n  `*EXAM IMPORTANT*`,\n  `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,\n  examConcepts,\n  ``,\n  `*NEVER FORGET:*`,\n  neverForget\n].join('\\n');\n\nreturn [{ json: { message, keyPoints, examConcepts, neverForget, whatsappTo, studentName, phone, subject, videoUrl, examTag, examRevision } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "fcd8e680-98d8-417c-9346-4ecd56fd8c4b",
      "name": "10. HTTP \u2014 Send WhatsApp via Twilio",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        912,
        0
      ],
      "parameters": {
        "url": "=https://api.twilio.com/2010-04-01/Accounts/YOUR_TWILIO_ACCOUNT_SID/Messages.json",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "To",
              "value": "={{ $json.whatsappTo }}"
            },
            {
              "name": "From",
              "value": "whatsapp:YOUR_TWILIO_WHATSAPP_NUMBER"
            },
            {
              "name": "Body",
              "value": "={{ $json.message }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Basic {{ Buffer.from('YOUR_TWILIO_ACCOUNT_SID:YOUR_TWILIO_AUTH_TOKEN').toString('base64') }}"
            },
            {
              "name": "Content-Type",
              "value": "application/x-www-form-urlencoded"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "a19c2591-1f8b-4910-9c23-fdaee07f8aa7",
      "name": "11. Google Sheets \u2014 Save Digest",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        912,
        176
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $now.toFormat('dd MMM yyyy HH:mm') }}",
            "Phone": "={{ $('9. Code \u2014 Build WhatsApp Message').item.json.phone }}",
            "Student": "={{ $('9. Code \u2014 Build WhatsApp Message').item.json.studentName }}",
            "Subject": "={{ $('9. Code \u2014 Build WhatsApp Message').item.json.subject }}",
            "Exam Tag": "={{ $('9. Code \u2014 Build WhatsApp Message').item.json.examTag }}",
            "Video URL": "={{ $('9. Code \u2014 Build WhatsApp Message').item.json.videoUrl }}",
            "Key Points": "={{ $('9. Code \u2014 Build WhatsApp Message').item.json.keyPoints }}",
            "Exam Concepts": "={{ $('9. Code \u2014 Build WhatsApp Message').item.json.examConcepts }}"
          },
          "schema": [
            {
              "id": "Student",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Student",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Phone",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Subject",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Subject",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Video URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Video URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Key Points",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Key Points",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Exam Concepts",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Exam Concepts",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Exam Tag",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Exam Tag",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Lecture Digests"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "b415286c-1562-4526-9a29-b892d391c532",
  "connections": {
    "4. Wait \u2014 90 Seconds": {
      "main": [
        [
          {
            "node": "5. HTTP \u2014 WayinVideo Get Summary Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6. IF \u2014 Summary Ready?": {
      "main": [
        [
          {
            "node": "8. AI Agent \u2014 Generate Study Digest",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "7. Wait \u2014 30 Second Retry",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1. Form \u2014 Student Request": {
      "main": [
        [
          {
            "node": "2. Code \u2014 Validate and Prepare",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7. Wait \u2014 30 Second Retry": {
      "main": [
        [
          {
            "node": "5. HTTP \u2014 WayinVideo Get Summary Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI \u2014 GPT-4o-mini Model": {
      "ai_languageModel": [
        [
          {
            "node": "8. AI Agent \u2014 Generate Study Digest",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "2. Code \u2014 Validate and Prepare": {
      "main": [
        [
          {
            "node": "3. HTTP \u2014 WayinVideo Submit Summarization",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "9. Code \u2014 Build WhatsApp Message": {
      "main": [
        [
          {
            "node": "10. HTTP \u2014 Send WhatsApp via Twilio",
            "type": "main",
            "index": 0
          },
          {
            "node": "11. Google Sheets \u2014 Save Digest",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8. AI Agent \u2014 Generate Study Digest": {
      "main": [
        [
          {
            "node": "9. Code \u2014 Build WhatsApp Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5. HTTP \u2014 WayinVideo Get Summary Results": {
      "main": [
        [
          {
            "node": "6. IF \u2014 Summary Ready?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3. HTTP \u2014 WayinVideo Submit Summarization": {
      "main": [
        [
          {
            "node": "4. Wait \u2014 90 Seconds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}