Build a voice agent that books jobs

Build an AI scheduling agent with Retell AI that can check availability and schedule jobs using Zenbooker's API with step-by-step instructions.

Overview

In this tutorial, you'll build a voice agent that books jobs end-to-end using the Zenbooker API and Retell AI.

Service Area Check

Validate customer location and check coverage

Live Availability

Fetch real-time timeslots for scheduling

End-to-End Booking

Create complete job with custom services

The agent will:

  1. Ask for the customer's ZIP code
  2. Check if that location is in your service area
  3. Ask what they need done and estimate the duration
  4. Fetch real-time availability
  5. Collect their contact info and address
  6. Create a new job in Zenbooker using a custom service (defined from their description)

Prerequisites

Required Accounts & Credentials
  • A Zenbooker API key
    • A Retell AI account
    • (Optional) A phone number in Retell for testing

Step 1 — Create the Agent

In Retell, click Create AgentVoice.

Response engine: Conversation Flow

Voice: Choose your preferred TTS (e.g., OpenAI Alloy, ElevenLabs, etc.)

Language: English (US)

Step 2 — Conversation Flow Design

Here's the high-level conversation flow our agent will follow:


graph TD
    %% --- Style Definitions ---
    classDef customerNode fill:#e0f2f7,stroke:#26c6da,stroke-width:2px,color:#212121;
    classDef agentNode fill:#e8f5e9,stroke:#66bb6a,stroke-width:2px,color:#212121;
    classDef apiNode fill:#fff3e0,stroke:#ffb74d,stroke-width:2px,color:#212121;
    classDef dataNode fill:#ede7f6,stroke:#7e57c2,stroke-width:2px,color:#212121;
    classDef decisionNode fill:#cfd8dc,stroke:#607d8b,color:#212121,font-weight:bold;
    classDef startNode fill:#c8e6c9,stroke:#388e3c,font-weight:bold;
    classDef endNode fill:#ffcdd2,stroke:#d32f2f,font-weight:bold;

    %% --- Flow Start ---
    START("Call Initiated"):::startNode --> A("Agent: Greets & asks for ZIP code"):::agentNode;

    %% --- 1. Service Area & Data Storage ---
    A --> B("Customer: Provides ZIP"):::customerNode;
    B --> C["API Call: /service_area_check"]:::apiNode;
    C --> D{"Serviceable?"}:::decisionNode;
    D -->|No| E("Agent: Sorry, not in area. New ZIP?"):::agentNode;
    E --> A;
    D -->|Yes| F("Agent: Stores territory_id, lat, & lng"):::dataNode;

    %% --- 2. Define Custom Service ---
    F --> G("Agent: What needs to be hauled away?"):::agentNode;
    G --> H("Customer: Describes Items"):::customerNode;
    H --> I("Agent: Extracts items & Estimates duration"):::agentNode;

    %% --- 3. Find & Select Timeslot ---
    I --> J["API Call: Fetch available timeslots"]:::apiNode;
    J --> K("Agent: Presents available times"):::agentNode;
    K --> L{"Customer selects a time?"}:::decisionNode;
    L -->|Yes| S("Customer: Confirms Chosen Slot"):::customerNode;
    L -->|"Wants more options"| M{"From currently fetched slots?"}:::decisionNode;
    M -->|Yes| K;
    M -->|No, wants later date| N["API Call: Fetch more timeslots"]:::apiNode;
    N --> K;

    %% --- 4. Finalize Booking ---
    S --> T("Agent: Collects Name, Address, Phone, Email"):::agentNode;
    T --> U("Customer: Provides Contact Info"):::customerNode;
    U --> V("Agent: Reviews all details for confirmation"):::agentNode;
    V --> W{"Customer Confirms Booking?"}:::decisionNode;
    W -->|No / Correct Info| T;
    W -->|Yes| X["API Call: /jobs (Create Job)"]:::apiNode;
    X --> Y{"Job Created Successfully?"}:::decisionNode;
    Y -->|Failure| Z("Agent: Issue booking. Please call back."):::agentNode;
    Y -->|Success| AA("Agent: Job booked! Confirmation sent."):::agentNode;

    %% --- Flow End ---
    AA --> END("End Call"):::endNode;
    Z --> END;
Conversation Flow Breakdown

Welcome → ZIP Collection

  • Greet the customer warmly
  • Ask for their ZIP code to check service coverage
  • Extract postal_code parameter

Service Area Validation

  • Call service_area_check with the postal code
  • If in_service_area = true: Continue to service inquiry
  • If in_service_area = false: Politely explain coverage limits, optionally retry

Service Details

  • Ask "What do you need help with?" or similar
  • Extract service_description (free text)
  • Estimate or ask for duration_minutes

Scheduling

  • Set date to today's date (YYYY-MM-DD format)
  • Call get_timeslots to fetch available appointments
  • Present 2-3 options to the customer
  • Extract chosen timeslot_id

Customer Information

  • Collect name, phone, email
  • Collect complete service address
  • Confirm notification preferences (SMS/Email)

Final Confirmation

  • Review all details with customer
  • Call create_job to book the appointment
  • Provide confirmation number and next steps

Step 3: Add Zenbooker API Functions in Retell

You'll connect your agent to Zenbooker's API by adding three custom functions.

graph LR
    A[ZIP Code] --> B[service_area_check]
    B --> C[territory_id + coordinates]
    C --> D[get_timeslots]
    D --> E[timeslot_id]
    E --> F[create_job]
1. Service Area Coverage Check

Purpose: Check if the customer's location is within any of your service territories and get the territory_id that services that area.

Method: GET

URL: https://api.zenbooker.com/v1/scheduling/service_area_check

  Authorization: Bearer YOUR_ZENBOOKER_API_KEY

Agent Logic: Call this after extracting a valid ZIP code. If in_service_area is true, continue to "What do you need done?"; otherwise, respond politely that the area isn't serviced. Save the territory_id — you'll need it for the next step.

2. Get Available Timeslots

Purpose: Fetch available appointment times for the specific territory that services the customer's location.

Method: GET

URL: https://api.zenbooker.com/v1/scheduling/timeslots

  Authorization: Bearer YOUR_ZENBOOKER_API_KEY

Agent Logic: The agent reads the first few timeslots and offers them to the customer. If the customer wants to hear more, the agent uses next_date to fetch additional results.

3. Create Job Booking

Purpose: Create the booking in Zenbooker once the customer confirms their time and details.

Method: POST

URL: https://api.zenbooker.com/v1/jobs

  Authorization: Bearer YOUR_ZENBOOKER_API_KEY
  Content-Type: application/json

Next Steps

Test Your Agent

Use Retell's testing interface to simulate the booking flow

Configure Webhooks

Set up webhooks to track booking status changes