Build an AI Voice Receptionist

Build a 24/7 AI voice receptionist that handles commercial property inquiries.

Introduction

30 Second Summary

Think about what happens when a potential customer calls a business after hours. They get voicemail, hang up, and call a competitor instead.

In this project, you will build an AI voice receptionist for a commercial property management company that answers calls 24/7, provides accurate property information, qualifies prospective tenants, and captures lead data automatically.

What You'll Build

A fully functional AI voice receptionist powered by Vapi AI that handles commercial property inquiries, calculates rental costs, and qualifies prospective tenants over the phone.

By the end of this project, you'll have:

  • A configured voice assistant with a comprehensive system prompt containing all company data, property listings, pricing, and conversation rules.
  • Two function tools and a structured output schema that automatically extracts 7 fields from every prospective tenant call.
  • A professional landing page with an embedded voice widget and a real Edmonton-area phone number routing inbound calls to your agent via Twilio.
  • Secret Mission: Write a 50-word pitch to a real commercial property management company quantifying the cost of their missed after-hours calls using real Edmonton market data.

Are there any prerequisites?

None. This project includes full setup instructions for every tool you need. You do not need any prior experience with voice AI, telephony, or commercial real estate.

Before We Start

Before We Start...

Set Up Your Accounts and Tools

Before building your AI voice receptionist, you need two things in place: a Vapi account to host and run your voice agent, and a code editor to build the landing page.

Vapi is the platform where you configure the agent's brain, voice, and phone connectivity. VS Code is the code editor where you will write the HTML landing page that embeds your voice widget.

In this step, get ready to:
  • Create a Vapi account and locate your API key.
  • Install VS Code and create your project folder.
  • Verify your setup is working.
Create your Vapi account

Vapi is the voice AI platform that hosts your assistant, manages conversation flows, and handles telephony connections. You need an account to configure your receptionist.

  • Open your browser and go to dashboard.vapi.ai.
  • Click Sign Up and create your account using Google, GitHub, or email.
  • After signing up, you land on the Vapi Dashboard overview page.

What about the free credits?

New Vapi accounts receive $10 in signup credits. At the base Vapi rate of $0.05/min (plus model provider costs), this gives you roughly 80-130 minutes of call time. That is more than enough for this project.

  • Locate your API key by clicking your profile icon in the top right corner of the dashboard.
  • Select Vapi API Keys from the dropdown menu.
  • Find your Public API Key and click the copy icon next to it.
  • Save this key somewhere safe, such as a text file or notes app on your computer.

Why save the key separately?

You will paste this Public API Key into your landing page code later. Keeping it in a notes file makes it easy to retrieve without navigating back to the dashboard each time.

Signup page not loading?

If the signup page freezes or buttons do not respond, try a different browser (Chrome works best). You can also try signing up with a different method (Google instead of email, or vice versa).

Help me troubleshoot my Vapi signup issue.

Install VS Code and create your project folder

You need a code editor to write the HTML landing page for your voice receptionist. VS Code is free, works on all platforms, and has features like syntax highlighting that make writing HTML easier.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Visual Studio Code and press Enter.

✔️ VS Code opens

VS Code is already installed. You are ready to create your project folder.

ⓧ Nothing happens or app not found

You need to install VS Code first.

  • Open your browser and go to code.visualstudio.com.
  • Click the download button for your operating system (macOS or Windows).
  • Run the installer and follow the prompts to complete installation.
  • Once installed, press Cmd+Space (macOS) or the Windows key (Windows), type Visual Studio Code, and press Enter to open it.

Now create your project folder. You will use VS Code's built-in terminal for this.

  • In VS Code, open the terminal by pressing Ctrl+` (backtick key, usually above Tab) on both macOS and Windows.
  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir apex-receptionist
cd apex-receptionist
  • Open this folder in VS Code by clicking File in the top menu bar.
  • Click Open Folder.
  • Navigate to your Desktop, select the apex-receptionist folder, and click Open.

VS Code reloads with the apex-receptionist folder shown in the Explorer sidebar on the left.

Don't see the terminal?

If the keyboard shortcut does not work, click Terminal in the top menu bar and select New Terminal.

Help me open the terminal in VS Code.

Verify your setup
  • Switch back to your browser and confirm you can see the Vapi Dashboard overview page.
  • Confirm your Public API Key is saved in your notes file.
  • In VS Code, confirm the Explorer sidebar shows the apex-receptionist folder name at the top.

How much testing can you do with $10?

Your $10 in credits provides approximately 200 minutes of call time at the base Vapi rate of $0.05/min. In practice, model provider costs bring the total to roughly $0.07-0.12/min per call, so you have around 80-130 minutes of real testing available. This is plenty for building and testing your receptionist.

Your accounts are ready and your project folder is waiting. Next up, you will create and configure the AI voice assistant inside the Vapi Dashboard.

Create and Configure the Voice Assistant

Your accounts are ready and your development workspace is set up. Now it's time to create the AI agent that will actually answer calls for Apex Property Group.

A voice assistant needs three things to sound professional: a clear greeting, a capable language model behind it, and a natural-sounding voice. You'll configure all three in the Vapi dashboard.

In this step, get ready to:
  • Create a new voice assistant from a blank template.
  • Configure the greeting message, language model, and voice.
  • Publish and verify the assistant responds correctly.
Create the Apex Reception assistant

Every Vapi assistant starts from a template. A blank template gives you full control over the greeting, model, and behavior from scratch.

  • In the Vapi Dashboard, click Assistants in the left sidebar.
  • Click Create Assistant.
  • Select Blank Template as your starting point.
  • Change the assistant name to Apex Reception.

Why a blank template?

Vapi offers pre-built templates for common use cases, but a blank template lets you define every aspect of your receptionist's personality and knowledge. For a commercial property company, you need precise control over what the agent says and how it handles inquiries.

Configure the first message, model, and voice

The first message is what callers hear immediately when the assistant picks up. The model determines how intelligently the assistant responds. The voice determines how it sounds.

  • In the assistant configuration, find the First Message field.
  • Set the First Message to:
Thank you for calling Apex Property Group. I'm the virtual receptionist. How can I help you today?
  • In the Model section, select OpenAI as the provider and gpt-4o as the model.
  • In the Voice section, select OpenAI as the provider and choose a professional-sounding voice such as alloy or onyx.

What do these settings do?

The First Message plays as soon as the assistant connects to a caller. It sets the professional tone for every interaction.

GPT-4o is OpenAI's latest multimodal model. It handles nuanced conversation well, which matters when a prospective tenant asks complex questions about lease terms or CAM charges.

The alloy voice is neutral and calm. The onyx voice is deeper and more authoritative. Either works well for a corporate receptionist.

Publish and verify the assistant responds

Publishing saves your configuration and makes the assistant available for testing. You can test it directly from the dashboard before adding the full system prompt.

  • Click Publish to save the assistant.
  • Click Talk to Assistant in the top right corner to start a test conversation.
  • Verify the assistant responds with your greeting: "Thank you for calling Apex Property Group. I'm the virtual receptionist. How can I help you today?"
  • End the test call once you confirm the greeting plays correctly.

Where is your assistant ID?

After publishing, copy your Assistant ID from the URL or assistant details. You will need this ID later when embedding the voice widget on your landing page. Save it alongside your Public API Key.

Not hearing the greeting?

Make sure you clicked Publish before clicking Talk to Assistant. Unpublished changes will not be reflected in the test.

Check that your browser has microphone permissions enabled. Vapi needs microphone access for the two-way voice conversation to work.

If you hear nothing at all, try a different browser (Chrome is recommended) or check that your device audio output is not muted.

Why isn't my Vapi assistant responding with the greeting when I click Talk to Assistant?

Your assistant is live and responding with the Apex Property Group greeting. Next up, you'll write the full system prompt that gives the agent all of its company knowledge, listing data, and conversation rules.

Write the System Prompt

Your assistant can respond with a greeting, but it has no company knowledge yet. Right now, if someone asks about available office space or lease terms, it has nothing to draw on.

The system prompt is the entire knowledge base for your voice agent. Because this project uses no backend server, everything the agent knows must live directly in the prompt. In this step, you will write a comprehensive system prompt containing all company data, property listings, and conversation rules.

In this step, get ready to:
  • Add the full Apex Property Group system prompt to your assistant.
  • Verify the conversation rules that control agent behavior.
  • Test that the assistant responds with company-specific knowledge.
Add the system prompt to your assistant

The system prompt defines who the agent is, what it knows, and how it behaves. For a voice receptionist with no backend, the prompt must contain every piece of information the agent could ever need.

  • In the Vapi Dashboard, click Assistants in the left sidebar.
  • Select your Apex Reception assistant.
  • Scroll to the Model section.
  • Locate the System Prompt field and paste the following prompt:
You are the virtual receptionist for Apex Property Group Inc., a commercial property management company located at 10235 101 St NW, Suite 310, Edmonton, Alberta.

## Company Information
- Company: Apex Property Group Inc.
- Phone: (780) 555-0247
- Email: info@apexpropertygroup.ca
- Office Hours: Monday to Friday, 8:00am to 4:30pm MST
- Established: 2007
- Specialization: Office, retail, and industrial commercial spaces across Edmonton

## Available Commercial Spaces

### 1. The Stratford - Office
- Address: 10180 101 St NW, Unit 204
- Size: 980 sqft
- Base Rent: $22.00/sf/yr ($21,560/yr or approximately $1,797/month)
- CAM Charges: $8.50/sf/yr
- Total Occupancy Cost: $30.50/sf/yr ($29,890/yr or approximately $2,491/month)
- Features: Corner unit, floor-to-ceiling windows, shared boardroom, underground parking available
- Availability: Immediate

### 2. Meridian Tower - Office
- Address: 10025 Jasper Ave, Suite 510
- Size: 1,450 sqft
- Base Rent: $26.00/sf/yr ($37,700/yr or approximately $3,142/month)
- CAM Charges: $9.25/sf/yr
- Total Occupancy Cost: $35.25/sf/yr ($51,113/yr or approximately $4,259/month)
- Features: Recently renovated, open floor plan, fiber internet, on-site security
- Availability: July 1, 2026

### 3. Gateway Plaza - Retail
- Address: 4821 Calgary Trail NW, Unit 12
- Size: 1,100 sqft
- Base Rent: $28.00/sf/yr ($30,800/yr or approximately $2,567/month)
- CAM Charges: $11.00/sf/yr
- Total Occupancy Cost: $39.00/sf/yr ($42,900/yr or approximately $3,575/month)
- Features: Street-level entrance, high foot traffic, dedicated signage, shared loading dock
- Availability: Immediate

### 4. Northgate Business Park - Retail
- Address: 13712 St Albert Trail, Unit 8
- Size: 2,200 sqft
- Base Rent: $16.00/sf/yr ($35,200/yr or approximately $2,933/month)
- CAM Charges: $6.50/sf/yr
- Total Occupancy Cost: $22.50/sf/yr ($49,500/yr or approximately $4,125/month)
- Features: End cap unit, drive-up access, 15 dedicated parking stalls, recently paved lot
- Availability: September 1, 2026

### 5. Westside Industrial Centre - Industrial
- Address: 18035 111 Ave NW, Bay 3
- Size: 3,800 sqft
- Base Rent: $12.00/sf/yr ($45,600/yr or approximately $3,800/month)
- CAM Charges: $4.25/sf/yr
- Total Occupancy Cost: $16.25/sf/yr ($61,750/yr or approximately $5,146/month)
- Features: 16ft clear ceiling height, drive-in bay door, 600V power, fenced yard access
- Availability: Immediate

## Lease Terms
- Standard lease term: 3 to 5 years
- Lease type: NNN (Triple Net) - tenant pays base rent plus their proportional share of property taxes, insurance, and common area maintenance (CAM)
- Security deposit: First and last month's base rent
- Rent escalation: 2.5% annual increase
- Tenant improvements: Negotiable on leases of 3+ years

## CAM Charges Explained
CAM (Common Area Maintenance) charges cover the shared costs of operating the property, including:
- Snow removal and landscaping
- Shared hallway and lobby cleaning
- Parking lot maintenance and lighting
- Building exterior maintenance
- Property management fees
- Shared utility costs for common areas

CAM charges are estimated annually and reconciled at year-end. The amounts listed are current estimates and may vary slightly.

## Utilities
- Electricity: Tenant responsibility, metered separately for each unit
- Natural gas (heating): Tenant responsibility in industrial units; included in CAM for office and retail
- Water/sewer: Included in CAM charges
- Internet/phone: Tenant responsibility, multiple providers available in all buildings

## Maintenance Policies
- Emergency maintenance: Call (780) 555-0247 (24/7 emergency line)
- Non-emergency requests: Submit through the tenant portal at tenants.apexpropertygroup.ca
- Response times: Emergency within 2 hours, urgent within 24 hours, routine within 5 business days
- Building systems (HVAC, elevators, plumbing mains): Landlord responsibility
- Interior unit maintenance: Tenant responsibility unless covered by lease terms

## Conversation Rules
1. Keep all responses under 2 sentences. Be concise and professional.
2. Always confirm details back to the caller before ending the conversation.
3. Never fabricate information. Only provide details explicitly listed in this prompt. If you do not have the answer, say so clearly.
4. Always capture prospective tenant details: caller name, company name, callback number, space type interest, approximate size needed, and move-in timeline.
5. If asked about properties or locations not listed above, respond with: "I don't have details on that location in our current portfolio. I'd be happy to take your contact information and have our leasing team reach out with options that might fit your needs."
6. For current tenants reporting maintenance issues, direct them to the tenant portal at tenants.apexpropertygroup.ca or advise them to call back during office hours (Monday to Friday, 8:00am to 4:30pm MST) to speak with the property management team.
7. If asked to schedule a tour, confirm the property of interest and collect the caller's name, company, and callback number. Let them know a leasing agent will contact them within one business day to arrange the tour.
8. When calculating costs, always clarify that you are providing the base rent and that total occupancy cost includes CAM charges on top of base rent.

What does this system prompt do?

The system prompt has six sections that give the agent everything it needs:

  • Company Information establishes the agent's identity and contact details.
  • Available Commercial Spaces provides 5 real listings with pricing, sizes, and features the agent can quote.
  • Lease Terms and CAM Charges let the agent explain how commercial rents work.
  • Utilities and Maintenance Policies cover operational questions from both prospective and current tenants.
  • Conversation Rules control the agent's behavior to keep it concise, honest, and consistent.

Why no backend server?

With a backend server, the agent could query a database for listing data. Without one, the system prompt IS the database. This means the agent can only ever know what you put in the prompt.

The tradeoff is simplicity. You get a working voice agent in minutes with no infrastructure to manage. The limitation is that updating listings requires editing the prompt directly.

Review the conversation rules

The conversation rules section at the bottom of the prompt is what separates a useful agent from an unreliable one. Each rule prevents a specific failure mode.

  • Scroll to the bottom of the system prompt you just pasted and read through the 8 conversation rules.
  • Verify that rule 3 says "Never fabricate information" to prevent hallucination.
  • Verify that rule 4 lists the 6 details to capture: caller name, company name, callback number, space type interest, approximate size needed, and move-in timeline.
  • Verify that rule 5 contains the exact redirect language for unlisted properties.

Why these specific rules matter

Rule 1 (under 2 sentences) keeps the agent from rambling. Voice conversations feel unnatural when one side delivers a monologue.

Rule 3 (never fabricate) is the most critical guardrail. Without it, the model will confidently invent listings, prices, or lease terms that do not exist.

Rule 5 (redirect language) gives the agent an exact script for situations it cannot handle. This ensures every caller still gets a professional response, even when the answer is "I don't know."

Publish and test with company-specific questions
  • Click Publish to save your updated assistant.
  • Click Talk to Assistant in the top right corner.
  • Ask: "Do you have any office space available under 1,500 square feet?"
  • Verify the agent mentions The Stratford (980 sqft at $22.00/sf/yr).
  • Ask a follow-up: "What are CAM charges?"
  • Verify the agent explains Common Area Maintenance fees using the details from your prompt.

Agent not referencing company data?

Make sure you clicked Publish after pasting the system prompt. Changes do not take effect until you publish.

If the agent gives generic responses, check that the prompt text is in the System Prompt field inside the Model section, not in the First Message field.

help me troubleshoot why my Vapi assistant is not using the system prompt data in its responses

Your agent now has a complete knowledge base covering 5 commercial spaces, pricing, lease terms, and strict conversation rules. Next up, you will add function tools that give the agent structured ways to check availability and capture lead data.

Add Function Tools

Your Apex Reception assistant now has a comprehensive system prompt full of company knowledge. The agent can answer questions, but it has no structured way to organize its responses into repeatable patterns.

Function tools solve this by acting as structured triggers that signal the agent to perform specific conversation flows. In this step, you'll create two tools: one that guides the agent through listing available spaces, and another that captures prospective tenant lead information into a consistent format.

In this step, get ready to:
  • Create the check_availability function tool.
  • Create the capture_lead function tool.
  • Publish and understand the expected "no backend" behavior.
Create the check_availability tool

The first tool tells the agent when a caller is asking about available spaces. When triggered, the agent follows a consistent pattern to list matching properties from the system prompt.

  • In the Vapi Dashboard, click Tools in the left sidebar.
  • Click Create Tool.
  • Select Function as your tool type.
  • Change the tool name to check_availability.
  • In the description field, enter:
Checks available commercial spaces by type (office, retail, or industrial) and returns matching listings from the portfolio.
  • Scroll down to the Parameters section.
  • Add one parameter with the name space_type, type string, and mark it as required.
  • Leave the Server URL field empty. Do not configure a backend server.

Why no Server URL?

Normally, function tools call an external server to fetch real data. In this project, the agent's system prompt already contains all the property data it needs.

The tools act as structured conversation triggers that signal the agent to perform specific response patterns, not as API integrations. This means no backend code is required.

  • Confirm your tool configuration matches: name check_availability, one parameter space_type (string, required), no server URL.
Create the capture_lead tool

The second tool structures the lead capture conversation. When a caller expresses interest in a space, the agent uses this tool's parameters as a checklist of information to collect.

  • Return to Tools in the left sidebar.
  • Click Create Tool again.
  • Select Function as your tool type.
  • Change the tool name to capture_lead.
  • In the description field, enter:
Captures prospective tenant contact information and space requirements for the leasing team to follow up.
  • Scroll down to the Parameters section and add the following 7 parameters:
  • caller_name (type: string).
  • company_name (type: string).
  • callback_number (type: string).
  • space_type (type: string).
  • approximate_size_sqft (type: string).
  • move_in_timeline (type: string).
  • tour_requested (type: boolean).
  • Leave the Server URL field empty, just like the first tool.

What do these parameters represent?

Each parameter maps to a piece of information the leasing team needs for follow-up. The agent treats these as a conversational checklist, asking the caller for each detail naturally during the call.

Using string types for fields like callback_number and approximate_size_sqft gives the agent flexibility to accept varied formats like "about 2000 square feet" or "780-555-1234" without strict validation errors.

Attach the tools and publish

Both tools are created, but they need to be connected to your Apex Reception assistant before the agent can use them.

  • Click Assistants in the left sidebar.
  • Select Apex Reception from your list of assistants.
  • Scroll down to the Tools section and expand it.
  • Click Add Tool and select check_availability from the dropdown.
  • Click Add Tool again and select capture_lead from the dropdown.
  • Click Publish to save your changes.
  • Verify both tools appear in the Tools section of your Apex Reception assistant.

What about the "No result returned" message?

When you test the assistant and trigger a tool, you will see "No result returned" in the call response details within Call Logs. This is expected.

Because no backend server is configured, the tools cannot return data. The agent uses its system prompt as the knowledge base instead. The tools serve purely as structured triggers that signal the agent to perform specific conversation patterns.

Don't see your tools in the dropdown?

Make sure you created the tools from the Tools section in the left sidebar, not from within the assistant's configuration. Tools created in the global Tools section are available to attach to any assistant.

If you still don't see them, refresh the page and try expanding the Tools section again.

help me troubleshoot why my tools aren't showing up in the Vapi assistant dropdown

Your assistant now has structured tools guiding its conversation flows. Next up, you'll build a professional landing page and embed the Vapi voice widget so visitors can talk to Apex Reception directly from their browser.

Deploy the Voice Widget on a Landing Page

Your Apex Reception assistant is configured with a full system prompt and two function tools. Now it needs a home on the web.

In this step, you will build a professional landing page for Apex Property Group and embed the Vapi voice widget directly into it. When visitors land on the page, they can click a floating voice button to start a live conversation with your AI receptionist.

In this step, get ready to:
  • Build a complete landing page with company branding, contact info, and portfolio details.
  • Embed the Vapi voice widget using the script tag method.
  • Test the full voice conversation flow in your browser.
Create the landing page HTML file

A professional-looking landing page gives your AI receptionist credibility. It shows prospective clients that your solution looks like a real business tool, not a tech experiment.

  • Switch back to VS Code with your apex-receptionist folder open.
  • Create a new file by pressing Cmd+N (macOS) or Ctrl+N (Windows).
  • Save it immediately as index.html by pressing Cmd+S (macOS) or Ctrl+S (Windows).
  • Make sure you save it inside the apex-receptionist folder.
  • Paste the following code into index.html to build the landing page structure, styling, and content:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Apex Property Group Inc. | Edmonton's Commercial Property Experts</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, sans-serif;
            color: #1a1a2e;
            line-height: 1.6;
            background-color: #f8f9fa;
        }

        .header {
            background-color: #1a1a2e;
            color: #ffffff;
            padding: 20px 40px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .logo {
            font-size: 24px;
            font-weight: 700;
            letter-spacing: 1px;
        }

        .logo span {
            color: #c9a94e;
        }

        .nav-contact {
            font-size: 14px;
            text-align: right;
        }

        .nav-contact a {
            color: #c9a94e;
            text-decoration: none;
        }

        .hero {
            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
            color: #ffffff;
            padding: 80px 40px;
            text-align: center;
        }

        .hero h1 {
            font-size: 48px;
            margin-bottom: 16px;
            font-weight: 700;
        }

        .hero .tagline {
            font-size: 22px;
            color: #c9a94e;
            margin-bottom: 24px;
            font-weight: 500;
        }

        .hero .description {
            font-size: 18px;
            max-width: 700px;
            margin: 0 auto 40px;
            color: #b8c4d4;
            line-height: 1.8;
        }

        .cta-section {
            background-color: #ffffff;
            border: 2px solid #c9a94e;
            border-radius: 12px;
            padding: 32px;
            max-width: 500px;
            margin: 0 auto;
        }

        .cta-section h2 {
            font-size: 20px;
            margin-bottom: 12px;
            color: #1a1a2e;
        }

        .cta-section p {
            font-size: 16px;
            color: #555;
            margin-bottom: 20px;
        }

        .cta-section .voice-prompt {
            background-color: #f0f7f0;
            border-left: 4px solid #28a745;
            padding: 12px 16px;
            border-radius: 4px;
            font-size: 14px;
            color: #2d5a2d;
        }

        .info-section {
            padding: 60px 40px;
            max-width: 900px;
            margin: 0 auto;
        }

        .info-grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 40px;
        }

        .info-card {
            background: #ffffff;
            border-radius: 8px;
            padding: 32px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
        }

        .info-card h3 {
            font-size: 18px;
            margin-bottom: 16px;
            color: #1a1a2e;
        }

        .info-card p, .info-card li {
            font-size: 15px;
            color: #555;
        }

        .info-card ul {
            list-style: none;
            padding: 0;
        }

        .info-card ul li {
            padding: 8px 0;
            border-bottom: 1px solid #eee;
        }

        .info-card ul li:last-child {
            border-bottom: none;
        }

        .footer {
            background-color: #1a1a2e;
            color: #b8c4d4;
            padding: 40px;
            text-align: center;
        }

        .footer .contact-info {
            font-size: 16px;
            margin-bottom: 12px;
        }

        .footer .contact-info a {
            color: #c9a94e;
            text-decoration: none;
        }

        .footer .hours {
            font-size: 14px;
            color: #7a8a9e;
        }

        @media (max-width: 768px) {
            .info-grid {
                grid-template-columns: 1fr;
            }

            .hero h1 {
                font-size: 32px;
            }

            .header {
                flex-direction: column;
                gap: 10px;
            }
        }
    </style>
</head>
<body>
    <header class="header">
        <div class="logo"><span>APEX</span> PROPERTY GROUP</div>
        <div class="nav-contact">
            <a href="tel:7805550247">(780) 555-0247</a> | 
            <a href="mailto:info@apexpropertygroup.ca">info@apexpropertygroup.ca</a>
        </div>
    </header>

    <section class="hero">
        <h1>Apex Property Group Inc.</h1>
        <p class="tagline">Edmonton's Commercial Property Experts</p>
        <p class="description">Managing office, retail, and industrial spaces across Edmonton since 2007. Talk to our virtual receptionist 24/7 — ask about available spaces, rates, or book a tour.</p>
        <div class="cta-section">
            <h2>Speak With Our Virtual Receptionist</h2>
            <p>Click the voice button in the bottom-right corner to start a conversation. Available 24 hours a day, 7 days a week.</p>
            <div class="voice-prompt">Ask about available spaces, pricing, CAM charges, lease terms, or request a property tour.</div>
        </div>
    </section>

    <section class="info-section">
        <div class="info-grid">
            <div class="info-card">
                <h3>Our Portfolio</h3>
                <ul>
                    <li>Office spaces from 980 - 1,450 sqft</li>
                    <li>Retail spaces from 1,100 - 2,200 sqft</li>
                    <li>Industrial bays from 3,800 - 6,200 sqft</li>
                    <li>Locations across Edmonton</li>
                </ul>
            </div>
            <div class="info-card">
                <h3>Contact Us</h3>
                <ul>
                    <li>Phone: (780) 555-0247</li>
                    <li>Email: info@apexpropertygroup.ca</li>
                    <li>Address: 10235 101 St NW, Suite 310</li>
                    <li>Hours: Mon-Fri 8:00am - 4:30pm MST</li>
                </ul>
            </div>
        </div>
    </section>

    <footer class="footer">
        <p class="contact-info">
            <a href="tel:7805550247">(780) 555-0247</a> | 
            <a href="mailto:info@apexpropertygroup.ca">info@apexpropertygroup.ca</a>
        </p>
        <p class="hours">Office Hours: Monday - Friday, 8:00am - 4:30pm MST | Closed Weekends</p>
        <p class="hours" style="margin-top: 8px;">&copy; 2007 - 2026 Apex Property Group Inc. All rights reserved.</p>
    </footer>

</body>
</html>

What does this page include?

  • A dark header with the APEX PROPERTY GROUP logo and contact links.
  • A hero section with the company name, tagline, description, and a call-to-action box that tells visitors about the voice button.
  • An info grid showing the portfolio (office, retail, industrial sizes) and contact details including office hours.
  • A footer repeating the phone number, email, and hours.
  • Responsive CSS that adapts the layout for mobile screens.
  • Save index.html with Cmd+S (macOS) or Ctrl+S (Windows).
  • Open the file in your browser by double-clicking index.html in your file explorer, or right-click the file in VS Code and select Open with Live Server if you have the Live Server extension installed.
  • You should see a dark navy page with "Apex Property Group Inc." as the heading, a gold tagline, and two information cards below the hero section.

Page looks broken or unstyled?

  • Make sure you saved the file with the .html extension. If VS Code saved it as a plain text file, the browser will not render it as HTML.
  • Check that all the code was pasted completely. If the page is missing sections, scroll to the bottom of your file and confirm it ends with </html>.
  • help me fix my HTML page layout
Add the Vapi voice widget

The landing page looks professional, but it is static. Adding the Vapi voice widget turns it into an interactive experience where visitors can speak directly to your AI receptionist.

  • In index.html, find the </body> tag near the bottom of the file.
  • Paste the following script section directly above </body> (below the closing </footer> tag):
    <!-- Vapi Voice Widget -->
    <script>
        var vapiInstance = null;
        const assistant = "your-assistant-id-here"; // Replace with your Vapi assistant ID
        const apiKey = "your-public-api-key-here"; // Replace with your Public API Key from Vapi Dashboard

        (function (d, t) {
            var g = document.createElement(t),
                s = d.getElementsByTagName(t)[0];
            g.src = "https://cdn.jsdelivr.net/gh/VapiAI/html-script-tag@latest/dist/assets/index.js";
            g.defer = true;
            g.async = true;
            s.parentNode.insertBefore(g, s);

            g.onload = function () {
                vapiInstance = window.vapiSDK.run({
                    apiKey: apiKey,
                    assistant: assistant,
                    config: {},
                });
            };
        })(document, "script");
    </script>
  • Replace your-assistant-id-here with your actual Vapi assistant ID. You can find this in the Vapi Dashboard by clicking on your Apex Reception assistant. The ID appears in the URL or at the top of the assistant settings page.
  • Replace your-public-api-key-here with the Public API Key you saved earlier from the Vapi Dashboard.

What does this script do?

  • It dynamically creates a <script> element that loads the Vapi SDK from their CDN.
  • Once the SDK loads, window.vapiSDK.run() initializes the widget with your API key and assistant ID.
  • The widget renders a floating voice button in the bottom-right corner of the page. Visitors click it to start a live voice conversation with your Apex Reception assistant.
  • Save index.html.
  • Refresh the page in your browser (or it will auto-refresh if you are using Live Server).
  • You should see a circular voice button appear in the bottom-right corner of the page.

Don't see the voice button?

  • Open your browser's developer console (Cmd+Option+J on macOS or Ctrl+Shift+J on Windows) and check for errors. A red error mentioning the API key means your apiKey value is incorrect.
  • Make sure you replaced both placeholder strings with your actual values. The quotes around the values must remain intact.
  • Confirm your internet connection is active. The widget loads from an external CDN and will not appear offline.
  • help me debug the Vapi voice widget not loading

✔️ Awesome, I've got everything!

Great. Double check you have saved index.html and the voice button is visible in the corner.

ⓧ I'd like to double check the full code

Here is the complete index.html file. Compare it with yours to spot any differences:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Apex Property Group Inc. | Edmonton's Commercial Property Experts</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, sans-serif;
            color: #1a1a2e;
            line-height: 1.6;
            background-color: #f8f9fa;
        }

        .header {
            background-color: #1a1a2e;
            color: #ffffff;
            padding: 20px 40px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .logo {
            font-size: 24px;
            font-weight: 700;
            letter-spacing: 1px;
        }

        .logo span {
            color: #c9a94e;
        }

        .nav-contact {
            font-size: 14px;
            text-align: right;
        }

        .nav-contact a {
            color: #c9a94e;
            text-decoration: none;
        }

        .hero {
            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
            color: #ffffff;
            padding: 80px 40px;
            text-align: center;
        }

        .hero h1 {
            font-size: 48px;
            margin-bottom: 16px;
            font-weight: 700;
        }

        .hero .tagline {
            font-size: 22px;
            color: #c9a94e;
            margin-bottom: 24px;
            font-weight: 500;
        }

        .hero .description {
            font-size: 18px;
            max-width: 700px;
            margin: 0 auto 40px;
            color: #b8c4d4;
            line-height: 1.8;
        }

        .cta-section {
            background-color: #ffffff;
            border: 2px solid #c9a94e;
            border-radius: 12px;
            padding: 32px;
            max-width: 500px;
            margin: 0 auto;
        }

        .cta-section h2 {
            font-size: 20px;
            margin-bottom: 12px;
            color: #1a1a2e;
        }

        .cta-section p {
            font-size: 16px;
            color: #555;
            margin-bottom: 20px;
        }

        .cta-section .voice-prompt {
            background-color: #f0f7f0;
            border-left: 4px solid #28a745;
            padding: 12px 16px;
            border-radius: 4px;
            font-size: 14px;
            color: #2d5a2d;
        }

        .info-section {
            padding: 60px 40px;
            max-width: 900px;
            margin: 0 auto;
        }

        .info-grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 40px;
        }

        .info-card {
            background: #ffffff;
            border-radius: 8px;
            padding: 32px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
        }

        .info-card h3 {
            font-size: 18px;
            margin-bottom: 16px;
            color: #1a1a2e;
        }

        .info-card p, .info-card li {
            font-size: 15px;
            color: #555;
        }

        .info-card ul {
            list-style: none;
            padding: 0;
        }

        .info-card ul li {
            padding: 8px 0;
            border-bottom: 1px solid #eee;
        }

        .info-card ul li:last-child {
            border-bottom: none;
        }

        .footer {
            background-color: #1a1a2e;
            color: #b8c4d4;
            padding: 40px;
            text-align: center;
        }

        .footer .contact-info {
            font-size: 16px;
            margin-bottom: 12px;
        }

        .footer .contact-info a {
            color: #c9a94e;
            text-decoration: none;
        }

        .footer .hours {
            font-size: 14px;
            color: #7a8a9e;
        }

        @media (max-width: 768px) {
            .info-grid {
                grid-template-columns: 1fr;
            }

            .hero h1 {
                font-size: 32px;
            }

            .header {
                flex-direction: column;
                gap: 10px;
            }
        }
    </style>
</head>
<body>
    <header class="header">
        <div class="logo"><span>APEX</span> PROPERTY GROUP</div>
        <div class="nav-contact">
            <a href="tel:7805550247">(780) 555-0247</a> | 
            <a href="mailto:info@apexpropertygroup.ca">info@apexpropertygroup.ca</a>
        </div>
    </header>

    <section class="hero">
        <h1>Apex Property Group Inc.</h1>
        <p class="tagline">Edmonton's Commercial Property Experts</p>
        <p class="description">Managing office, retail, and industrial spaces across Edmonton since 2007. Talk to our virtual receptionist 24/7 — ask about available spaces, rates, or book a tour.</p>
        <div class="cta-section">
            <h2>Speak With Our Virtual Receptionist</h2>
            <p>Click the voice button in the bottom-right corner to start a conversation. Available 24 hours a day, 7 days a week.</p>
            <div class="voice-prompt">Ask about available spaces, pricing, CAM charges, lease terms, or request a property tour.</div>
        </div>
    </section>

    <section class="info-section">
        <div class="info-grid">
            <div class="info-card">
                <h3>Our Portfolio</h3>
                <ul>
                    <li>Office spaces from 980 - 1,450 sqft</li>
                    <li>Retail spaces from 1,100 - 2,200 sqft</li>
                    <li>Industrial bays from 3,800 - 6,200 sqft</li>
                    <li>Locations across Edmonton</li>
                </ul>
            </div>
            <div class="info-card">
                <h3>Contact Us</h3>
                <ul>
                    <li>Phone: (780) 555-0247</li>
                    <li>Email: info@apexpropertygroup.ca</li>
                    <li>Address: 10235 101 St NW, Suite 310</li>
                    <li>Hours: Mon-Fri 8:00am - 4:30pm MST</li>
                </ul>
            </div>
        </div>
    </section>

    <footer class="footer">
        <p class="contact-info">
            <a href="tel:7805550247">(780) 555-0247</a> | 
            <a href="mailto:info@apexpropertygroup.ca">info@apexpropertygroup.ca</a>
        </p>
        <p class="hours">Office Hours: Monday - Friday, 8:00am - 4:30pm MST | Closed Weekends</p>
        <p class="hours" style="margin-top: 8px;">&copy; 2007 - 2026 Apex Property Group Inc. All rights reserved.</p>
    </footer>

    <!-- Vapi Voice Widget -->
    <script>
        var vapiInstance = null;
        const assistant = "your-assistant-id-here"; // Replace with your Vapi assistant ID
        const apiKey = "your-public-api-key-here"; // Replace with your Public API Key from Vapi Dashboard

        (function (d, t) {
            var g = document.createElement(t),
                s = d.getElementsByTagName(t)[0];
            g.src = "https://cdn.jsdelivr.net/gh/VapiAI/html-script-tag@latest/dist/assets/index.js";
            g.defer = true;
            g.async = true;
            s.parentNode.insertBefore(g, s);

            g.onload = function () {
                vapiInstance = window.vapiSDK.run({
                    apiKey: apiKey,
                    assistant: assistant,
                    config: {},
                });
            };
        })(document, "script");
    </script>
</body>
</html>
Test the full voice conversation flow

The widget is live. Now you need to confirm your Apex Reception assistant responds correctly through the page.

  • Click the voice button in the bottom-right corner of the page.
  • Wait for the connection. Your browser may ask for microphone permission. Click Allow to grant access.
  • Listen for the greeting: "Thank you for calling Apex Property Group. I'm the virtual receptionist. How can I help you today?"
  • Ask: "What office space do you have available?"
  • Verify the agent responds with information about available office spaces from the system prompt you configured earlier.
  • End the call by clicking the voice button again.

Why does page design matter?

When pitching this solution to a real property management company, the landing page is your proof of concept. A polished, branded page shows the client exactly what their tenants would experience. It transforms an abstract "AI voice agent" into something tangible they can see and hear.

Agent not responding or giving wrong answers?

  • Check that you replaced your-assistant-id-here with the correct assistant ID from Vapi. An incorrect ID connects you to nothing.
  • Return to the Vapi Dashboard and confirm your Apex Reception assistant is still published. If you made changes without clicking Publish, the widget uses the last published version.
  • If the agent greets correctly but cannot answer questions about spaces, your system prompt may not have saved properly. Return to the assistant configuration and verify the full prompt is present.
  • help me troubleshoot my Vapi voice widget conversation

Your AI receptionist now has a public-facing home. Next up, you will put it through five real-world conversation scenarios to see how it handles everything from pricing questions to edge cases.

Test With Five Real Scenarios

Your voice receptionist is live on a landing page and ready for callers. But how do you know it actually works the way a real prospective tenant would expect?

In this step, you will run five real conversation scenarios that test different aspects of the agent's knowledge, conversation handling, and failure behaviour. These scenarios cover the most common types of calls a commercial property receptionist receives.

In this step, get ready to:
  • Test listing knowledge and price calculations.
  • Test lead capture and off-script handling.
  • Test an edge case where the agent must not fabricate information.
Run Scenario 1 and Scenario 2

The first two scenarios test the agent's core knowledge. Can it accurately reference specific listings and calculate rental costs? Can it explain commercial real estate terminology like CAM charges?

  • Switch back to your landing page in the browser.
  • Click the voice button in the bottom-right corner to start a conversation.
  • For Scenario 1, ask the agent about office space under 1,500 square feet.
  • Verify the agent mentions The Stratford (980 sqft at $22/sf/yr) and calculates approximate monthly costs.
  • End the call by saying goodbye.

What should I hear?

The agent should reference specific listing data from its system prompt. For The Stratford at 980 sqft and $22/sf/yr, the annual base rent is $21,560. Divided by 12, that is approximately $1,797/month before CAM charges.

If the agent gives a vague answer without numbers, or mentions a property not in your system prompt, that is a fail for this scenario.

  • Click the voice button again to start a new conversation for Scenario 2.
  • Ask: "What are CAM charges and what do they include?"
  • Verify the agent explains Common Area Maintenance fees accurately using details from your system prompt.
  • End the call.

What counts as a pass for Scenario 2?

The agent should explain that CAM charges cover shared costs like lobbies, parking areas, snow removal, landscaping, and common utilities. It should reference the specific CAM rates from your system prompt for the property the caller asks about.

Write down whether each scenario passed or failed. Note what the agent said correctly and what it got wrong.

Run Scenario 3 and Scenario 4

These scenarios test the agent's ability to capture lead information and handle conversations that fall outside its primary purpose. A real receptionist needs to gracefully redirect calls that do not match their job description.

  • Click the voice button to start a new conversation for Scenario 3.
  • Tell the agent you would like to book a property tour at The Stratford.
  • When prompted, provide your name, a company name, and a callback number.
  • Verify the agent captures all three pieces of information and confirms them back to you before ending the call.
  • End the call.

What triggers the capture_lead tool?

When the agent recognizes that a caller wants to book a tour or is a prospective tenant, it should trigger the capture_lead function tool. You will see "No result returned" in the call logs because there is no backend server. This is expected. The important thing is that the agent asks for and confirms the caller's details during the conversation.

  • Click the voice button to start a new conversation for Scenario 4.
  • This time, pretend to be a current tenant. Say something like: "Hi, I'm a tenant in Suite 200 and my heating isn't working."
  • Verify the agent directs you to the tenant portal or advises you to call back during office hours (Mon-Fri 8:00am-4:30pm MST).
  • End the call.

Why off-script handling matters

A real receptionist receives all kinds of calls, not just prospective tenant inquiries. The agent's system prompt should include rules for redirecting current tenants to the appropriate channel. If the agent tries to book a tour for a maintenance caller, that is a fail.

Record your pass/fail results for Scenarios 3 and 4.

Run Scenario 5 and document all results

This final scenario is the most important test for any AI agent. It checks whether the agent fabricates information when it does not have the answer. In AI terminology, this is called a hallucination test.

  • Click the voice button to start a new conversation for Scenario 5.
  • Ask the agent about commercial space in Sherwood Park.
  • Verify the agent does NOT fabricate a listing for Sherwood Park.
  • Verify the agent instead says it does not have details on that location and offers to take your information for the leasing team to follow up.
  • End the call.

Why this edge case matters for real businesses

Sherwood Park is a community just outside Edmonton. Apex Property Group does not manage any properties there. If the agent invents a listing that does not exist, a real business would lose credibility and potentially face legal issues.

The system prompt's rule to never fabricate information not in the prompt is what prevents this. If the agent fails this test, revisit your system prompt and strengthen the instruction about only referencing listed properties.

  • Document all 5 results in a pass/fail table with three columns: Scenario, What Happened, and Pass/Fail.

Keep notes on the most surprising failure

It is common for at least one scenario to fail on the first attempt. The most valuable learning happens when you identify why the agent gave an unexpected response and trace it back to a gap in your system prompt. If a scenario fails, update your system prompt, click Publish, and re-run the scenario.

Agent giving vague or incorrect answers?

If the agent gives generic responses instead of referencing specific listing data, your system prompt may not include enough detail about the properties. Return to your assistant's Model section in the Vapi Dashboard and verify the listing details (names, sizes, prices) are present.

If the agent fabricates information for Scenario 5, add a stronger instruction in your system prompt such as: "If asked about a location or property not listed above, say you do not have information on that location and offer to take the caller's details."

Remember to click Publish after any system prompt changes before re-testing.

Still getting unexpected results? Help me debug why my Vapi voice agent is not following its system prompt instructions for one of my test scenarios.

You now have a tested, verified voice receptionist that handles five distinct business scenarios. Next up, you will configure structured outputs to automatically extract lead data from every call into a clean JSON format.

Configure Structured Outputs

Your voice agent captures lead information during conversations, but right now that data lives buried inside unstructured call transcripts. The leasing team would need to listen to every single recording to extract tenant details.

Structured outputs solve this by automatically extracting specific data fields from every call into clean JSON. In this step, you'll configure a schema that pulls 7 key fields from each conversation automatically.

In this step, get ready to:
  • Create a structured output schema with 7 fields.
  • Attach the schema to your Apex Reception assistant.
  • Verify extraction accuracy across 3 complete test calls.
Create the Lead Capture structured output

A structured output tells Vapi exactly which data points to extract from a conversation. You define the fields and their types, and Vapi analyzes each call to populate them automatically.

  • In the Vapi Dashboard, click Structured Outputs in the left sidebar.
  • Click Create New Structured Output.
  • Name it Lead Capture.
  • Set the type to Object.

Now define the 7 fields that Vapi will extract from every call. Add each field with the following names and types:

  • caller_name (string)
  • company_name (string)
  • space_type_interest (string)
  • approximate_size_sqft (string)
  • move_in_timeline (string)
  • tour_requested (boolean)
  • callback_number (string)

Why are most fields strings instead of more specific types?

Voice conversations are messy. A caller might say "around two thousand square feet" or "2,000 sqft" or "2k." Strings let Vapi capture exactly what was said without failing type validation.

The one exception is tour_requested because that's always a clear yes or no answer.

Attach the structured output to your assistant

Creating the schema alone doesn't activate it. You need to link it to the specific assistant that should use it.

  • Navigate to Assistants in the left sidebar.
  • Click on your Apex Reception assistant.
  • Find the Artifact Plan section in your assistant's configuration.
  • Link the Lead Capture structured output.
  • Click Publish to save your changes.

What is the Artifact Plan?

The Artifact Plan tells Vapi what structured data to produce after each call ends. By linking your Lead Capture schema here, every completed call will automatically generate a JSON object with the 7 fields you defined.

Can't find the Artifact Plan section?

Scroll down in your assistant's configuration page. The Artifact Plan section may be below the Model, Voice, and Tools sections. Make sure you're editing the Apex Reception assistant and not creating a new one.

Help me find where to attach a structured output to my Vapi assistant.

Run 3 test calls and verify the extracted data

The schema is configured, but you need to prove it works. Each test call must include enough information for all 7 fields to populate.

  • Click Talk to Assistant in the top right corner of your Apex Reception assistant.
  • In your first test call, state your name, a company name, a space type and size preference, a move-in timeline, and request a tour.
  • End the call once the agent confirms your details.

Example conversation script

Try something like: "Hi, my name is Sarah Chen from Bright Ideas Marketing. We're looking for office space around 1,200 square feet. We'd like to move in by September. Can I book a tour? My number is 780-555-0199."

Vary your details across all 3 calls. Use different names, company types, space preferences, and timelines to test extraction accuracy across diverse inputs.

After each call, verify that Vapi correctly extracted the data:

  • Wait 30 seconds after ending the call for processing to complete.
  • Click Call Logs in the left sidebar.
  • Click your most recent call.
  • Find the Structured Outputs section. You should see all 7 fields populated with the values you provided during the call.
  • Repeat this process for 2 more calls, using different details each time.
  • After all 3 calls, check that each call's structured output has all 7 fields correctly filled.

Some fields showing as empty or null?

If a field like callback_number or company_name is empty, you likely didn't mention that information clearly during the call. Re-run the test and make sure you explicitly state every piece of data.

If tour_requested isn't populating, try clearly saying "Yes, I'd like to book a tour" or "No tour needed" rather than hinting at it indirectly.

Help me troubleshoot why my structured output fields are not populating after a Vapi call.

Your voice agent now captures structured lead data from every conversation. Next up, you'll record a 60-second demo that proves the entire system works end-to-end.

Record Your 60-Second Demo

Your voice receptionist is fully functional. It answers questions, qualifies leads, and captures structured data from every call. Now you need proof.

A 60-second uncut screen recording is the single most convincing asset you can show a potential client. It proves the system works end-to-end in real time, with no edits or tricks.

In this step, get ready to:
  • Prepare your screen recording tool.
  • Record a complete conversation with the voice agent.
  • Show the structured output result in Call Logs to close the recording.
Prepare your screen recording tool

Both macOS and Windows have free built-in screen recording tools. You do not need to install anything extra.

macOS

  • Press Cmd+Shift+5 to open the Screenshot toolbar.
  • Click the Record Entire Screen icon (the rectangle with a circle in the corner).
  • Click Options and select your built-in microphone so your voice is captured during the call.
  • Do not click Record yet. You will start recording in the next substep.

Windows

  • Press Win+G to open the Xbox Game Bar.
  • In the Capture widget, click the microphone icon to enable audio recording.
  • Close the Game Bar overlay for now by pressing Win+G again. You will start recording in the next substep.

Snipping Tool alternative

If Xbox Game Bar is disabled on your machine, open Snipping Tool from the Start menu and click the video camera icon to switch to screen recording mode.

  • Switch to your browser where the Apex Property Group landing page is open with the Vapi voice widget visible in the bottom-right corner.

Close distractions

Before recording, close any browser tabs, notifications, or chat windows that could interrupt. A clean screen looks more professional in your demo.

Record a complete conversation with the voice agent

Your recording needs to show the full conversation flow in one uncut take. Plan what you will say before pressing record.

What to cover in your 60 seconds

Your conversation must include these four parts in order:

  • The agent greeting you when the call connects.
  • You asking about a specific available space with pricing (e.g., office space under 1,500 sqft).
  • You asking about CAM charges.
  • You providing your name and callback number for lead capture.
  • Start your screen recording now.

macOS

  • Press Cmd+Shift+5 to reopen the toolbar if it closed, then click Record.

Windows

  • Press Win+Alt+R to start recording immediately via Xbox Game Bar.
  • Click the voice button in the bottom-right corner of the landing page.
  • Wait for the agent to greet you with the Apex Property Group message.
  • Ask about available office space and pricing. For example: "Do you have any office space under 1,500 square feet?"
  • After the agent responds with listing details, ask: "What are CAM charges and what do they include?"
  • When the agent finishes explaining, provide your name and a callback number so the agent triggers lead capture.
  • End the call by clicking the voice button again or saying goodbye.

Keep answers short

If the agent gives a long response, you can interrupt politely to move to the next topic. This keeps your demo tight and within 60 seconds.

Show the structured output and stop recording

The final proof in your demo is showing the structured data the agent captured. This demonstrates the system does not just talk, it produces actionable output.

  • After the call ends, switch to the Vapi Dashboard in your browser.
  • Click Call Logs in the left sidebar.
  • Click your most recent call (the one you just finished).
  • Scroll to the Structured Outputs section. Wait until all 7 fields are visible on screen.
  • Pause for 3-5 seconds so a viewer can read the captured data.
  • Stop your screen recording now.

macOS

  • Click the square Stop icon in the menu bar at the top of your screen.
  • Your recording saves automatically to the Desktop by default.

Windows

  • Press Win+Alt+R again to stop recording.
  • Your recording saves to Videos > Captures by default.
  • Open the recording file and watch it back to confirm the full conversation and structured output are both visible.

Why uncut matters

An uncut recording proves the system works in real time with no edits. This is far more convincing to a potential client than a polished montage, because it shows reliability under live conditions.

Structured output shows empty fields?

If some fields in the structured output are empty after your demo call, it means the agent did not capture those details during the conversation. Record again, making sure you clearly state your name, company, callback number, and space preferences.

Also check that you waited at least 30 seconds after the call ended before opening Call Logs. The structured output needs a moment to populate.

Why are my structured output fields empty after the demo call?

You now have a portfolio-ready demo proving your AI receptionist works end-to-end. Next, you will connect a real Edmonton-area phone number so people can call your agent from any phone.

Connect a Real Phone Number via Twilio

Your demo recording proves the system works through the web widget. But a real receptionist needs to answer a real phone number.

In this step, you'll create a Twilio account and purchase an Edmonton-area phone number that routes inbound calls directly to your Apex Reception agent.

In this step, get ready to:
  • Purchase an Edmonton-area phone number through Twilio.
  • Import the number into Vapi and assign your assistant.
  • Make a real phone call to verify the integration works end-to-end.
Create a Twilio account and purchase a phone number

Twilio is a cloud communications platform that provides phone numbers you can program. You'll use it to get a real Edmonton-area number that forwards calls to your Vapi assistant.

  • Open twilio.com in your browser.
  • Click Sign up and create a free trial account.
  • Twilio will ask you to verify your email and phone number during signup. Complete both verifications.

What does Twilio's free trial include?

The free trial includes $15 in credits with no credit card required. A Canadian local number costs $1.15/month, so your trial credits cover the number for the duration of this project.

The phone number you use during signup is automatically verified as a Caller ID. This matters later when testing inbound calls.

  • In the Twilio Console, navigate to Products & Services in the left sidebar.
  • Click Numbers and Senders.
  • Click the Phone Numbers tab.
  • Click Set up a new phone number.
  • Complete the Basic information page and click Next.
  • On the Select Number page, apply the area code filter. Enter 780 or 587 (both serve Edmonton) and click Search.
  • Click Select next to a number you like, then click Next.
  • On the Review and buy number page, review your selection and click Purchase.

Why an Edmonton area code?

Area codes 780 and 587 serve Edmonton, Alberta. A local number builds trust with prospective tenants calling Apex Property Group. People are more likely to call a local number than a toll-free or out-of-province one.

Not seeing Canadian numbers?

Twilio may prompt you to complete a regulatory compliance step for non-US numbers. Canada is a supported trial country, so follow any on-screen prompts to provide your address or identity information. This is a standard verification step.

If you cannot find a 780 or 587 number, try the other area code. Both serve Edmonton.

Help me find and purchase a Canadian phone number in Twilio.

You should see a confirmation that your number has been purchased. Save this phone number somewhere safe. You'll need it in the next substep.

Import the Twilio number into Vapi

Now you need to connect your Twilio number to Vapi so that inbound calls route to your Apex Reception assistant.

  • In the Twilio Console, go to API keys & tokens in the left sidebar.
  • Locate your Account SID and Auth Token. Copy both values and save them somewhere safe.

What are Account SID and Auth Token?

These are your Twilio API credentials. The Account SID identifies your account, and the Auth Token authenticates requests. Vapi needs both to control your phone number on your behalf.

  • Switch back to the Vapi Dashboard.
  • Click Phone Numbers in the left sidebar.
  • Click Import.
  • Enter your Twilio phone number, Account SID, and Auth Token in the fields provided.
  • Click Import.
  • After the number imports, assign the Apex Reception assistant to handle all inbound calls on this number.

You should see the phone number listed in your Vapi Phone Numbers section with the Apex Reception assistant assigned.

Import failing?

Double-check that you copied the Account SID and Auth Token exactly. The Auth Token is hidden by default in the Twilio Console. Click the reveal icon to copy it.

Make sure the phone number format includes the country code (e.g. +1 for Canada).

Help me import my Twilio number into Vapi.

Verify your phone and test the integration

Twilio trial accounts require verified caller IDs for inbound calls

Twilio trial accounts only accept inbound calls from phone numbers that have been verified in that account. If you call your Twilio number from an unverified phone, the call will not connect.

The phone number you used during Twilio signup is automatically verified. If that is the phone you plan to test with, you can skip the verification step below.

  • In the Twilio Console, navigate to Products & Services, then Numbers and Senders.
  • Select Verified caller IDs in the side navigation.
  • Click Add a new Caller ID.
  • Enter your personal phone number and verify it by entering the code Twilio sends via call or SMS.

Already verified during signup?

If you used the same phone number when creating your Twilio account, it is already verified. You can confirm this by checking the Verified caller IDs page. Your signup number should already appear in the list.

Now for the moment of truth. Call your new Twilio number from your verified personal phone.

  • Open your phone's dialler and call the Edmonton-area number you just purchased.
  • Listen for the Apex Reception greeting: "Thank you for calling Apex Property Group."
  • Run one full test conversation. Ask about available office space and provide your name and callback number to trigger the lead capture flow.
  • End the call and check Call Logs in the Vapi Dashboard to confirm the call was recorded and structured output populated.

Call not connecting?

If you hear a message about the number not being reachable, confirm that you are calling from a verified phone number. Check the Verified caller IDs page in the Twilio Console to make sure your personal number is listed.

If the call connects but you hear silence instead of the greeting, return to the Vapi Dashboard and confirm the Apex Reception assistant is assigned to the imported phone number.

Help me troubleshoot my Twilio phone integration with Vapi.

Secret mission

Write a 50-Word Pitch Quantifying the Cost of Missed After-Hours Calls

You built the solution. Now prove its value with hard numbers. Write a 50-word pitch to a real commercial property management company that makes the ROI undeniable. Every number must be verifiable. No estimates. No vague language.

Clean Up Your Resources

Clean Up Your Resources

This project uses two cloud services that may incur charges over time. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Cost warning

Your Twilio phone number costs $1.15/month. This is covered by your $15 trial credits for approximately 13 months. After trial credits run out, Twilio will charge your payment method.

Your Vapi account charges $0.05/min plus model provider costs only when calls come in. There is no monthly fee. If no one calls, you pay nothing.

Resources you used:

  • Twilio Edmonton-area phone number (780/587 area code, $1.15/month covered by trial credits).
  • Vapi account with remaining signup credits (usage-based, no monthly charge).
  • Local project folder apex-receptionist containing index.html.

Keep everything running

No action needed. Choose this if you plan to keep demoing the agent or pitch it to a real company.

  • Your Twilio number stays active and the Apex Reception agent continues answering inbound calls.
  • Monthly cost after trial credits expire: $1.15/month for the phone number plus Vapi per-minute charges when calls come in.
  • Your landing page remains accessible locally by opening index.html in a browser.

Pause - I'll come back to this later

Release the Twilio number to stop monthly charges while keeping your Vapi assistant fully configured. You can import a new number anytime to reconnect.

  • In the Twilio Console, navigate to Phone Numbers, then Active Phone Numbers.
  • Click on your Edmonton-area number.
  • In the Properties tab, click Release this Number.
  • Your Vapi assistant, tools, and structured outputs stay configured at no cost. When you are ready to demo again, import a new Twilio number into Vapi.

Delete - I don't want to use this again

Remove all project resources and start fresh. Follow every item below.

  • Release your Twilio phone number: In the Twilio Console, go to Phone Numbers, then Active Phone Numbers. Click your number, open the Properties tab, and click Release this Number.
  • Delete your local project folder by running this command in the terminal:

On macOS/Linux:

rm -rf ~/Desktop/apex-receptionist

On Windows:

rmdir /s /q %USERPROFILE%\Desktop\apex-receptionist

What about your Vapi assistant?

Your Vapi assistant, function tools, and structured outputs remain on your Vapi account at no ongoing cost. Vapi only charges when calls are made. There is nothing to delete unless you want a completely empty dashboard.

That's a Wrap!

That's a Wrap!

You just built an AI voice receptionist that handles real commercial property inquiries, qualifies leads, captures structured data, and answers a real phone number. That is not a toy project. That is a deployable product.

Here's what you accomplished:

  • Designed a comprehensive system prompt that serves as an entire company knowledge base, and configured function tools for structured conversation flows without needing a backend server.
  • Built and deployed a professional landing page with an embedded Vapi voice widget, and set up structured outputs that extract 7 data fields from every call automatically.
  • Connected a real Edmonton-area phone number via Twilio that routes inbound calls to your AI agent, and tested 5 distinct business scenarios end-to-end with a recorded demo proving the system works.
  • Wrote a data-backed 50-word pitch to a real commercial property management company, quantifying the ROI of your AI receptionist solution with verifiable numbers.

Ready to quiz yourself?