Extracting Structured Data from VAPI Call Transcripts
Every AI call produces a transcript. Here's how to extract structured fields (budget, timeline, objections, intent) and push them to your CRM automatically.
Haroon Mohamed
AI Automation & Lead Generation
Why extraction matters
VAPI calls produce a goldmine of conversational data:
- Budget mentioned by prospect
- Timeline for purchase
- Pain points expressed
- Decision makers named
- Specific objections raised
- Sentiment / engagement level
If this data stays as a text transcript, it's useless. If you extract it into structured fields and push to your CRM, every call becomes lead intelligence.
Here's how to build the extraction pipeline.
What VAPI gives you
After every call, VAPI fires an end-of-call-report webhook with:
- Transcript: full text of the conversation, timestamped
- Summary: AI-generated brief of the call
- Recording URL: audio file
- Analysis: structured fields if configured (this is the key)
You can also configure VAPI's analysisPlan to extract specific fields automatically using a separate LLM call.
Approach 1: VAPI's built-in analysisPlan
In your assistant config:
{
"analysisPlan": {
"summaryPrompt": "Summarize this call in 2-3 sentences focusing on the prospect's interest, qualification, and next steps.",
"structuredDataPrompt": "Extract the following from the conversation:",
"structuredDataSchema": {
"type": "object",
"properties": {
"interested": {"type": "boolean", "description": "Is the prospect interested in the product?"},
"homeowner": {"type": "boolean", "description": "Does the prospect own their home?"},
"budget_range": {"type": "string", "description": "Mentioned budget range, e.g., 'under $10k', '$10-25k', etc."},
"timeline": {"type": "string", "description": "When are they looking to buy? e.g., 'this month', '3-6 months', 'this year', 'no timeline'"},
"key_objection": {"type": "string", "description": "The main objection raised, if any"},
"decision_maker": {"type": "boolean", "description": "Is this person the decision maker?"},
"appointment_set": {"type": "boolean", "description": "Did they agree to an appointment?"}
}
},
"successEvaluationPrompt": "Evaluate if the call achieved its goal of qualifying the prospect and either booking an appointment or determining unfit."
}
}
VAPI will run a second LLM call after the conversation ends to extract these fields. They appear in the webhook payload.
Cost: ~$0.005-$0.02 per extraction (one extra LLM call).
Approach 2: Custom extraction in Make.com
If you need more control:
- Receive VAPI webhook with full transcript
- Pass transcript to OpenAI API with extraction prompt
- Parse JSON response
- Update CRM
Example OpenAI call:
POST https://api.openai.com/v1/chat/completions
{
"model": "gpt-4o-mini",
"messages": [
{"role": "system", "content": "Extract structured data from sales call transcripts. Return only valid JSON matching the schema."},
{"role": "user", "content": "Transcript:\n\n[transcript here]\n\nReturn JSON with: interested (bool), homeowner (bool), budget_range (string), timeline (string), key_objection (string), decision_maker (bool), appointment_set (bool)"}
],
"response_format": {"type": "json_object"}
}
The response_format flag forces JSON output, which is easier to parse than freeform text.
Approach 3: Function calling within the call
Instead of post-call extraction, use VAPI's function calling to extract data live:
{
"name": "log_qualification",
"description": "Log the prospect's qualification info as it's discovered",
"parameters": {
"type": "object",
"properties": {
"field": {"type": "string", "enum": ["budget", "timeline", "homeowner", "decision_maker"]},
"value": {"type": "string"}
}
}
}
The AI calls this function whenever it learns a piece of info. Your webhook handler logs each piece in real-time.
Pro: real-time data, can adjust call flow based on what's been captured.
Con: more complex prompt design, requires careful instruction to AI on when to call the function.
Schema design principles
Use specific enum values, not freeform
Bad:
{"timeline": "string"}
Result: "soon", "in a few months", "Q2 2026", "asap" — unanalyzable.
Better:
{"timeline": {"type": "string", "enum": ["immediate", "1_to_3_months", "3_to_6_months", "6_to_12_months", "12_plus_months", "no_timeline"]}}
Result: standardized values for filtering.
Numerical when possible
Convert "$200/month electric bill" to a number field:
{"electric_bill_monthly": {"type": "number"}}
Categorical with examples
For sentiment or objections, use limited categories:
{"primary_objection": {"type": "string", "enum": ["price", "timing", "trust", "spouse_decision", "evaluating_competitors", "no_objection"]}}
Boolean for decisions
Don't extract "they seemed interested" as text. Extract interested: true/false.
Pushing to CRM
Once extracted, fields flow to GHL/HubSpot custom fields.
GoHighLevel custom fields
Create custom fields matching your schema:
call_outcome(text)is_homeowner(boolean)budget_range(dropdown)timeline(dropdown)electric_bill_monthly(number)primary_objection(dropdown)
In Make.com, after extraction, call GHL API to update contact custom fields.
HubSpot
Same pattern, custom properties on the contact object.
Triggering downstream workflows
Extracted data drives the next steps:
If qualified + appointment set
- Move opportunity to "Appointment Booked" stage
- Send confirmation email
- Pre-meeting reminder sequence
If qualified + no appointment
- Move opportunity to "Hot Lead - Manual Follow-up"
- Notify sales rep with extracted context
- Add to high-priority list
If unqualified
- Tag contact with reason ("not-homeowner", "budget-too-low")
- Move to "Disqualified" stage
- Optionally: enroll in long-term nurture sequence
If specific objection
- Tag with objection type
- Trigger objection-specific email sequence (e.g., "How to finance a solar system" for price objections)
Quality assurance
1. Sample audit weekly
Manually review 20 random call transcripts vs. extracted fields. Are they accurate? Where does extraction fail?
2. Track extraction accuracy
For each field, measure: of extracted values, what % match what a human reviewer would mark?
Target: 90%+ accuracy on simple fields (homeowner, appointment_set), 75%+ on complex fields (primary_objection, sentiment).
3. Iterate prompts
If extraction is inaccurate, refine the prompt:
- Add more examples
- Clarify enum definitions
- Add explicit instructions for ambiguous cases
4. Confidence scoring
Add a confidence field. If LLM is uncertain about extraction, flag for human review:
{
"extracted_fields": {...},
"confidence_score": 0.85,
"needs_review": false
}
If confidence < 0.7, set needs_review: true and surface to sales rep.
Cost considerations
For 1,000 calls/day:
- VAPI built-in extraction: ~$10-$20/day
- Custom GPT-4o-mini extraction: ~$5-$10/day
- Custom GPT-4o extraction: ~$50-$100/day
GPT-4o-mini is usually accurate enough for extraction tasks. Save GPT-4o for the actual conversation, not post-processing.
Real example: solar lead qualification
Schema:
{
"interested": "bool",
"homeowner": "bool",
"roof_condition": "enum: good|fair|poor|unknown",
"electric_bill_monthly": "number",
"credit_score_range": "enum: excellent|good|fair|poor|unknown",
"ready_to_install": "enum: ready|exploring|not_ready",
"primary_concern": "enum: price|aesthetics|reliability|none",
"appointment_set": "bool",
"spouse_decision_required": "bool"
}
After 100 calls:
- 35 with
interested: true, homeowner: true, ready_to_install: ready→ highest priority - 25 with
interested: true, ready_to_install: exploring→ nurture sequence - 20 with
homeowner: false→ disqualified - 10 with
spouse_decision_required: true→ reschedule for combined call
Lead routing now driven by structured data, not manual review.
Common pitfalls
1. Over-engineering the schema
50 extracted fields = AI accuracy degrades. Keep schema focused on what drives action.
2. Trusting extraction blindly
LLM extraction is 85-95% accurate, not 100%. Build in human review for high-stakes decisions.
3. Not feeding extracted data to next call
If a prospect is called again, the AI should know what was already discussed. Pass extracted data as context to the next call.
4. No version control on extraction prompt
Updates to the extraction prompt change all future data. Track prompt changes alongside CRM data updates.
5. Mixing call summary with extraction
Asking one LLM call to "summarize and extract structured data" produces worse results than two separate calls (summary, then structured extraction).
Sources
VAPI documentation from vapi.ai/docs (analysisPlan, structured data extraction). OpenAI API docs from platform.openai.com/docs (response_format, JSON mode). Pricing from each platform's pricing pages as of April 2026. Extraction accuracy benchmarks based on typical small-to-mid-size deployment outcomes.
Want help designing extraction schemas and pipelines for your AI calling stack? Let's talk — typical setup is 1 week.
Need This Built?
Ready to implement this for your business?
Everything in this article reflects real systems I've built and operated. Let's talk about yours.
Haroon Mohamed
Full-stack automation, AI, and lead generation specialist. 2+ years running 13+ concurrent client campaigns using GoHighLevel, multiple AI voice providers, Zapier, APIs, and custom data pipelines. Founder of HMX Zone.
Related articles
How to Train Your AI Caller for a Specific Vertical: Solar, Real Estate, HVAC
Most AI calling deployments start with a generic prompt: "qualify this lead and book an appointment." Generic prompts produce generic conversations. They miss: - Industry-specific qualifications - Co…
AI Voice for Real Estate Lead Follow-Up: What Works in the First 5 Minutes
National Association of Realtors data is clear: ~50% of buyers and sellers go with the first agent who responds. Most real estate teams call leads within 10-30 minutes. By then, the lead has already …