AI Voice7 min read30 April 2026

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.

H

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:

  1. Receive VAPI webhook with full transcript
  2. Pass transcript to OpenAI API with extraction prompt
  3. Parse JSON response
  4. 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.

H

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.

ShareShare on X →