Eedesy
Book Demo
HomeProductsContact
AI Voice Agent
  • Introduction
  • Quick Start
  • Architecture
  • Core Concepts
  • Configuration
  • Creating an Agent
  • Using Templates
  • System Prompt Configuration
  • Language Selection
  • Settings Reference
  • Overview
  • Upload Files (PDF, DOCX)
  • Web Crawling (URLs & Sitemaps)
  • Document Processing
  • RAG Integration
  • Troubleshooting
  • Creating a Campaign
  • CSV Upload & Variables
  • Scheduling & Retry Logic
  • Campaign Analytics
  • Contact Management
  • Uploading Contacts
  • Managing Contacts
  • Call History Enrichment
  • Trial Numbers
  • Purchasing Numbers
  • BYOP Setup
  • Exotel Setup
  • Telephony Providers Guide
  • Credits System
  • Provider Costs Breakdown
  • Usage Analytics
  • Credit Packs
  • Overview
  • Finding Your Workspace ID
  • Common Issues
  • Audio Quality
  • Latency Optimization
  • Error Codes
  • Overview
  • Twilio
  • Exotel
  • Plivo
  • Telnyx
  • WhatsApp
  • WebRTC Browser
  • Overview
  • Deepgram
  • Google Chirp
  • Azure Speech
  • ElevenLabs Scribe
  • AssemblyAI
  • OpenAI Whisper
  • Overview
  • Cartesia
  • ElevenLabs
  • Google TTS
  • Azure Neural
  • OpenAI TTS
  • Deepgram Aura
  • Sarvam Bulbul
  • HeyPixa Luna
  • Overview
  • OpenAI GPT-4o
  • Gemini 2.0/2.5 Flash
  • Gemini Live (Native Audio)
  • OpenAI Realtime
  • Anthropic Claude
  • Azure OpenAI
  • Overview
  • VAD (Voice Activity Detection)
  • Interruption Handling
  • Turn Detection
  • Audio Processing
  • Function Calling
  • Call Transfer
  • DTMF Handling
  • Call Recording
  • Exporting Recordings
  • Transcripts
  • Webhooks
  • Variables & Templates
  • Multi-Language Support
  • Hindi
  • Tamil
  • Assamese
  • Other Indian Languages
  • Latency Optimization
  • Scaling & Performance
  • Error Handling
  • Monitoring & Logging
  • Security Best Practices
  • Trigger Call via API
  • REST API
  • WebSocket Protocol
  • Webhooks
  • Webhook Subscriptions
  • SDKs
  • Overview
  • Financial Services
  • E-commerce
  • Logistics
  • Hyperlocal
  • Healthcare
  • Education
  • Overview
  • Customer Support
  • Sales & Lead Conversion
  • Marketing Campaigns
  • Debt Collection
  • Overview
  • Customer Support Bot
  • Order Status IVR
  • Appointment Booking
  • Lead Qualification
  • Outbound Sales
  • Recruitment Screening
  • Overview
  • Migrate from Vapi
  • Migrate from Retell AI
  • Migrate from Traditional IVR

Related Products

  • AI Voice Agent
  • AI Voice Assistant
  • Try Free
AI Voice Agent
  • Introduction
  • Quick Start
  • Architecture
  • Core Concepts
  • Configuration
  • Creating an Agent
  • Using Templates
  • System Prompt Configuration
  • Language Selection
  • Settings Reference
  • Overview
  • Upload Files (PDF, DOCX)
  • Web Crawling (URLs & Sitemaps)
  • Document Processing
  • RAG Integration
  • Troubleshooting
  • Creating a Campaign
  • CSV Upload & Variables
  • Scheduling & Retry Logic
  • Campaign Analytics
  • Contact Management
  • Uploading Contacts
  • Managing Contacts
  • Call History Enrichment
  • Trial Numbers
  • Purchasing Numbers
  • BYOP Setup
  • Exotel Setup
  • Telephony Providers Guide
  • Credits System
  • Provider Costs Breakdown
  • Usage Analytics
  • Credit Packs
  • Overview
  • Finding Your Workspace ID
  • Common Issues
  • Audio Quality
  • Latency Optimization
  • Error Codes
  • Overview
  • Twilio
  • Exotel
  • Plivo
  • Telnyx
  • WhatsApp
  • WebRTC Browser
  • Overview
  • Deepgram
  • Google Chirp
  • Azure Speech
  • ElevenLabs Scribe
  • AssemblyAI
  • OpenAI Whisper
  • Overview
  • Cartesia
  • ElevenLabs
  • Google TTS
  • Azure Neural
  • OpenAI TTS
  • Deepgram Aura
  • Sarvam Bulbul
  • HeyPixa Luna
  • Overview
  • OpenAI GPT-4o
  • Gemini 2.0/2.5 Flash
  • Gemini Live (Native Audio)
  • OpenAI Realtime
  • Anthropic Claude
  • Azure OpenAI
  • Overview
  • VAD (Voice Activity Detection)
  • Interruption Handling
  • Turn Detection
  • Audio Processing
  • Function Calling
  • Call Transfer
  • DTMF Handling
  • Call Recording
  • Exporting Recordings
  • Transcripts
  • Webhooks
  • Variables & Templates
  • Multi-Language Support
  • Hindi
  • Tamil
  • Assamese
  • Other Indian Languages
  • Latency Optimization
  • Scaling & Performance
  • Error Handling
  • Monitoring & Logging
  • Security Best Practices
  • Trigger Call via API
  • REST API
  • WebSocket Protocol
  • Webhooks
  • Webhook Subscriptions
  • SDKs
  • Overview
  • Financial Services
  • E-commerce
  • Logistics
  • Hyperlocal
  • Healthcare
  • Education
  • Overview
  • Customer Support
  • Sales & Lead Conversion
  • Marketing Campaigns
  • Debt Collection
  • Overview
  • Customer Support Bot
  • Order Status IVR
  • Appointment Booking
  • Lead Qualification
  • Outbound Sales
  • Recruitment Screening
  • Overview
  • Migrate from Vapi
  • Migrate from Retell AI
  • Migrate from Traditional IVR
  1. Docs
  2. AI Voice Agent
  3. Industries
  4. Logistics

AI Voice Agents for Logistics & Delivery

Build intelligent voice agents for logistics operations including shipment tracking, delivery scheduling, address confirmation, failed delivery handling, and proof of delivery collection. Integrate with Delhivery, BlueDart, and Shiprocket APIs.

AI Voice Agents for Logistics & Delivery

Automate customer communication across the delivery lifecycle with intelligent voice agents. Handle shipment tracking, delivery scheduling, address confirmation, and failed delivery resolution at scale.

Use Cases

1. Shipment Tracking

Proactive and reactive order tracking for customers.

Customer: "Where is my order?"
Agent: "I found your shipment. Your order ORD-78234 is currently in transit
        at the Bengaluru hub. Expected delivery is tomorrow by 6 PM.
        Would you like me to send a tracking link via SMS?"

2. Delivery Scheduling

Schedule and reschedule deliveries based on customer availability.

Agent: "Hi, this is Maya from QuickShip. We have a delivery scheduled for
        tomorrow between 10 AM and 2 PM. Will someone be available to receive it?"
Customer: "No, I'll be at work. Can you deliver after 6 PM?"
Agent: "I've rescheduled your delivery to tomorrow between 6 PM and 9 PM.
        Is there anything else I can help with?"

3. Address Confirmation

Verify delivery addresses before dispatch to reduce failed deliveries.

Agent: "I'm calling to confirm the delivery address for your order.
        I have: Flat 402, Sunrise Apartments, MG Road, Bengaluru 560001.
        Is this correct?"
Customer: "The flat number is wrong. It's 502, not 402."
Agent: "Thank you! I've updated the address to Flat 502, Sunrise Apartments.
        Your delivery is scheduled for tomorrow."

4. Failed Delivery Handling

Resolve failed deliveries and reschedule with customers.

Agent: "Hi, we attempted delivery of your order today but couldn't reach you.
        Would you like to reschedule for tomorrow, or should we hold it at
        our pickup center on Anna Nagar?"
Customer: "Please reschedule for tomorrow morning."
Agent: "Done! I've scheduled delivery between 9 AM and 12 PM tomorrow.
        Please ensure someone is available to receive it."

5. Proof of Delivery Collection

Collect delivery confirmations and feedback via voice.

Agent: "This is a confirmation call for your order ORD-91234 delivered today.
        Did you receive the package in good condition?"
Customer: "Yes, I got it."
Agent: "Great! On a scale of 1 to 5, how would you rate your delivery experience?"
Customer: "4"
Agent: "Thank you for your feedback! Is there anything we could improve?"

Agent Configuration

Standard Logistics Agent

{
  "agent": {
    "name": "Logistics Assistant",
    "language": "en-IN",

    "llmProvider": "gemini-2.5",
    "llmModel": "gemini-2.5-flash-lite",
    "llmTemperature": 0.3,

    "sttProvider": "deepgram",
    "sttModel": "nova-3",
    "sttConfig": {
      "endpointing": 400,
      "interimResults": true,
      "keywords": ["AWB:2", "tracking:2", "delivery:2", "address:2"]
    },

    "ttsProvider": "azure",
    "ttsVoice": "en-IN-NeerjaNeural",
    "ttsConfig": {
      "rate": "+5%",
      "pitch": "default"
    },

    "greetingMessage": "Hello! This is Maya from QuickShip logistics. How can I help you with your delivery today?",

    "allowInterruptions": true,
    "interruptionThreshold": 0.6,

    "prompt": "...",

    "tools": [],

    "webhooks": {
      "url": "https://your-server.com/webhooks/logistics",
      "events": ["call.ended", "delivery.rescheduled", "address.updated"]
    }
  }
}

Multilingual Configuration (Hindi + English)

{
  "agent": {
    "name": "Hinglish Delivery Agent",
    "language": "hi-IN",

    "llmProvider": "gemini",
    "llmModel": "gemini-2.0-flash",
    "llmTemperature": 0.5,

    "sttProvider": "deepgram",
    "sttModel": "nova-3",
    "sttConfig": {
      "language": "hi",
      "model": "nova-3",
      "keywords": ["AWB:2", "parcel:2", "delivery:2"]
    },

    "ttsProvider": "azure",
    "ttsVoice": "hi-IN-SwaraNeural",

    "greetingMessage": "Namaste! Main QuickShip ki taraf se Maya bol rahi hoon. Aapke delivery ke baare mein kaise madad kar sakti hoon?"
  }
}

System Prompt

You are Maya, a professional and efficient delivery assistant for QuickShip Logistics.

## Your Role
- Help customers track their shipments
- Schedule and reschedule deliveries
- Confirm and update delivery addresses
- Handle failed delivery inquiries
- Collect delivery confirmations and feedback

## Conversation Guidelines

### Response Style
- Be concise and clear (1-2 sentences max)
- Speak naturally, like a helpful delivery executive
- Always confirm changes before ending the call
- Use the customer's name when available

### Information Gathering
- Ask for AWB number or order ID to look up shipments
- Verify phone number if AWB not available (last 4 digits)
- Confirm address details by reading them back
- Never ask for more than one piece of information at a time

### Handling Common Scenarios

**Tracking Inquiries:**
1. Look up the shipment status
2. Provide current location and ETA
3. Offer to send SMS tracking link
4. Ask if they need anything else

**Delivery Reschedule:**
1. Confirm the order details
2. Ask for preferred date and time slot
3. Check slot availability using tool
4. Confirm the new schedule clearly
5. Send SMS confirmation

**Address Updates:**
1. Read out the current address on file
2. Listen carefully to corrections
3. Repeat the updated address back
4. Confirm the change was saved

**Failed Delivery:**
1. Apologize for the inconvenience
2. Explain the attempt details
3. Offer reschedule or pickup options
4. Confirm next steps clearly

## Escalation Criteria
Transfer to human agent if:
- Customer requests human assistance
- Customer is upset or frustrated
- Shipment shows "exception" or "lost" status
- Complex address issues requiring verification
- Requests for refunds or compensation

## Localization
- Use "delivery executive" not "driver"
- Use "parcel" or "shipment" interchangeably
- Time slots in 12-hour format with AM/PM
- Dates as "15th December" format

## DO NOT
- Make promises about exact delivery times
- Provide refund estimates
- Share delivery executive personal details
- Discuss pricing or charges

Tools for Delivery Management

1. Track Shipment

{
  "type": "function",
  "function": {
    "name": "track_shipment",
    "description": "Get real-time tracking status of a shipment by AWB number or order ID",
    "parameters": {
      "type": "object",
      "properties": {
        "awb_number": {
          "type": "string",
          "description": "Air Waybill number (e.g., DEL123456789)"
        },
        "order_id": {
          "type": "string",
          "description": "Order ID from e-commerce platform"
        },
        "phone_last_4": {
          "type": "string",
          "description": "Last 4 digits of customer phone for verification"
        }
      }
    }
  }
}

Tool Handler:

func handleTrackShipment(params map[string]any) (string, error) {
    var shipment *Shipment
    var err error

    if awb, ok := params["awb_number"].(string); ok && awb != "" {
        shipment, err = courierService.TrackByAWB(awb)
    } else if orderID, ok := params["order_id"].(string); ok && orderID != "" {
        shipment, err = courierService.TrackByOrderID(orderID)
    } else {
        return "I need either an AWB number or order ID to track your shipment.", nil
    }

    if err != nil || shipment == nil {
        return "I couldn't find that shipment. Please verify the tracking number.", nil
    }

    return formatShipmentStatus(shipment), nil
}

func formatShipmentStatus(s *Shipment) string {
    var response strings.Builder

    response.WriteString(fmt.Sprintf("Your shipment %s is ", s.AWB))

    switch s.Status {
    case "booked":
        response.WriteString("booked and awaiting pickup from the seller.")
    case "picked_up":
        response.WriteString(fmt.Sprintf("picked up and on its way to our %s facility.", s.CurrentLocation))
    case "in_transit":
        response.WriteString(fmt.Sprintf("in transit at our %s hub.", s.CurrentLocation))
    case "out_for_delivery":
        response.WriteString(fmt.Sprintf("out for delivery! Expected by %s today.", s.ETA.Format("3 PM")))
    case "delivered":
        response.WriteString(fmt.Sprintf("delivered on %s.", s.DeliveredAt.Format("January 2 at 3:04 PM")))
    case "failed_attempt":
        response.WriteString(fmt.Sprintf("marked as delivery attempted on %s. Reason: %s.",
            s.LastAttempt.Format("January 2"), s.FailureReason))
    case "rto":
        response.WriteString("being returned to the seller.")
    default:
        response.WriteString(fmt.Sprintf("in %s status.", s.Status))
    }

    if s.Status != "delivered" && s.Status != "rto" && !s.ETA.IsZero() {
        response.WriteString(fmt.Sprintf(" Expected delivery: %s.", s.ETA.Format("Monday, January 2")))
    }

    return response.String()
}

2. Reschedule Delivery

{
  "type": "function",
  "function": {
    "name": "reschedule_delivery",
    "description": "Reschedule a delivery to a new date and time slot",
    "parameters": {
      "type": "object",
      "properties": {
        "awb_number": {
          "type": "string",
          "description": "AWB number of the shipment"
        },
        "new_date": {
          "type": "string",
          "description": "New delivery date (YYYY-MM-DD)"
        },
        "time_slot": {
          "type": "string",
          "enum": ["morning", "afternoon", "evening"],
          "description": "Preferred time slot: morning (9AM-12PM), afternoon (12PM-4PM), evening (4PM-9PM)"
        }
      },
      "required": ["awb_number", "new_date", "time_slot"]
    }
  }
}

Tool Handler:

func handleRescheduleDelivery(params map[string]any) (string, error) {
    awb := params["awb_number"].(string)
    newDate := params["new_date"].(string)
    timeSlot := params["time_slot"].(string)

    // Parse and validate date
    deliveryDate, err := time.Parse("2006-01-02", newDate)
    if err != nil {
        return "I couldn't understand that date. Please specify a date like tomorrow or December 15th.", nil
    }

    // Check if date is valid (not in past, within 7 days)
    today := time.Now().Truncate(24 * time.Hour)
    maxDate := today.AddDate(0, 0, 7)

    if deliveryDate.Before(today) {
        return "I can only schedule deliveries for today or future dates.", nil
    }
    if deliveryDate.After(maxDate) {
        return "I can only schedule deliveries within the next 7 days.", nil
    }

    // Check slot availability
    available, err := courierService.CheckSlotAvailability(awb, deliveryDate, timeSlot)
    if !available {
        return fmt.Sprintf("Unfortunately, the %s slot on %s is not available. Would you like to try a different time?",
            timeSlot, deliveryDate.Format("January 2")), nil
    }

    // Reschedule
    result, err := courierService.RescheduleDelivery(awb, deliveryDate, timeSlot)
    if err != nil {
        return "I couldn't reschedule the delivery right now. Let me transfer you to someone who can help.", nil
    }

    slotTimes := map[string]string{
        "morning":   "9 AM to 12 PM",
        "afternoon": "12 PM to 4 PM",
        "evening":   "4 PM to 9 PM",
    }

    return fmt.Sprintf("I've rescheduled your delivery to %s between %s. You'll receive an SMS confirmation shortly.",
        deliveryDate.Format("Monday, January 2"), slotTimes[timeSlot]), nil
}

3. Update Delivery Address

{
  "type": "function",
  "function": {
    "name": "update_delivery_address",
    "description": "Update the delivery address for a shipment",
    "parameters": {
      "type": "object",
      "properties": {
        "awb_number": {
          "type": "string",
          "description": "AWB number of the shipment"
        },
        "flat_number": {
          "type": "string",
          "description": "Flat/House number"
        },
        "building_name": {
          "type": "string",
          "description": "Building or apartment name"
        },
        "street": {
          "type": "string",
          "description": "Street address"
        },
        "landmark": {
          "type": "string",
          "description": "Nearby landmark"
        },
        "city": {
          "type": "string",
          "description": "City name"
        },
        "pincode": {
          "type": "string",
          "description": "6-digit postal code"
        }
      },
      "required": ["awb_number"]
    }
  }
}

Tool Handler:

func handleUpdateAddress(params map[string]any) (string, error) {
    awb := params["awb_number"].(string)

    // Get current shipment
    shipment, err := courierService.GetShipment(awb)
    if err != nil {
        return "I couldn't find that shipment.", nil
    }

    // Check if address can be updated
    if shipment.Status == "out_for_delivery" || shipment.Status == "delivered" {
        return "Sorry, the address cannot be updated as the shipment is already out for delivery or delivered.", nil
    }

    // Build updated address
    address := shipment.Address
    if flat, ok := params["flat_number"].(string); ok && flat != "" {
        address.FlatNumber = flat
    }
    if building, ok := params["building_name"].(string); ok && building != "" {
        address.Building = building
    }
    if street, ok := params["street"].(string); ok && street != "" {
        address.Street = street
    }
    if landmark, ok := params["landmark"].(string); ok && landmark != "" {
        address.Landmark = landmark
    }
    if city, ok := params["city"].(string); ok && city != "" {
        address.City = city
    }
    if pincode, ok := params["pincode"].(string); ok && pincode != "" {
        if !isValidPincode(pincode) {
            return "That doesn't seem like a valid pincode. Please provide a 6-digit postal code.", nil
        }
        address.Pincode = pincode
    }

    // Update address
    err = courierService.UpdateAddress(awb, address)
    if err != nil {
        return "I couldn't update the address right now. Please try again later.", nil
    }

    return fmt.Sprintf("I've updated the delivery address to: %s. Is there anything else I can help with?",
        formatAddress(address)), nil
}

func formatAddress(a *Address) string {
    parts := []string{}
    if a.FlatNumber != "" {
        parts = append(parts, a.FlatNumber)
    }
    if a.Building != "" {
        parts = append(parts, a.Building)
    }
    if a.Street != "" {
        parts = append(parts, a.Street)
    }
    if a.City != "" && a.Pincode != "" {
        parts = append(parts, fmt.Sprintf("%s %s", a.City, a.Pincode))
    }
    return strings.Join(parts, ", ")
}

4. Get Delivery Slots

{
  "type": "function",
  "function": {
    "name": "get_available_slots",
    "description": "Get available delivery time slots for a date",
    "parameters": {
      "type": "object",
      "properties": {
        "awb_number": {
          "type": "string",
          "description": "AWB number of the shipment"
        },
        "date": {
          "type": "string",
          "description": "Date to check availability (YYYY-MM-DD)"
        }
      },
      "required": ["awb_number", "date"]
    }
  }
}

5. Collect Delivery Confirmation

{
  "type": "function",
  "function": {
    "name": "confirm_delivery",
    "description": "Record delivery confirmation from customer",
    "parameters": {
      "type": "object",
      "properties": {
        "awb_number": {
          "type": "string",
          "description": "AWB number of the shipment"
        },
        "received_by": {
          "type": "string",
          "description": "Name of person who received the delivery"
        },
        "condition": {
          "type": "string",
          "enum": ["good", "damaged", "partial"],
          "description": "Package condition on receipt"
        },
        "rating": {
          "type": "integer",
          "minimum": 1,
          "maximum": 5,
          "description": "Customer satisfaction rating (1-5)"
        },
        "feedback": {
          "type": "string",
          "description": "Additional feedback from customer"
        }
      },
      "required": ["awb_number", "condition"]
    }
  }
}

Courier System Integration

Delhivery Integration

package delhivery

import (
    "encoding/json"
    "fmt"
    "net/http"
    "net/url"
)

type Client struct {
    apiKey  string
    baseURL string
    client  *http.Client
}

func NewClient(apiKey string) *Client {
    return &Client{
        apiKey:  apiKey,
        baseURL: "https://track.delhivery.com/api/v1",
        client:  &http.Client{Timeout: 10 * time.Second},
    }
}

// Track shipment by AWB
func (c *Client) Track(awb string) (*ShipmentStatus, error) {
    url := fmt.Sprintf("%s/packages/json/?waybill=%s&token=%s",
        c.baseURL, awb, c.apiKey)

    resp, err := c.client.Get(url)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    var result DelhiveryTrackResponse
    json.NewDecoder(resp.Body).Decode(&result)

    if len(result.ShipmentData) == 0 {
        return nil, fmt.Errorf("shipment not found")
    }

    return mapDelhiveryStatus(result.ShipmentData[0]), nil
}

// Create pickup request
func (c *Client) CreatePickup(req PickupRequest) (*PickupResponse, error) {
    // Implementation
}

// Update delivery address
func (c *Client) UpdateAddress(awb string, address Address) error {
    // Implementation
}

type DelhiveryTrackResponse struct {
    ShipmentData []struct {
        Shipment struct {
            Status struct {
                Status          string `json:"Status"`
                StatusDateTime  string `json:"StatusDateTime"`
                StatusLocation  string `json:"StatusLocation"`
            } `json:"Status"`
            ExpectedDeliveryDate string `json:"ExpectedDeliveryDate"`
            Destination         string `json:"Destination"`
        } `json:"Shipment"`
    } `json:"ShipmentData"`
}

func mapDelhiveryStatus(data ShipmentData) *ShipmentStatus {
    status := &ShipmentStatus{
        AWB:             data.AWB,
        CurrentLocation: data.Shipment.Status.StatusLocation,
        RawStatus:       data.Shipment.Status.Status,
    }

    // Map Delhivery status to standard status
    switch data.Shipment.Status.Status {
    case "Manifested":
        status.Status = "booked"
    case "In Transit":
        status.Status = "in_transit"
    case "Out for Delivery":
        status.Status = "out_for_delivery"
    case "Delivered":
        status.Status = "delivered"
    case "Undelivered":
        status.Status = "failed_attempt"
    default:
        status.Status = "in_transit"
    }

    return status
}

BlueDart Integration

package bluedart

import (
    "encoding/xml"
    "fmt"
    "net/http"
)

type Client struct {
    licenseKey string
    loginID    string
    baseURL    string
    client     *http.Client
}

func NewClient(licenseKey, loginID string) *Client {
    return &Client{
        licenseKey: licenseKey,
        loginID:    loginID,
        baseURL:    "https://nettrack.bluedart.com/ver_1.7",
        client:     &http.Client{Timeout: 10 * time.Second},
    }
}

// Track shipment
func (c *Client) Track(awb string) (*ShipmentStatus, error) {
    soapRequest := fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
        <soap:Body>
            <GetShipmentTrackingDetails xmlns="http://bluedart.com/">
                <AWBNo>%s</AWBNo>
                <LicenceKey>%s</LicenceKey>
                <LoginID>%s</LoginID>
            </GetShipmentTrackingDetails>
        </soap:Body>
    </soap:Envelope>`, awb, c.licenseKey, c.loginID)

    req, _ := http.NewRequest("POST", c.baseURL+"/TrackingService.svc",
        strings.NewReader(soapRequest))
    req.Header.Set("Content-Type", "text/xml; charset=utf-8")
    req.Header.Set("SOAPAction", "http://bluedart.com/GetShipmentTrackingDetails")

    resp, err := c.client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    // Parse SOAP response and map to standard status
    return parseBluedarResponse(resp.Body)
}

// Schedule delivery slot
func (c *Client) ScheduleDelivery(awb string, date time.Time, slot string) error {
    // BlueDart slot scheduling implementation
}

Shiprocket Integration

package shiprocket

import (
    "encoding/json"
    "fmt"
    "net/http"
)

type Client struct {
    token   string
    baseURL string
    client  *http.Client
}

func NewClient(email, password string) (*Client, error) {
    client := &Client{
        baseURL: "https://apiv2.shiprocket.in/v1/external",
        client:  &http.Client{Timeout: 10 * time.Second},
    }

    // Authenticate and get token
    token, err := client.authenticate(email, password)
    if err != nil {
        return nil, err
    }
    client.token = token

    return client, nil
}

// Track by AWB
func (c *Client) Track(awb string) (*ShipmentStatus, error) {
    req, _ := http.NewRequest("GET",
        fmt.Sprintf("%s/courier/track/awb/%s", c.baseURL, awb), nil)
    req.Header.Set("Authorization", "Bearer "+c.token)

    resp, err := c.client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    var result ShiprocketTrackResponse
    json.NewDecoder(resp.Body).Decode(&result)

    return mapShiprocketStatus(result), nil
}

// Track by Order ID
func (c *Client) TrackByOrderID(orderID string) (*ShipmentStatus, error) {
    req, _ := http.NewRequest("GET",
        fmt.Sprintf("%s/orders/show/%s", c.baseURL, orderID), nil)
    req.Header.Set("Authorization", "Bearer "+c.token)

    resp, err := c.client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    var result ShiprocketOrderResponse
    json.NewDecoder(resp.Body).Decode(&result)

    if result.Data.AWBCode == "" {
        return nil, fmt.Errorf("order not shipped yet")
    }

    return c.Track(result.Data.AWBCode)
}

// Update delivery address
func (c *Client) UpdateAddress(orderID string, address Address) error {
    payload := map[string]any{
        "order_id":         orderID,
        "shipping_address": address.Street,
        "shipping_city":    address.City,
        "shipping_pincode": address.Pincode,
        "shipping_state":   address.State,
    }

    body, _ := json.Marshal(payload)
    req, _ := http.NewRequest("POST", c.baseURL+"/orders/address/update",
        bytes.NewReader(body))
    req.Header.Set("Authorization", "Bearer "+c.token)
    req.Header.Set("Content-Type", "application/json")

    resp, err := c.client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return fmt.Errorf("failed to update address")
    }

    return nil
}

Unified Courier Interface

package courier

type CourierProvider interface {
    Track(awb string) (*ShipmentStatus, error)
    UpdateAddress(awb string, address Address) error
    RescheduleDelivery(awb string, date time.Time, slot string) error
    GetDeliverySlots(awb string, date time.Time) ([]TimeSlot, error)
}

type MultiCourierService struct {
    providers map[string]CourierProvider
}

func NewMultiCourierService() *MultiCourierService {
    return &MultiCourierService{
        providers: map[string]CourierProvider{
            "delhivery":  delhivery.NewClient(os.Getenv("DELHIVERY_API_KEY")),
            "bluedart":   bluedart.NewClient(os.Getenv("BLUEDART_LICENSE"), os.Getenv("BLUEDART_LOGIN")),
            "shiprocket": shiprocket.NewClient(os.Getenv("SHIPROCKET_EMAIL"), os.Getenv("SHIPROCKET_PASSWORD")),
        },
    }
}

// Auto-detect courier from AWB prefix
func (s *MultiCourierService) DetectCourier(awb string) string {
    prefixes := map[string]string{
        "1":   "delhivery",   // Delhivery AWBs start with numbers
        "2":   "delhivery",
        "D":   "delhivery",
        "3":   "bluedart",    // BlueDart AWBs
        "SF":  "shiprocket",  // Shiprocket self-ship
    }

    for prefix, courier := range prefixes {
        if strings.HasPrefix(awb, prefix) {
            return courier
        }
    }

    return "shiprocket" // Default fallback
}

func (s *MultiCourierService) Track(awb string) (*ShipmentStatus, error) {
    courier := s.DetectCourier(awb)
    provider := s.providers[courier]

    status, err := provider.Track(awb)
    if err != nil {
        // Try other providers as fallback
        for name, p := range s.providers {
            if name == courier {
                continue
            }
            if status, err = p.Track(awb); err == nil {
                return status, nil
            }
        }
        return nil, fmt.Errorf("shipment not found in any courier system")
    }

    status.Courier = courier
    return status, nil
}

Multi-Language Support

Regional Language Configuration

var LogisticsLanguageConfigs = map[string]LanguageConfig{
    "hi-IN": {
        Language:     "hi-IN",
        STTProvider:  "deepgram",
        STTModel:     "nova-3",
        TTSProvider:  "azure",
        TTSVoice:     "hi-IN-SwaraNeural",
        LLMProvider:  "gemini",
        Greeting:     "Namaste! Main QuickShip logistics se Maya bol rahi hoon. Aapke delivery ke baare mein kaise madad karun?",
    },
    "ta-IN": {
        Language:     "ta-IN",
        STTProvider:  "deepgram",
        STTModel:     "nova-3",
        TTSProvider:  "azure",
        TTSVoice:     "ta-IN-PallaviNeural",
        LLMProvider:  "gemini",
        Greeting:     "Vanakkam! Naan QuickShip logistics-il irundhu Maya pesugiren. Ungal delivery patriya eppadi udhava mudiyum?",
    },
    "te-IN": {
        Language:     "te-IN",
        STTProvider:  "google",
        STTModel:     "chirp_2",
        TTSProvider:  "azure",
        TTSVoice:     "te-IN-ShrutiNeural",
        LLMProvider:  "gemini",
        Greeting:     "Namaskaram! Nenu QuickShip logistics nundi Maya matladutunnanu. Mee delivery gurinchi ela sahaayam cheyagalanu?",
    },
    "bn-IN": {
        Language:     "bn-IN",
        STTProvider:  "deepgram",
        STTModel:     "nova-3",
        TTSProvider:  "azure",
        TTSVoice:     "bn-IN-TanishaaNeural",
        LLMProvider:  "gemini",
        Greeting:     "Namaskar! Ami QuickShip logistics theke Maya bolchi. Apnar delivery niye ki bhabe sahajyo korte pari?",
    },
    "mr-IN": {
        Language:     "mr-IN",
        STTProvider:  "google",
        STTModel:     "chirp_2",
        TTSProvider:  "azure",
        TTSVoice:     "mr-IN-AarohiNeural",
        LLMProvider:  "gemini",
        Greeting:     "Namaskar! Mi QuickShip logistics madhun Maya bolte ahe. Tumchya delivery babtit kashi madad karu?",
    },
    "gu-IN": {
        Language:     "gu-IN",
        STTProvider:  "google",
        STTModel:     "chirp_2",
        TTSProvider:  "azure",
        TTSVoice:     "gu-IN-DhwaniNeural",
        LLMProvider:  "gemini",
        Greeting:     "Namaskar! Hu QuickShip logistics thi Maya bolu chhu. Tamari delivery mate kem madad kari shaku?",
    },
    "kn-IN": {
        Language:     "kn-IN",
        STTProvider:  "google",
        STTModel:     "chirp_2",
        TTSProvider:  "azure",
        TTSVoice:     "kn-IN-SapnaNeural",
        LLMProvider:  "gemini",
        Greeting:     "Namaskara! Naanu QuickShip logistics inda Maya maatanaaduttiddene. Nimma delivery bagge hege sahaaya maadali?",
    },
}

Language Detection and Switching

type MultilingualDeliveryAgent struct {
    configs      map[string]LanguageConfig
    currentLang  string
    session      *Session
}

func (a *MultilingualDeliveryAgent) DetectLanguage(transcript string) string {
    // Check for language indicators
    languagePatterns := map[string][]string{
        "hi-IN": {"kya", "haan", "nahi", "delivery", "parcel", "address"},
        "ta-IN": {"enna", "illa", "aama", "irukku", "delivery"},
        "te-IN": {"emi", "kaadu", "avunu", "delivery", "address"},
        "bn-IN": {"ki", "na", "haan", "delivery", "thik"},
    }

    for lang, patterns := range languagePatterns {
        for _, pattern := range patterns {
            if strings.Contains(strings.ToLower(transcript), pattern) {
                return lang
            }
        }
    }

    return "en-IN" // Default to English
}

func (a *MultilingualDeliveryAgent) SwitchLanguage(lang string) error {
    config, ok := a.configs[lang]
    if !ok {
        return fmt.Errorf("language %s not supported", lang)
    }

    a.currentLang = lang
    a.session.UpdateSTT(config.STTProvider, config.STTModel)
    a.session.UpdateTTS(config.TTSProvider, config.TTSVoice)
    a.session.AddSystemContext(fmt.Sprintf(
        "User prefers %s. Respond in %s from now on.",
        lang, config.LanguageName,
    ))

    return nil
}

Localized Response Templates

var DeliveryStatusTemplates = map[string]map[string]string{
    "en-IN": {
        "in_transit":        "Your shipment is in transit at our %s hub. Expected delivery: %s.",
        "out_for_delivery":  "Great news! Your package is out for delivery and should arrive by %s today.",
        "delivered":         "Your package was delivered on %s.",
        "failed_attempt":    "We attempted delivery on %s but couldn't reach you. Reason: %s.",
    },
    "hi-IN": {
        "in_transit":        "Aapka shipment hamare %s hub par hai. Delivery ka anuman: %s.",
        "out_for_delivery":  "Acha news! Aapka parcel delivery ke liye nikal chuka hai, aaj %s tak pahunch jayega.",
        "delivered":         "Aapka package %s ko deliver ho gaya.",
        "failed_attempt":    "%s ko delivery ka prayas kiya gaya lekin aap tak nahi pahunch sake. Karan: %s.",
    },
    "ta-IN": {
        "in_transit":        "Ungal shipment engal %s hub-il irukkiradhu. Ethirpaarkkum delivery: %s.",
        "out_for_delivery":  "Nalla seythi! Ungal parcel delivery-kku purappattu vittathu, inru %s-kku varum.",
        "delivered":         "Ungal package %s andru deliver seyyappattathu.",
        "failed_attempt":    "%s andru delivery muyarchi seyyappattathu aanaal ungalai adaiya mudiyavillai. Kaaranam: %s.",
    },
}

func (a *MultilingualDeliveryAgent) FormatStatus(status *ShipmentStatus) string {
    templates := DeliveryStatusTemplates[a.currentLang]
    if templates == nil {
        templates = DeliveryStatusTemplates["en-IN"]
    }

    template := templates[status.Status]
    if template == "" {
        template = templates["in_transit"]
    }

    return fmt.Sprintf(template, status.CurrentLocation, status.ETA.Format("January 2"))
}

Outbound Campaign Management

Delivery Notification Campaign

type DeliveryNotificationCampaign struct {
    AgentID       string
    ShipmentIDs   []string
    CallType      string // "scheduling", "confirmation", "failed_delivery"
    MaxRetries    int
    RetryInterval time.Duration
}

func (c *DeliveryNotificationCampaign) Execute(ctx context.Context) (*CampaignResult, error) {
    results := &CampaignResult{
        TotalCalls:    len(c.ShipmentIDs),
        SuccessfulCalls: 0,
        FailedCalls:   0,
        Outcomes:      make(map[string]int),
    }

    for _, shipmentID := range c.ShipmentIDs {
        shipment, _ := courierService.GetShipment(shipmentID)

        // Prepare call variables
        variables := map[string]string{
            "awb_number":        shipment.AWB,
            "customer_name":     shipment.CustomerName,
            "delivery_date":     shipment.ETA.Format("Monday, January 2"),
            "delivery_slot":     shipment.TimeSlot,
            "current_address":   formatAddress(shipment.Address),
        }

        // Initiate call
        call, err := voiceAgent.Call(ctx, CallRequest{
            AgentID:   c.AgentID,
            To:        shipment.CustomerPhone,
            Variables: variables,
        })

        if err != nil {
            results.FailedCalls++
            continue
        }

        // Wait for call completion
        outcome := <-call.Done()
        results.Outcomes[outcome]++

        if outcome == "success" || outcome == "rescheduled" {
            results.SuccessfulCalls++
        } else {
            results.FailedCalls++

            // Schedule retry if needed
            if outcome == "no_answer" && call.Attempts < c.MaxRetries {
                scheduleRetry(shipmentID, c.RetryInterval)
            }
        }
    }

    return results, nil
}

Batch Processing

func ProcessDailyDeliveryNotifications(ctx context.Context) error {
    // Get shipments scheduled for tomorrow
    tomorrow := time.Now().AddDate(0, 0, 1)
    shipments, _ := courierService.GetShipmentsForDate(tomorrow)

    // Group by notification type
    confirmations := filterByStatus(shipments, "in_transit")
    failedDeliveries := filterByStatus(shipments, "failed_attempt")

    // Run confirmation calls (morning)
    confirmCampaign := &DeliveryNotificationCampaign{
        AgentID:       "delivery_confirmation_agent",
        ShipmentIDs:   getAWBs(confirmations),
        CallType:      "confirmation",
        MaxRetries:    2,
        RetryInterval: 2 * time.Hour,
    }

    go confirmCampaign.Execute(ctx)

    // Run failed delivery calls (afternoon)
    time.AfterFunc(6*time.Hour, func() {
        failedCampaign := &DeliveryNotificationCampaign{
            AgentID:       "failed_delivery_agent",
            ShipmentIDs:   getAWBs(failedDeliveries),
            CallType:      "failed_delivery",
            MaxRetries:    3,
            RetryInterval: 1 * time.Hour,
        }
        failedCampaign.Execute(ctx)
    })

    return nil
}

Metrics and Analytics

Key Performance Indicators

type LogisticsMetrics struct {
    // Call Metrics
    TotalCalls           int           `json:"total_calls"`
    SuccessfulCalls      int           `json:"successful_calls"`
    FailedCalls          int           `json:"failed_calls"`
    AverageCallDuration  time.Duration `json:"avg_call_duration"`

    // Delivery Metrics
    DeliveriesConfirmed  int     `json:"deliveries_confirmed"`
    AddressesUpdated     int     `json:"addresses_updated"`
    DeliveriesRescheduled int    `json:"deliveries_rescheduled"`

    // Customer Reach
    CustomerReachRate    float64 `json:"customer_reach_rate"`    // Answered / Total
    FirstAttemptSuccess  float64 `json:"first_attempt_success"`  // Success on first try

    // Delivery Success
    DeliverySuccessRate  float64 `json:"delivery_success_rate"`  // Delivered / Attempted
    RTORate              float64 `json:"rto_rate"`               // Returns / Total

    // Language Distribution
    LanguageBreakdown    map[string]int `json:"language_breakdown"`

    // Time-based
    PeakCallHours        []int   `json:"peak_call_hours"`
    AverageResponseTime  float64 `json:"avg_response_time_ms"`
}

func CollectLogisticsMetrics(startDate, endDate time.Time) *LogisticsMetrics {
    metrics := &LogisticsMetrics{
        LanguageBreakdown: make(map[string]int),
    }

    calls := getCallsInRange(startDate, endDate)

    for _, call := range calls {
        metrics.TotalCalls++
        metrics.AverageCallDuration += call.Duration

        if call.Outcome == "success" {
            metrics.SuccessfulCalls++
        } else {
            metrics.FailedCalls++
        }

        // Track language usage
        metrics.LanguageBreakdown[call.Language]++

        // Track delivery outcomes
        for _, action := range call.Actions {
            switch action.Type {
            case "delivery_confirmed":
                metrics.DeliveriesConfirmed++
            case "address_updated":
                metrics.AddressesUpdated++
            case "delivery_rescheduled":
                metrics.DeliveriesRescheduled++
            }
        }
    }

    // Calculate rates
    if metrics.TotalCalls > 0 {
        metrics.CustomerReachRate = float64(metrics.SuccessfulCalls) / float64(metrics.TotalCalls) * 100
        metrics.AverageCallDuration /= time.Duration(metrics.TotalCalls)
    }

    // Calculate delivery success rate
    deliveries := getDeliveriesInRange(startDate, endDate)
    delivered := countByStatus(deliveries, "delivered")
    rto := countByStatus(deliveries, "rto")

    if len(deliveries) > 0 {
        metrics.DeliverySuccessRate = float64(delivered) / float64(len(deliveries)) * 100
        metrics.RTORate = float64(rto) / float64(len(deliveries)) * 100
    }

    return metrics
}

Dashboard Metrics

type DashboardData struct {
    // Real-time metrics
    ActiveCalls          int     `json:"active_calls"`
    CallsToday           int     `json:"calls_today"`
    SuccessRateToday     float64 `json:"success_rate_today"`

    // Delivery metrics
    PendingDeliveries    int     `json:"pending_deliveries"`
    OutForDeliveryToday  int     `json:"out_for_delivery"`
    DeliveredToday       int     `json:"delivered_today"`
    FailedAttemptsToday  int     `json:"failed_attempts_today"`

    // Trends (7-day)
    DailyCallVolume      []int     `json:"daily_call_volume"`
    DailySuccessRate     []float64 `json:"daily_success_rate"`
    DailyDeliveryRate    []float64 `json:"daily_delivery_rate"`
}

// Webhook handler for real-time updates
func handleDeliveryWebhook(w http.ResponseWriter, r *http.Request) {
    var event WebhookEvent
    json.NewDecoder(r.Body).Decode(&event)

    switch event.Type {
    case "call.ended":
        updateCallMetrics(event)
    case "delivery.rescheduled":
        updateDeliveryMetrics(event)
    case "address.updated":
        trackAddressUpdate(event)
    }

    w.WriteHeader(http.StatusOK)
}

Analytics Queries

-- Customer reach rate by time of day
SELECT
    EXTRACT(HOUR FROM created_at) as hour,
    COUNT(*) as total_calls,
    SUM(CASE WHEN outcome = 'answered' THEN 1 ELSE 0 END) as answered,
    ROUND(SUM(CASE WHEN outcome = 'answered' THEN 1 ELSE 0 END)::DECIMAL / COUNT(*) * 100, 2) as reach_rate
FROM voice_calls
WHERE call_type = 'delivery_notification'
    AND created_at > NOW() - INTERVAL '30 days'
GROUP BY EXTRACT(HOUR FROM created_at)
ORDER BY reach_rate DESC;

-- Delivery success rate by courier
SELECT
    courier,
    COUNT(*) as total_shipments,
    SUM(CASE WHEN status = 'delivered' THEN 1 ELSE 0 END) as delivered,
    SUM(CASE WHEN status = 'rto' THEN 1 ELSE 0 END) as rto,
    ROUND(SUM(CASE WHEN status = 'delivered' THEN 1 ELSE 0 END)::DECIMAL / COUNT(*) * 100, 2) as success_rate
FROM shipments
WHERE created_at > NOW() - INTERVAL '30 days'
GROUP BY courier
ORDER BY success_rate DESC;

-- Language preference by region
SELECT
    shipping_state,
    language,
    COUNT(*) as call_count
FROM voice_calls v
JOIN shipments s ON v.awb_number = s.awb_number
WHERE v.created_at > NOW() - INTERVAL '30 days'
GROUP BY shipping_state, language
ORDER BY shipping_state, call_count DESC;

Best Practices

1. Optimal Call Timing

// Best times to reach customers by segment
var OptimalCallTimes = map[string]TimeWindow{
    "residential": {Start: 10, End: 12, Evening: TimeWindow{Start: 18, End: 20}},
    "business":    {Start: 10, End: 17},
    "premium":     {Start: 9, End: 21},  // Flexible timing for premium customers
}

func GetBestCallTime(customer *Customer) time.Time {
    segment := customer.Segment
    if segment == "" {
        segment = "residential"
    }

    window := OptimalCallTimes[segment]
    now := time.Now()

    // If within morning window, call now
    if now.Hour() >= window.Start && now.Hour() < window.End {
        return now
    }

    // If evening window exists and we're in it
    if window.Evening.Start > 0 && now.Hour() >= window.Evening.Start && now.Hour() < window.Evening.End {
        return now
    }

    // Schedule for next available window
    nextWindow := time.Date(now.Year(), now.Month(), now.Day(), window.Start, 0, 0, 0, now.Location())
    if now.Hour() >= window.End {
        nextWindow = nextWindow.AddDate(0, 0, 1)
    }

    return nextWindow
}

2. Retry Strategy

type RetryConfig struct {
    MaxAttempts     int
    InitialDelay    time.Duration
    MaxDelay        time.Duration
    BackoffFactor   float64
    RetryableErrors []string
}

var DeliveryCallRetryConfig = RetryConfig{
    MaxAttempts:     3,
    InitialDelay:    30 * time.Minute,
    MaxDelay:        4 * time.Hour,
    BackoffFactor:   2.0,
    RetryableErrors: []string{"no_answer", "busy", "voicemail"},
}

func ShouldRetry(outcome string, attempt int) (bool, time.Duration) {
    config := DeliveryCallRetryConfig

    if attempt >= config.MaxAttempts {
        return false, 0
    }

    retryable := false
    for _, err := range config.RetryableErrors {
        if outcome == err {
            retryable = true
            break
        }
    }

    if !retryable {
        return false, 0
    }

    delay := config.InitialDelay * time.Duration(math.Pow(config.BackoffFactor, float64(attempt-1)))
    if delay > config.MaxDelay {
        delay = config.MaxDelay
    }

    return true, delay
}

3. Error Handling

func handleDeliveryToolError(toolName string, err error, session *Session) string {
    log.Error().Err(err).Str("tool", toolName).Msg("Tool execution failed")

    switch toolName {
    case "track_shipment":
        return "I'm having trouble looking up that shipment right now. " +
               "Can you please verify the tracking number, or would you like me to transfer you to an agent?"

    case "reschedule_delivery":
        return "I couldn't reschedule the delivery at the moment. " +
               "Let me transfer you to someone who can help with this."

    case "update_address":
        return "I'm unable to update the address right now. " +
               "For security, I'll need to transfer you to verify this change."

    default:
        return "I encountered an issue. Let me connect you with a human agent."
    }
}

Next Steps

  • Order Status Agent - Basic order tracking
  • Function Calling - Tool integration guide
  • Indian Languages - Regional language setup
  • Call Transfer - Human handoff
  • Webhooks - Post-call integrations
Previous
E-commerce
Next
Hyperlocal

On this page

  • Use Cases
  • 1. Shipment Tracking
  • 2. Delivery Scheduling
  • 3. Address Confirmation
  • 4. Failed Delivery Handling
  • 5. Proof of Delivery Collection
  • Agent Configuration
  • Standard Logistics Agent
  • Multilingual Configuration (Hindi + English)
  • System Prompt
  • Your Role
  • Conversation Guidelines
  • Response Style
  • Information Gathering
  • Handling Common Scenarios
  • Escalation Criteria
  • Localization
  • DO NOT
  • Tools for Delivery Management
  • 1. Track Shipment
  • 2. Reschedule Delivery
  • 3. Update Delivery Address
  • 4. Get Delivery Slots
  • 5. Collect Delivery Confirmation
  • Courier System Integration
  • Delhivery Integration
  • BlueDart Integration
  • Shiprocket Integration
  • Unified Courier Interface
  • Multi-Language Support
  • Regional Language Configuration
  • Language Detection and Switching
  • Localized Response Templates
  • Outbound Campaign Management
  • Delivery Notification Campaign
  • Batch Processing
  • Metrics and Analytics
  • Key Performance Indicators
  • Dashboard Metrics
  • Analytics Queries
  • Best Practices
  • 1. Optimal Call Timing
  • 2. Retry Strategy
  • 3. Error Handling
  • Next Steps

Stay Updated

Get the latest updates on AI voice technology, product releases, and exclusive resources.

Get Started

Try our products for free
AI Voice Agent
Build voice AI for calls
WhatsApp AI Bot
Automate WhatsApp chats
Website Chatbot
AI chat for websites
Edesy CRM
Manage leads & customers
Book a DemoCall UsEmail Us
Eedesy

Your all-in-one platform for digital innovation. We build AI-powered solutions that transform how businesses operate.

[email protected]+91 95475 31359

Products

  • AI Voice Assistant
  • WhatsApp Voice AI
  • WhatsApp Bot Builder
  • AI Website Chatbot
  • AI-SDR
  • Number Masking
  • Shopify Apps
  • View All Products

Solutions

  • For E-commerce
  • For Healthcare
  • For Real Estate
  • For Restaurants
  • For Appointments
  • View All Use Cases

Services

  • AI Chatbot Development
  • Voice AI Development
  • Shopify Development
  • SaaS Development
  • WhatsApp API Integration
  • View All Services

Resources

  • Documentation
  • Voice Agent Docs
  • API Reference
  • Number Masking API Docs
  • Blog
  • Changelog
  • Book a Demo

Company

  • About Us
  • Contact
  • Careers
  • Privacy Policy
  • Terms of Service

Products

  • AI Voice Assistant
  • WhatsApp Voice AI
  • WhatsApp Bot Builder
  • AI Website Chatbot
  • AI-SDR
  • Number Masking
  • Shopify Apps
  • View All Products

Solutions

  • For E-commerce
  • For Healthcare
  • For Real Estate
  • For Restaurants
  • For Appointments
  • View All Use Cases

Services

  • AI Chatbot Development
  • Voice AI Development
  • Shopify Development
  • SaaS Development
  • WhatsApp API Integration
  • View All Services

Resources

  • Documentation
  • Voice Agent Docs
  • API Reference
  • Number Masking API Docs
  • Blog
  • Changelog
  • Book a Demo

Company

  • About Us
  • Contact
  • Careers
  • Privacy Policy
  • Terms of Service
  • AI Voice Assistant
  • WhatsApp Voice AI
  • WhatsApp Bot Builder
  • AI Website Chatbot
  • AI-SDR
  • Number Masking
  • Shopify Apps
  • View All Products
  • For E-commerce
  • For Healthcare
  • For Real Estate
  • For Restaurants
  • For Appointments
  • View All Use Cases
  • AI Chatbot Development
  • Voice AI Development
  • Shopify Development
  • SaaS Development
  • WhatsApp API Integration
  • View All Services
  • Documentation
  • Voice Agent Docs
  • API Reference
  • Number Masking API Docs
  • Blog
  • Changelog
  • Book a Demo
  • About Us
  • Contact
  • Careers
  • Privacy Policy
  • Terms of Service

Popular Free Tools

Compress PDFMerge PDFPDF to WordGST CalculatorEMI CalculatorSIP CalculatorJSON FormatterBase64 EncoderImage CompressorQR Code GeneratorVoice AI ROI CalculatorAmazon FBA CalculatorAI Email WriterVideo to GIFPrivacy Policy GeneratorCRM ROI CalculatorMeeting Cost Calculator
Categories:PDF ToolsDeveloper ToolsFinance CalculatorsImage ToolsVideo ToolsAI Writing ToolsAudio ToolsWhatsApp ToolsDocument GeneratorsVoice AI ToolsE-commerce ToolsView All Tools

© 2026 Edesy Technology Labs Pvt Ltd

SSL Secured
99.9% Uptime