This workflow corresponds to n8n.io template #13593 — we link there as the canonical source.
This workflow follows the Agent → Emailsend recipe pattern — see all workflows that pair these two integrations.
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 →
{
"id": "TXjq0tor23oALYeC",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "AI Customer Call Analyzer \u2014 Voice to Insights to CRM with GPT-4",
"tags": [],
"nodes": [
{
"id": "40ad9913-82b4-4a28-82b8-8acd76c22468",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-384,
-64
],
"parameters": {
"width": 780,
"height": 1160,
"content": "## AI Customer Call Analyzer \u2014 Voice \u2192 Insights \u2192 CRM with GPT-4\n\nConverts raw sales call recordings into structured CRM intelligence. Uploads audio \u2192 transcribes via Whisper \u2192 GPT-4 extracts intent, sentiment, objections, next steps \u2192 updates CRM and sends a structured summary to the sales team.\n\n### How it works\n\n1. **Upload Call Recording** - Webhook receives audio file upload (mp3, wav, m4a) from sales rep portal\n2. **Validate & Prepare Audio** - Checks file type, size limits, extracts call metadata\n3. **Transcribe via Whisper** - Sends audio to OpenAI Whisper API for high-accuracy transcription\n4. **Wait \u2014 Transcription Buffer** - Holds until transcription is confirmed complete\n5. **GPT-4 Call Intelligence** - Extracts intent, sentiment, objections, buying signals, action items\n6. **MCP Context Enrichment** - Pulls CRM history and enriches analysis with account context\n7. **Update CRM Record** - Writes structured insights back to CRM (HubSpot / Salesforce)\n8. **Send Sales Summary** - Emails rep and manager with call scorecard and next steps\n9. **Audit Log** - Records all processing steps for compliance and coaching\n\n### Setup Steps\n\n1. Import this workflow into n8n\n2. Configure credentials:\n - **OpenAI API** - For Whisper transcription and GPT-4 analysis\n - **HubSpot / Salesforce** - CRM update target\n - **Google Sheets** - Audit log and call registry\n - **SMTP / Gmail** - Sales summary delivery\n3. Set your CRM API endpoint and field mapping in the update node\n4. Configure your sales team email list in the notify node\n5. Activate the workflow\n\n### Sample Upload Payload\n```json\n{\n \"callId\": \"CALL-20250222-0042\",\n \"repEmail\": \"jane.smith@company.com\",\n \"repName\": \"Jane Smith\",\n \"contactEmail\": \"buyer@prospect.com\",\n \"contactName\": \"Bob Johnson\",\n \"companyName\": \"Acme Corp\",\n \"dealStage\": \"negotiation\",\n \"callDurationSecs\": 1847,\n \"audioUrl\": \"https://storage.company.com/calls/call-0042.mp3\"\n}\n```\n\n### Features\n- **Whisper-powered transcription** with speaker diarization hints\n- **GPT-4 intent and sentiment** extraction with confidence scores\n- **Objection and buying signal** detection\n- **Auto CRM field mapping** \u2014 no manual data entry\n- **Sales scorecard** with talk ratio, next step clarity, deal risk\n- **Full audit trail** for call coaching and compliance"
},
"typeVersion": 1
},
{
"id": "4db57828-168e-4946-ba7c-4498e6e12efb",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
532,
264
],
"parameters": {
"color": 4,
"width": 440,
"height": 328,
"content": "## 1. Call Upload & Validation"
},
"typeVersion": 1
},
{
"id": "cf4eba0e-589a-4d35-96fc-55e58fc08286",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1008,
272
],
"parameters": {
"color": 4,
"width": 636,
"height": 332,
"content": "## 2. Transcription & Wait Buffer"
},
"typeVersion": 1
},
{
"id": "77e5f6e9-e6c8-4082-af85-f91373d6a143",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1664,
304
],
"parameters": {
"color": 4,
"width": 720,
"height": 476,
"content": "## 3. GPT-4 Intelligence & MCP Enrichment"
},
"typeVersion": 1
},
{
"id": "ede89085-3097-4a4e-a036-18485b280e36",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
2464,
240
],
"parameters": {
"color": 4,
"width": 1240,
"height": 492,
"content": "## 4. CRM Update, Summary & Audit"
},
"typeVersion": 1
},
{
"id": "6a47226b-b440-4741-ac96-e0c018786666",
"name": "Receive Call Recording Upload",
"type": "n8n-nodes-base.webhook",
"position": [
592,
432
],
"parameters": {
"path": "call-upload",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "0172d15d-ef94-4d4e-b7e7-cd24b3149600",
"name": "Validate Call Metadata and Audio",
"type": "n8n-nodes-base.code",
"position": [
816,
432
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const body = $input.item.json.body || $input.item.json;\n\n// Required metadata fields\nconst required = ['callId', 'repEmail', 'repName', 'contactEmail', 'contactName', 'companyName'];\nconst missing = required.filter(f => !body[f]);\nif (missing.length > 0) {\n throw new Error(`Missing required call metadata: ${missing.join(', ')}`);\n}\n\n// Validate email formats\nconst emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nif (!emailRegex.test(body.repEmail)) {\n throw new Error(`Invalid rep email: ${body.repEmail}`);\n}\nif (!emailRegex.test(body.contactEmail)) {\n throw new Error(`Invalid contact email: ${body.contactEmail}`);\n}\n\n// Validate audio URL or binary\nconst audioUrl = body.audioUrl || body.audio_url || null;\nif (!audioUrl && !$input.item.binary?.audio) {\n throw new Error('No audio provided: supply audioUrl or binary audio attachment');\n}\n\n// Duration validation\nconst durationSecs = parseInt(body.callDurationSecs) || 0;\nif (durationSecs > 7200) {\n throw new Error(`Call too long: ${durationSecs}s exceeds 2-hour maximum for processing`);\n}\n\n// Deal stage normalization\nconst validStages = ['prospecting', 'qualification', 'discovery', 'demo', 'proposal', 'negotiation', 'closed_won', 'closed_lost'];\nconst dealStage = body.dealStage?.toLowerCase().replace(/ /g, '_') || 'unknown';\n\n// Build normalized call record\nconst callRecord = {\n callId: body.callId.trim(),\n repEmail: body.repEmail.trim().toLowerCase(),\n repName: body.repName.trim(),\n repManagerEmail: body.repManagerEmail || null,\n contactEmail: body.contactEmail.trim().toLowerCase(),\n contactName: body.contactName.trim(),\n companyName: body.companyName.trim(),\n dealStage: validStages.includes(dealStage) ? dealStage : 'unknown',\n dealValue: body.dealValue ? parseFloat(body.dealValue) : null,\n crmContactId: body.crmContactId || null,\n crmDealId: body.crmDealId || null,\n audioUrl,\n callDurationSecs: durationSecs,\n callDurationMins: Math.round(durationSecs / 60),\n callDate: body.callDate || new Date().toISOString(),\n language: body.language || 'en',\n product: body.product || 'General',\n notes: body.notes || null,\n processingId: `PROC-${Date.now()}-${Math.random().toString(36).substr(2, 8).toUpperCase()}`,\n receivedAt: new Date().toISOString(),\n status: 'VALIDATED'\n};\n\nreturn { json: { callRecord } };"
},
"typeVersion": 2
},
{
"id": "80e939d8-6099-41ea-8ea1-c3a88da1e03f",
"name": "Fetch Audio File from URL",
"type": "n8n-nodes-base.httpRequest",
"position": [
1040,
432
],
"parameters": {
"url": "={{ $json.callRecord.audioUrl }}",
"options": {
"timeout": 30000,
"response": {
"response": {
"responseFormat": "file"
}
}
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "1f508b12-4ba4-4dcc-b1fc-a0164530cc5a",
"name": "Transcribe Audio with OpenAI Whisper",
"type": "n8n-nodes-base.httpRequest",
"position": [
1264,
432
],
"parameters": {
"url": "https://api.openai.com/v1/audio/transcriptions",
"method": "POST",
"options": {
"timeout": 120000
},
"sendBody": true,
"sendHeaders": true,
"specifyBody": "multipartFormData",
"authentication": "predefinedCredentialType",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $credentials.apiKey }}"
}
]
},
"nodeCredentialType": "openAiApi"
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "61fd5aa1-f5c4-4e0d-a5f0-5e8682d8ec73",
"name": "Wait \u2014 Transcription Buffer (15 sec)",
"type": "n8n-nodes-base.wait",
"position": [
1488,
432
],
"parameters": {
"amount": 15
},
"typeVersion": 1.1
},
{
"id": "cfaf7087-38a1-4d6f-8eb8-134dde1774c4",
"name": "Parse and Structure Transcript",
"type": "n8n-nodes-base.code",
"position": [
1712,
432
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const whisperResponse = $('Transcribe Audio with OpenAI Whisper').item.json;\nconst callRecord = $('Validate Call Metadata and Audio').item.json.callRecord;\n\n// Validate transcription succeeded\nif (!whisperResponse || whisperResponse.error) {\n throw new Error(`Whisper transcription failed: ${whisperResponse?.error?.message || 'Unknown error'}`);\n}\n\nconst fullText = whisperResponse.text || '';\nif (!fullText.trim()) {\n throw new Error('Transcription returned empty text. Audio may be silent or corrupted.');\n}\n\n// Extract segment-level data for analysis\nconst segments = whisperResponse.segments || [];\nconst totalDuration = whisperResponse.duration || callRecord.callDurationSecs;\n\n// Calculate word count and speaking pace\nconst wordCount = fullText.split(/\\s+/).filter(w => w.length > 0).length;\nconst wordsPerMinute = totalDuration > 0 ? Math.round((wordCount / totalDuration) * 60) : 0;\n\n// Estimate speaker turns (basic heuristic: long pauses between segments)\nconst speakerTurns = segments.filter((seg, idx) => {\n if (idx === 0) return false;\n const gap = seg.start - segments[idx - 1].end;\n return gap > 1.5; // 1.5s gap = likely speaker change\n}).length;\n\n// Chunk transcript for GPT-4 (max 12k chars per chunk to stay in context)\nconst CHUNK_SIZE = 12000;\nconst chunks = [];\nfor (let i = 0; i < fullText.length; i += CHUNK_SIZE) {\n chunks.push(fullText.substring(i, i + CHUNK_SIZE));\n}\n\nreturn {\n json: {\n callRecord,\n transcript: {\n fullText,\n wordCount,\n wordsPerMinute,\n totalDurationSecs: totalDuration,\n segmentCount: segments.length,\n estimatedSpeakerTurns: speakerTurns,\n language: whisperResponse.language || callRecord.language,\n chunkCount: chunks.length,\n transcriptChunk: chunks[0], // primary chunk for GPT-4\n transcribedAt: new Date().toISOString()\n }\n }\n};"
},
"typeVersion": 2
},
{
"id": "9010cd1a-7b5f-4c19-a5b1-c18cdd435e55",
"name": "Fetch CRM Contact History",
"type": "n8n-nodes-base.httpRequest",
"position": [
1936,
432
],
"parameters": {
"url": "=https://api.hubapi.com/crm/v3/contacts/search",
"method": "POST",
"options": {
"timeout": 10000
},
"jsonBody": "={\n \"filterGroups\": [{\n \"filters\": [{\n \"propertyName\": \"email\",\n \"operator\": \"EQ\",\n \"value\": \"{{ $json.callRecord.contactEmail }}\"\n }]\n }],\n \"properties\": [\"email\", \"firstname\", \"lastname\", \"company\", \"dealstage\", \"lifecyclestage\", \"hs_lead_status\", \"num_contacted_notes\", \"recent_deal_amount\", \"notes_last_contacted\"]\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"nodeCredentialType": "hubspotApi"
},
"credentials": {
"hubspotApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "fd05714e-1a80-45d9-b1bd-473df7adb57f",
"name": "GPT-4 Call Intelligence Analysis",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
2160,
432
],
"parameters": {
"text": "=You are an expert sales call analyst and conversation intelligence specialist. Analyze this sales call transcript and extract structured intelligence for CRM enrichment and sales coaching.\n\n**Call Metadata:**\n- Call ID: {{ $json.callRecord.callId }}\n- Sales Rep: {{ $json.callRecord.repName }}\n- Contact: {{ $json.callRecord.contactName }} at {{ $json.callRecord.companyName }}\n- Deal Stage: {{ $json.callRecord.dealStage }}\n- Deal Value: {{ $json.callRecord.dealValue ? '$' + $json.callRecord.dealValue : 'Unknown' }}\n- Call Duration: {{ $json.transcript.totalDurationSecs }}s ({{ $json.transcript.wordCount }} words)\n- Words per Minute: {{ $json.transcript.wordsPerMinute }}\n- Estimated Speaker Turns: {{ $json.transcript.estimatedSpeakerTurns }}\n- Product/Service: {{ $json.callRecord.product }}\n\n**CRM History Summary:**\n{{ $json.crmContext || 'No prior CRM history found for this contact' }}\n\n**Call Transcript:**\n{{ $json.transcript.transcriptChunk }}\n\n**Analysis Tasks:**\n1. Overall call sentiment (prospect and rep separately)\n2. Primary intent of the prospect \u2014 what did they actually want?\n3. Key objections raised (price, timing, competition, authority, need)\n4. Buying signals detected (urgency, budget mentions, decision timeline, positive language)\n5. Topics discussed and time allocation\n6. Questions asked by prospect (these indicate interest areas)\n7. Next steps agreed upon (committed vs soft)\n8. Deal risk indicators\n9. Rep performance scorecard\n10. Recommended CRM updates\n\n**Response Format (JSON only, no markdown):**\n{\n \"overallSentiment\": \"positive | neutral | negative | mixed\",\n \"prospectSentiment\": \"positive | neutral | negative | mixed\",\n \"repSentiment\": \"confident | neutral | uncertain | pressured\",\n \"sentimentScore\": 72,\n \"primaryIntent\": \"evaluation | complaint | purchase_ready | information_gathering | negotiation | churn_risk | renewal\",\n \"intentConfidence\": 88,\n \"callSummary\": \"3-4 sentence plain English summary of the call\",\n \"keyTopics\": [\"pricing\", \"integration\", \"security\"],\n \"objections\": [\n {\n \"type\": \"price | timing | competition | authority | need | trust\",\n \"verbatim\": \"exact or close quote from transcript\",\n \"wasAddressed\": true,\n \"addressedEffectively\": true\n }\n ],\n \"buyingSignals\": [\n {\n \"signal\": \"description of signal\",\n \"strength\": \"strong | moderate | weak\",\n \"verbatim\": \"quote from transcript\"\n }\n ],\n \"prospectQuestions\": [\"list of key questions the prospect asked\"],\n \"nextSteps\": [\n {\n \"action\": \"description of next step\",\n \"owner\": \"rep | prospect | both\",\n \"deadline\": \"date or timeframe or null\",\n \"commitment\": \"hard | soft | unclear\"\n }\n ],\n \"dealRisk\": \"low | medium | high | critical\",\n \"dealRiskFactors\": [\"list of risk indicators\"],\n \"dealMomentum\": \"accelerating | stable | slowing | stalled\",\n \"recommendedDealStage\": \"prospecting | qualification | discovery | demo | proposal | negotiation | closed_won | closed_lost\",\n \"stageChangeJustification\": \"why the stage should or should not change\",\n \"repScorecard\": {\n \"listeningScore\": 78,\n \"objectionHandlingScore\": 65,\n \"nextStepClarityScore\": 90,\n \"talkListenRatio\": \"60:40\",\n \"coachingTip\": \"one specific, actionable coaching tip for the rep\"\n },\n \"crmUpdates\": {\n \"dealStage\": \"recommended stage\",\n \"nextActivityDate\": \"ISO date or null\",\n \"nextActivityType\": \"call | email | demo | proposal | meeting | null\",\n \"contactNotes\": \"2-3 sentence CRM note to log\",\n \"dealNotes\": \"2-3 sentence deal note\",\n \"customFields\": {\n \"last_objection_type\": \"price\",\n \"buying_signal_count\": 3,\n \"call_sentiment_score\": 72\n }\n },\n \"competitorsmentioned\": [\"list of competitors mentioned, empty if none\"],\n \"pricingDiscussed\": true,\n \"budgetMentioned\": false,\n \"decisionMakerOnCall\": true,\n \"followUpEmailDraft\": \"A short, professional follow-up email draft the rep can send after the call\"\n}",
"options": {
"systemMessage": "You are a sales call intelligence analyst. Respond with valid JSON only \u2014 no markdown, no code blocks, no preamble. Be specific and quote from the transcript wherever possible. Focus on actionable insights that help reps close deals faster."
},
"promptType": "define"
},
"typeVersion": 1.6
},
{
"id": "e82ed233-d4d9-4cff-a6b5-8691b2b68bc2",
"name": "GPT-4 Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
2232,
656
],
"parameters": {
"model": "gpt-4o",
"options": {
"maxTokens": 4000,
"temperature": 0.2
}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "3d588a16-4e9d-49b8-8c9f-4a434fa05ead",
"name": "Parse GPT-4 Intelligence Output",
"type": "n8n-nodes-base.code",
"position": [
2512,
432
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const aiResponse = $input.item.json;\nlet aiText = aiResponse.response || aiResponse.output || aiResponse.text || '';\n\nif (aiResponse.content && Array.isArray(aiResponse.content)) {\n aiText = aiResponse.content[0]?.text || aiResponse.content[0]?.message?.content || '';\n}\n\nconst cleanText = aiText.replace(/```json\\s*/g, '').replace(/```\\s*/g, '').trim();\n\nlet intelligence;\ntry {\n intelligence = JSON.parse(cleanText);\n} catch (e) {\n throw new Error(`Failed to parse GPT-4 call intelligence: ${e.message}. Raw: ${cleanText.substring(0, 300)}`);\n}\n\nconst callData = $('Parse and Structure Transcript').item.json;\nconst crmResponse = $('Fetch CRM Contact History').item.json;\n\n// Extract CRM contact ID if found\nconst crmContact = crmResponse?.results?.[0] || null;\nconst crmContactId = crmContact?.id || callData.callRecord.crmContactId || null;\n\nreturn {\n json: {\n callRecord: callData.callRecord,\n transcript: callData.transcript,\n intelligence,\n crmContactId,\n crmContact,\n processedAt: new Date().toISOString()\n }\n};"
},
"typeVersion": 2
},
{
"id": "a73f3a33-23df-481d-b600-20510aa54ef9",
"name": "Update CRM Contact and Deal",
"type": "n8n-nodes-base.httpRequest",
"position": [
2736,
336
],
"parameters": {
"url": "=https://api.hubapi.com/crm/v3/contacts/{{ $json.crmContactId || 'search' }}",
"method": "PATCH",
"options": {
"timeout": 15000
},
"jsonBody": "={\n \"properties\": {\n \"hs_lead_status\": \"{{ $json.intelligence.recommendedDealStage }}\",\n \"notes_last_contacted\": \"{{ new Date().toISOString() }}\",\n \"hubspot_owner_id\": \"{{ $json.callRecord.repEmail }}\",\n \"hs_content_membership_notes\": \"{{ $json.intelligence.crmUpdates.contactNotes }}\",\n \"call_sentiment_score\": \"{{ $json.intelligence.sentimentScore }}\",\n \"last_objection_type\": \"{{ ($json.intelligence.objections[0] && $json.intelligence.objections[0].type) || 'none' }}\",\n \"buying_signal_count\": \"{{ ($json.intelligence.buyingSignals || []).length }}\",\n \"deal_momentum\": \"{{ $json.intelligence.dealMomentum }}\",\n \"competitors_mentioned\": \"{{ ($json.intelligence.competitorsmentioned || []).join(', ') }}\",\n \"last_call_id\": \"{{ $json.callRecord.callId }}\",\n \"last_call_summary\": \"{{ $json.intelligence.callSummary }}\",\n \"deal_risk_level\": \"{{ $json.intelligence.dealRisk }}\"\n }\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"nodeCredentialType": "hubspotApi"
},
"credentials": {
"hubspotApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "23b60433-4148-472b-ad0f-894bd1653b79",
"name": "Log Call Activity in CRM",
"type": "n8n-nodes-base.httpRequest",
"position": [
2736,
528
],
"parameters": {
"url": "https://api.hubapi.com/crm/v3/objects/calls",
"method": "POST",
"options": {
"timeout": 10000
},
"jsonBody": "={\n \"properties\": {\n \"hs_call_title\": \"Sales Call \u2014 {{ $json.callRecord.companyName }} | {{ $json.intelligence.primaryIntent }}\",\n \"hs_call_body\": \"{{ $json.intelligence.crmUpdates.dealNotes }}\\n\\nNext Steps:\\n{{ ($json.intelligence.nextSteps || []).map((ns, i) => (i+1) + '. ' + ns.action + ' (' + ns.commitment + ')').join('\\n') }}\",\n \"hs_call_duration\": \"{{ $json.callRecord.callDurationSecs * 1000 }}\",\n \"hs_call_direction\": \"OUTBOUND\",\n \"hs_call_disposition\": \"{{ $json.intelligence.overallSentiment === 'positive' ? 'connected' : 'left_voicemail' }}\",\n \"hs_call_status\": \"COMPLETED\",\n \"hs_timestamp\": \"{{ new Date($json.callRecord.callDate).getTime() }}\",\n \"hs_activity_type\": \"CALL\"\n },\n \"associations\": [\n {\n \"to\": { \"id\": \"{{ $json.crmContactId }}\" },\n \"types\": [{ \"associationCategory\": \"HUBSPOT_DEFINED\", \"associationTypeId\": 194 }]\n }\n ]\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"nodeCredentialType": "hubspotApi"
},
"credentials": {
"hubspotApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "f78882a7-647b-4cf3-83a8-61340b455519",
"name": "Send Call Intelligence Summary to Sales Team",
"type": "n8n-nodes-base.emailSend",
"position": [
2960,
336
],
"parameters": {
"options": {},
"subject": "=[Call Intelligence] {{ $json.callRecord.companyName }} \u2014 {{ $json.intelligence.overallSentiment.toUpperCase() }} | {{ $json.intelligence.dealRisk.toUpperCase() }} Risk | {{ $json.callRecord.callId }}",
"toEmail": "=",
"fromEmail": "="
},
"credentials": {
"smtp": {
"name": "<your credential>"
}
},
"typeVersion": 2.1,
"continueOnFail": true
},
{
"id": "29209d55-d9c2-4b04-8945-7d7e05d8f4c9",
"name": "Write to Call Analytics Audit Log",
"type": "n8n-nodes-base.googleSheets",
"position": [
2960,
528
],
"parameters": {
"columns": {
"value": {},
"schema": [],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "="
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "="
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5,
"continueOnFail": true
},
{
"id": "f315cf24-d388-49b2-b0f9-f1fe799507a6",
"name": "Build Final Processing Response",
"type": "n8n-nodes-base.code",
"position": [
3184,
432
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const data = $input.item.json;\n\nreturn {\n json: {\n success: true,\n callId: data.callRecord.callId,\n processingId: data.callRecord.processingId,\n repName: data.callRecord.repName,\n companyName: data.callRecord.companyName,\n transcriptionStats: {\n wordCount: data.transcript.wordCount,\n durationSecs: data.transcript.totalDurationSecs,\n language: data.transcript.language\n },\n callIntelligence: {\n sentiment: data.intelligence.overallSentiment,\n sentimentScore: data.intelligence.sentimentScore,\n primaryIntent: data.intelligence.primaryIntent,\n dealRisk: data.intelligence.dealRisk,\n dealMomentum: data.intelligence.dealMomentum,\n buyingSignals: (data.intelligence.buyingSignals || []).length,\n objections: (data.intelligence.objections || []).length,\n nextSteps: (data.intelligence.nextSteps || []).length,\n recommendedStage: data.intelligence.recommendedDealStage\n },\n repScorecard: data.intelligence.repScorecard,\n crmUpdated: true,\n crmContactId: data.crmContactId,\n summaryEmailSent: true,\n processedAt: data.processedAt\n }\n};"
},
"typeVersion": 2
},
{
"id": "fb526474-5ad5-4c69-8447-d36a4661da49",
"name": "Return Processing Confirmation",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
3408,
432
],
"parameters": {
"options": {
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "X-Processing-ID",
"value": "={{ $json.processingId }}"
},
{
"name": "X-Call-Sentiment",
"value": "={{ $json.callIntelligence.sentiment }}"
}
]
}
},
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json, null, 2) }}"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "f6a430f0-fefe-48f4-9d69-a2dcfa640fab",
"connections": {
"GPT-4 Model": {
"ai_languageModel": [
[
{
"node": "GPT-4 Call Intelligence Analysis",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Log Call Activity in CRM": {
"main": [
[
{
"node": "Write to Call Analytics Audit Log",
"type": "main",
"index": 0
}
]
]
},
"Fetch Audio File from URL": {
"main": [
[
{
"node": "Transcribe Audio with OpenAI Whisper",
"type": "main",
"index": 0
}
]
]
},
"Fetch CRM Contact History": {
"main": [
[
{
"node": "GPT-4 Call Intelligence Analysis",
"type": "main",
"index": 0
}
]
]
},
"Update CRM Contact and Deal": {
"main": [
[
{
"node": "Send Call Intelligence Summary to Sales Team",
"type": "main",
"index": 0
}
]
]
},
"Receive Call Recording Upload": {
"main": [
[
{
"node": "Validate Call Metadata and Audio",
"type": "main",
"index": 0
}
]
]
},
"Parse and Structure Transcript": {
"main": [
[
{
"node": "Fetch CRM Contact History",
"type": "main",
"index": 0
}
]
]
},
"Build Final Processing Response": {
"main": [
[
{
"node": "Return Processing Confirmation",
"type": "main",
"index": 0
}
]
]
},
"Parse GPT-4 Intelligence Output": {
"main": [
[
{
"node": "Update CRM Contact and Deal",
"type": "main",
"index": 0
},
{
"node": "Log Call Activity in CRM",
"type": "main",
"index": 0
}
]
]
},
"GPT-4 Call Intelligence Analysis": {
"main": [
[
{
"node": "Parse GPT-4 Intelligence Output",
"type": "main",
"index": 0
}
]
]
},
"Validate Call Metadata and Audio": {
"main": [
[
{
"node": "Fetch Audio File from URL",
"type": "main",
"index": 0
}
]
]
},
"Write to Call Analytics Audit Log": {
"main": [
[
{
"node": "Build Final Processing Response",
"type": "main",
"index": 0
}
]
]
},
"Transcribe Audio with OpenAI Whisper": {
"main": [
[
{
"node": "Wait \u2014 Transcription Buffer (15 sec)",
"type": "main",
"index": 0
}
]
]
},
"Wait \u2014 Transcription Buffer (15 sec)": {
"main": [
[
{
"node": "Parse and Structure Transcript",
"type": "main",
"index": 0
}
]
]
},
"Send Call Intelligence Summary to Sales Team": {
"main": [
[
{
"node": "Build Final Processing Response",
"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.
googleSheetsOAuth2ApihubspotApiopenAiApismtp
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Converts raw sales call recordings into structured CRM intelligence. Uploads audio → transcribes via Whisper → GPT-4 extracts intent, sentiment, objections, next steps → updates CRM and sends a structured summary to the sales team. Upload Call Recording - Webhook receives audio…
Source: https://n8n.io/workflows/13593/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This n8n workflow orchestrates a powerful suite of AI Agents and automations to manage and optimize various aspects of an e-commerce operation, particularly for platforms like Shopify. It leverages La
This n8n workflow automates real-time phishing detection by ingesting incoming emails, extracting indicators, analyzing content with AI (GPT-4), calculating risk scores, and taking immediate action—qu
Law firms in corporate, litigation, or family law needing streamlined case and contract management.
Automates fraud risk detection for financial transactions by analyzing real-time webhook events through AI-powered scoring. Target audience: fintech companies, payment processors, and banking teams pr
K&S-Media Downloadliste SQL. Uses httpRequest, agent, googleSheets, lmChatOpenAi. Event-driven trigger; 97 nodes.