DEV Community

sy int999
sy int999

Posted on

Add an FAQ bot and appointment booking to any website with 3 API calls

Most small-business sites need the same two things: answer the five questions everyone asks ("what are your hours?", "how much is…?") and let people book. Building a booking backend for every client is a waste of a week. Here's how to do both with three HTTP calls, using CallChatSyn's API (free for the first 1,000 businesses).

0. Try it right now (no account)

There's a public demo key, ccs_demo_public, that answers as a demo business. Bookings made with it are dry runs, so nothing is saved:

curl https://callchatsyn.com/api/v1/answer \
  -H "Authorization: Bearer ccs_demo_public" \
  -H "Content-Type: application/json" \
  -d '{"message": "Where are you located?"}'
# {"intent":"faq","lang":"en","matched":true,"reply":"We're at our main location, details on our website."}
Enter fullscreen mode Exit fullscreen mode

When you want your own FAQs and real bookings, get your own key:

1. Set up the business (2 minutes)

  1. Create an account at callchatsyn.com and confirm your email.
  2. Add a few FAQs (Dashboard → FAQs) and your opening hours (Dashboard → Appointments). Set your time zone in Dashboard → Booking Page.
  3. Dashboard → Developers → Claim founder API access, then Create API key. Copy it once; it's not shown again.

Keep the key on your server. Never put it in browser code.

2. Answer a question

curl https://callchatsyn.com/api/v1/answer \
  -H "Authorization: Bearer $CCS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": "What are your opening hours?"}'
# {"intent":"faq","lang":"en","matched":true,"reply":"We're open every day, 9am to 9pm."}
Enter fullscreen mode Exit fullscreen mode

matched: false means no FAQ fit and the reply is a polite fallback, so you can hand off to a human. It also recognises booking requests (intent: "appointment"), order-status questions and "talk to a person", in English and Chinese.

3. List open times and book one

curl https://callchatsyn.com/api/v1/slots -H "Authorization: Bearer $CCS_KEY"
# {"slots":[{"start":"2026-10-05T01:00:00.000Z","label":"Mon, Oct 5, 9:00 AM"}],"services":["Haircut"],"locations":["Main St"]}

curl https://callchatsyn.com/api/v1/bookings \
  -H "Authorization: Bearer $CCS_KEY" -H "Content-Type: application/json" \
  -d '{"start":"2026-10-05T01:00:00.000Z","service":"Haircut","name":"Ana","email":"ana@example.com"}'
# 201 {"booked":true,"start":"2026-10-05T01:00:00.000Z","label":"Mon, Oct 5, 9:00 AM"}
Enter fullscreen mode Exit fullscreen mode

Only times the business actually offers can be booked; a time taken a second earlier returns 409. Labels are already in the business's own time zone.

4. A tiny website widget (server route + 30 lines of JS)

Your server holds the key and forwards the question (Express example):

// server.js
app.post("/chat", express.json(), async (req, res) => {
  const r = await fetch("https://callchatsyn.com/api/v1/answer", {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.CCS_KEY}`, "Content-Type": "application/json" },
    body: JSON.stringify({ message: String(req.body.message || "").slice(0, 2000) }),
  });
  res.status(r.status).json(await r.json());
});
Enter fullscreen mode Exit fullscreen mode

The page talks only to your server:

<div id="faq-bot">
  <div id="log"></div>
  <form id="ask"><input name="q" placeholder="Ask us anything" required /><button>Send</button></form>
</div>
<script>
  const log = document.getElementById("log");
  const say = (who, text) => {
    const p = document.createElement("p");
    p.textContent = `${who}: ${text}`;
    log.appendChild(p);
  };
  document.getElementById("ask").addEventListener("submit", async (e) => {
    e.preventDefault();
    const q = e.target.q.value;
    e.target.reset();
    say("You", q);
    const r = await fetch("/chat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: q }) });
    const data = await r.json();
    say("Bot", data.reply ?? "Sorry, something went wrong.");
    if (data.intent === "appointment") say("Bot", "Pick a time on our booking page, or ask me for the next available slot.");
  });
</script>
Enter fullscreen mode Exit fullscreen mode

Limits, honestly

  • Answers are rule-based FAQ matching, not a free-form LLM: instant, predictable, and close to free to run (which is why there's a free tier at all).
  • Founder accounts get 100 calls a day and 2,000 a month per business.
  • WhatsApp and phone/voice answering are the paid part of CallChatSyn.

Full docs and the OpenAPI spec: callchatsyn.com/developers. Feedback welcome in the comments, especially from people who build sites for local businesses.

Top comments (0)