Popular Integrations
Zoho CRM

Zoho CRM Integration

Automate SMS notifications for your sales and customer relationship management workflows. Send personalized messages when leads are created, deals are updated, or appointments are scheduled.

Use Case: Automatically notify leads and customers via SMS when important events occur in your Zoho CRM.

How It Works

Zoho CRM can trigger SMS notifications through webhook workflows when:

  • New leads are created
  • Deals move through pipeline stages
  • Appointments are scheduled or updated
  • Tasks are assigned to team members
  • Custom field values change
  • Follow-up reminders are due

Prerequisites

Before you begin, ensure you have:

  • An active SMSLeopard account with API credentials (Get started here)
  • Zoho CRM account with workflow automation access
  • A webhook endpoint to receive Zoho notifications

Integration Steps

Step 1: Set Up Webhook Endpoint

Create an endpoint to receive webhooks from Zoho CRM:

const express = require('express');
const axios = require('axios');
const app = express();
 
app.use(express.json());
 
// Zoho CRM webhook endpoint
app.post('/zoho/webhook', async (req, res) => {
try {
const { module, action, data } = req.body;
 
    console.log('Zoho webhook received:', { module, action });
 
    // Handle different modules and actions
    if (module === 'Leads' && action === 'create') {
      await handleNewLead(data);
    } else if (module === 'Deals' && action === 'update') {
      await handleDealUpdate(data);
    } else if (module === 'Events' && action === 'create') {
      await handleAppointment(data);
    }
 
    res.json({ success: true, message: 'Webhook processed' });
 
} catch (error) {
console.error('Webhook processing error:', error);
res.status(500).json({ success: false, error: error.message });
}
});
 
// Handle new lead
async function handleNewLead(lead) {
const phoneNumber = lead.Phone || lead.Mobile;
const firstName = lead.First_Name;
const lastName = lead.Last_Name;
 
if (!phoneNumber) {
console.log('No phone number found for lead');
return;
}
 
const message = `Hi ${firstName}, thank you for your interest! Our team will contact you shortly to discuss how we can help.`;
 
await sendSMS(phoneNumber, message);
}
 
// Handle deal stage update
async function handleDealUpdate(deal) {
if (deal.Stage === 'Closed Won') {
const contactPhone = deal.Contact_Phone || deal.Contact_Mobile;
const dealName = deal.Deal_Name;
const amount = deal.Amount;
 
    if (contactPhone) {
      const message = `Congratulations! Your deal "${dealName}" worth $${amount} has been confirmed. We're excited to work with you!`;
      await sendSMS(contactPhone, message);
    }
 
}
}
 
// Handle appointment
async function handleAppointment(event) {
const attendeePhone = event.Participant_Phone;
const eventTitle = event.Event_Title;
const startTime = new Date(event.Start_DateTime);
 
if (attendeePhone) {
const formattedTime = startTime.toLocaleString('en-US', {
dateStyle: 'medium',
timeStyle: 'short'
});
 
    const message = `Appointment confirmed: ${eventTitle} on ${formattedTime}. We look forward to meeting you!`;
    await sendSMS(attendeePhone, message);
 
}
}
 
// Send SMS using SMSLeopard API
async function sendSMS(phoneNumber, message) {
const apiKey = process.env.SMSLEOPARD_API_KEY;
const apiSecret = process.env.SMSLEOPARD_API_SECRET;
const sourceAddress = process.env.SENDER_ID;
 
const formattedPhone = formatPhoneNumber(phoneNumber);
 
try {
const response = await axios.post(
'https://api.smsleopard.com/v1/sms/send',
{
source: sourceAddress,
destination: [formattedPhone],
message: message
},
{
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}:${apiSecret}`
}
}
);
 
    console.log('SMS sent successfully:', response.data);
    return response.data;
 
} catch (error) {
console.error('Error sending SMS:', error.response?.data || error.message);
throw error;
}
}
 
function formatPhoneNumber(phone) {
// Remove spaces and special characters
phone = phone.replace(/[\s\-\(\)]/g, '');
 
// Add country code if missing (example for Kenya)
if (phone.startsWith('0')) {
return '254' + phone.substring(1);
} else if (phone.startsWith('+')) {
return phone.substring(1);
}
 
return phone;
}
 
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Zoho webhook server running on port ${PORT}`);
});
 

Step 2: Configure Zoho CRM Webhook

  1. Log in to Zoho CRM and navigate to Setup > Automation > Workflows
  2. Click Create Rule and select the module (Leads, Deals, Events, etc.)
  3. Set up your trigger conditions (e.g., "When a record is created")
  4. Add a Webhook action:
    • URL: Your webhook endpoint (e.g., https://yourdomain.com/zoho/webhook)
    • Method: POST
    • Format: JSON
  5. Map the fields you want to send to your webhook

Step 3: Test Your Integration

Create a test record in Zoho CRM to verify the webhook triggers and SMS sends correctly.

Use Cases

Lead Nurturing

Send immediate follow-up messages to new leads:

const leadTemplates = {
  newLead: (name) =>
    `Hi ${name}, thanks for reaching out! We've received your inquiry and will get back to you within 24 hours.`,
 
  leadQualified: (name, product) =>
    `Hi ${name}, great news! You qualify for our ${product}. Our sales team will call you today.`,
 
  followUp: (name, days) =>
    `Hi ${name}, just checking in! It's been ${days} days since we last spoke. Any questions we can answer?`
};

Deal Stage Notifications

Keep customers informed as deals progress:

const dealTemplates = {
  proposal: (name, dealName) =>
    `Hi ${name}, your proposal for "${dealName}" is ready for review. Check your email for details.`,
 
  negotiation: (name) =>
    `Hi ${name}, we're reviewing your requirements and will send you a revised offer shortly.`,
 
  won: (name, amount) =>
    `Congratulations ${name}! Your deal worth $${amount} is confirmed. Welcome aboard!`,
 
  lost: (name) =>
    `Hi ${name}, we appreciate you considering us. We'd love to work with you in the future!`,
};

Appointment Reminders

Send reminders before scheduled meetings:

const cron = require('node-cron');
 
// Send reminders 24 hours before appointments
cron.schedule('0 9 \* \* \*', async () => {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
 
// Fetch appointments from Zoho CRM API
const appointments = await fetchTomorrowAppointments(tomorrow);
 
for (const appointment of appointments) {
const message = `Reminder: You have an appointment tomorrow at ${appointment.time} for ${appointment.title}. See you then!`;
await sendSMS(appointment.phone, message);
}
});
 
async function fetchTomorrowAppointments(date) {
// Implement Zoho CRM API call to fetch appointments
// This is a placeholder - actual implementation depends on Zoho API
return [];
}
 

Advanced Features

Custom Field Triggers

Send SMS based on custom field changes:

app.post('/zoho/webhook', async (req, res) => {
  const { data, previous_data } = req.body;
 
  // Check if payment status changed to "Paid"
  if (data.Payment_Status === 'Paid' && previous_data.Payment_Status !== 'Paid') {
    const message = `Payment received! Your invoice #${data.Invoice_Number} has been marked as paid. Thank you!`;
    await sendSMS(data.Contact_Phone, message);
  }
 
  res.json({ success: true });
});

Multi-language Support

Send messages in the customer's preferred language:

const messages = {
  en: {
    welcome: (name) => `Hi ${name}, welcome! We're excited to work with you.`,
    appointment: (time) => `Appointment confirmed for ${time}. See you then!`,
  },
  sw: {
    welcome: (name) =>
      `Habari ${name}, karibu! Tunafurahi kufanya kazi na wewe.`,
    appointment: (time) => `Miadi imethibitishwa kwa ${time}. Tutaonana!`,
  },
};
 
function getLocalizedMessage(language, key, ...args) {
  const template = messages[language]?.[key] || messages.en[key];
  return template(...args);
}

Best Practices

  • Always validate webhook authenticity using Zoho's webhook validation tokens
  • Store phone numbers in E.164 format in Zoho CRM for consistency
  • Implement retry logic for failed SMS sends
  • Log all webhook events for debugging and audit purposes
  • Use custom fields in Zoho to store SMS delivery status
  • Respect opt-out preferences stored in your CRM
  • Test with staging environment before going live

Monitoring

Track your integration performance:

// Log webhook events to database
async function logWebhookEvent(module, action, recordId, status) {
  await db.webhookLogs.create({
    module,
    action,
    recordId,
    status,
    timestamp: new Date(),
  });
}
 
// Track SMS delivery
async function trackSMSDelivery(phone, message, response) {
  await db.smsLogs.create({
    phone,
    message,
    deliveryStatus: response.status,
    messageId: response.messageId,
    timestamp: new Date(),
  });
}

Refer to Zoho CRM Webhook Documentation (opens in a new tab) for more information.