Skip to main content

Telegram Bot Integration

Create a Telegram bot that customers can chat with to check your availability and book appointments, plus receive real-time booking notifications in a Telegram channel or group.

What You'll Build

A Telegram bot that handles:

  1. /services— list available services with prices
  2. /slots— check available times for a date
  3. /book— book an appointment

Plus webhook-driven notifications that post to a Telegram chat when new bookings come in.

Prerequisites

  • A Telegram account.
  • A Reservly account with an API key (write scope). Go to Settings → Integrations to generate one.

Step 1: Create a Bot with BotFather

Open Telegram and search for @BotFather. Send these commands:

BotFather commands
/newbot
Name: Luxe Salon Bot
Username: luxe_salon_bot
text

BotFather will reply with your bot token (looks like 123456:ABC-DEF1234...). Save this — you'll need it in the next step.

Step 2: Build the Bot (Node.js)

Create a simple Node.js project that listens for commands and calls Reservly's API:

Project setup
mkdir reservly-telegram-bot && cd reservly-telegram-bot
npm init -y
npm install node-telegram-bot-api
bash
index.js
const TelegramBot = require('node-telegram-bot-api');

const BOT_TOKEN = 'YOUR_BOT_TOKEN';
const API_BASE = 'https://reservly.io/api/public/luxe-salon';
const API_KEY = 'rsvly_YOUR_KEY';

const bot = new TelegramBot(BOT_TOKEN, { polling: true });

// /start — Welcome message
bot.onText(/\/start/, (msg) => {
  bot.sendMessage(
    msg.chat.id,
    'Welcome to Luxe Salon & Spa! Here\'s what I can do:\n\n' +
      '/services — View our services\n' +
      '/slots YYYY-MM-DD — Check availability for a date\n' +
      '/book ServiceName YYYY-MM-DD HH:MM — Book an appointment'
  );
});

// /services — List all services
bot.onText(/\/services/, async (msg) => {
  const res = await fetch(`${API_BASE}/services`);
  const data = await res.json();
  const text = data.services
    .map((s) => `• ${s.name} — $${s.price} (${s.duration_minutes} min)`)
    .join('\n');
  bot.sendMessage(msg.chat.id, `Available services:\n\n${text}`);
});

// /slots YYYY-MM-DD — Check availability
bot.onText(/\/slots (\S+)/, async (msg, match) => {
  const date = match[1];
  // For simplicity, show slots for all services
  const res = await fetch(`${API_BASE}/slots?date=${date}`);
  const data = await res.json();
  if (!data.slots || data.slots.length === 0) {
    bot.sendMessage(msg.chat.id, `No available slots for ${date}.`);
    return;
  }
  const text = data.slots
    .filter((s) => s.available)
    .map((s) => `• ${s.time}`)
    .join('\n');
  bot.sendMessage(
    msg.chat.id,
    `Available slots for ${date}:\n\n${text}\n\nUse /book ServiceName ${date} HH:MM to book.`
  );
});

// /book ServiceName YYYY-MM-DD HH:MM
bot.onText(/\/book (.+) (\d{4}-\d{2}-\d{2}) (\d{2}:\d{2})/, async (msg, match) => {
  const serviceName = match[1];
  const date = match[2];
  const time = match[3];

  // Look up the service ID by name
  const servicesRes = await fetch(`${API_BASE}/services`);
  const servicesData = await servicesRes.json();
  const service = servicesData.services.find(
    (s) => s.name.toLowerCase() === serviceName.toLowerCase()
  );

  if (!service) {
    bot.sendMessage(msg.chat.id, `Service "${serviceName}" not found. Use /services to see options.`);
    return;
  }

  // Book the appointment
  const bookRes = await fetch(`${API_BASE}/book`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${API_KEY}`,
    },
    body: JSON.stringify({
      service_ids: [service.id],
      date,
      time,
      customer_name: `${msg.from.first_name} ${msg.from.last_name || ''}`.trim(),
      customer_email: 'telegram-user@placeholder.com',
      source: 'telegram',
    }),
  });

  const bookData = await bookRes.json();

  if (bookData.booking) {
    bot.sendMessage(
      msg.chat.id,
      `Booked! Here are your details:\n\n` +
        `Service: ${service.name}\n` +
        `Date: ${date}\n` +
        `Time: ${time}\n\n` +
        `You'll receive a confirmation email shortly.`
    );
  } else {
    bot.sendMessage(msg.chat.id, 'Sorry, something went wrong. Please try again.');
  }
});

console.log('Luxe Salon Bot is running...');
javascript

Replace YOUR_BOT_TOKEN with the token from BotFather, rsvly_YOUR_KEY with your Reservly API key, and luxe-salon with your business slug.

Step 3: Add Webhook Notifications

To receive real-time booking notifications in a Telegram chat, set up a Reservly webhook that posts to your bot's server:

  1. Add a webhook endpoint to your bot server that receives POST requests from Reservly.
  2. In Reservly, go to Settings → Integrations → Webhooksand create a webhook pointing to your bot's URL (e.g., https://your-server.com/webhook).
  3. Select the booking.created event.
Webhook handler (add to index.js)
const http = require('http');

const NOTIFICATION_CHAT_ID = 'YOUR_CHAT_ID'; // Your personal or group chat ID

const server = http.createServer((req, res) => {
  if (req.method === 'POST' && req.url === '/webhook') {
    let body = '';
    req.on('data', (chunk) => (body += chunk));
    req.on('end', () => {
      const payload = JSON.parse(body);
      const b = payload.booking;
      bot.sendMessage(
        NOTIFICATION_CHAT_ID,
        `New booking!\n\n` +
          `Customer: ${b.customer_name}\n` +
          `Service: ${b.service_name}\n` +
          `Date: ${b.date}\n` +
          `Time: ${b.time}`
      );
      res.writeHead(200);
      res.end('OK');
    });
  }
});

server.listen(3001, () => console.log('Webhook server on port 3001'));
javascript

Step 4: Deploy Your Bot

The bot needs to run continuously. Popular hosting options:

  • Railway — free tier, deploy from GitHub
  • Render — free tier, auto-deploy
  • Any VPS (DigitalOcean, Hetzner) with pm2 or Docker

Alternative: No-Code with N8N

If you prefer not to write code, you can build the same bot using N8N:

  1. Create an N8N workflow with a Telegram Trigger node (listens for messages to your bot).
  2. Add a Switch node to route by command (/services, /slots, /book).
  3. For each route, add an HTTP Request node that calls the corresponding Reservly API endpoint.
  4. Add a Telegram → Send Message node to reply with the formatted response.

See the N8N integration guide for general setup instructions.

Testing

  1. Start your bot with node index.js.
  2. Open Telegram and search for your bot by its username.
  3. Send /start to see the welcome message.
  4. Send /services to verify it lists your services.
  5. Send /slots 2026-04-05 to check availability.
  6. Send /book Haircut 2026-04-05 10:00 to make a booking.
  7. Check your Reservly dashboard — the booking should appear with the source "telegram".

Example Use Case

Luxe Salon & Spa creates a Telegram bot and shares the link (t.me/luxe_salon_bot) in their bio and on their website. Customers in regions where Telegram is popular can book appointments without downloading another app. The salon owner also adds the bot to a staff group chat so everyone gets instant notifications when a new booking comes in.

Next Steps