Custom scheduling — connect your own appointment system
What it is
Section titled “What it is”Custom scheduling lets the AI book appointments in your own system: a calendar that isn’t Calendly or GoHighLevel, a bespoke CRM, an internal agenda or any tool you can put a couple of endpoints in front of. For the lead, the experience is the same as with the other providers: they see the available slots inside the conversation, pick one, leave their name and email, and the appointment is created wherever you manage it.
All you need to expose is two HTTPS URLs:
- an Availability URL, which ZeroChats asks for the free slots within a date range;
- a Booking URL, which ZeroChats sends the chosen slot and the lead’s details to so it creates the appointment.
Everything else — when to offer times, how to present them, collecting the details and asking for confirmation — the AI does exactly as in Appointment scheduling. This page covers your side of it: setting up the tab and building the two endpoints.
How to set it up
Section titled “How to set it up”-
Go to Sales links in the side menu and open Schedule Automatically.
-
Open the Custom tab, next to the Calendly and GoHighLevel tabs. From there, the Endpoint documentation link brings you to this page.
-
Fill in the Availability URL and the Booking URL. Both must be public HTTPS URLs. A
localhostaddress, a private IP or an internal network is refused on save; to develop locally, expose your server through a tunnel (ngrok or similar) and use the URL it gives you. -
Add the API key (optional). If you set one, ZeroChats sends it on every request as
Authorization: Bearer <api key>, and your server can reject any call that doesn’t carry it. It’s stored encrypted and never shown again: after saving you’ll only see a hint with its last characters. To change it, type a new one; you can also remove it. -
Write the Scheduling condition. It’s the same natural-language rule as with Calendly or GoHighLevel: it tells the AI when to offer times. Follow the advice on how to write the condition.
-
Click Save endpoints.
-
Test both endpoints with Test availability and Test booking before letting the AI book with real leads. What each test does is explained below.
Testing the endpoints
Section titled “Testing the endpoints”- Test availability calls your Availability URL with a real date range and shows you how many slots came back plus a sample of them. If the number doesn’t match your calendar, check the date format and the range you’re reading.
- Test booking takes the first slot your Availability URL returns and calls your Booking URL with
"test": trueand test contact data: nameZeroChats Test, email[email protected]. If you declare questions, it answers the required ones with sample values (the first option, a test phone number or the textZeroChats Test). Your endpoint can do either of two things: create the appointment for real — and you cancel it afterwards — or, whentestistrue, just validate the request and answer 2xx without creating anything.
In both cases the result shows the HTTP status and the message your endpoint returned, so whoever builds it can debug without leaving ZeroChats.
How it works during the conversation
Section titled “How it works during the conversation”- The AI evaluates the scheduling condition on every message.
- When it’s met, it asks your Availability URL for slots and presents a few of them, spread across different days.
- It collects the lead’s name and email — and the answers to your questions, if you declare any — and asks for explicit confirmation.
- Once confirmed, it calls your Booking URL to create the appointment.
- The lead moves to Booked, same as with Calendly or GoHighLevel.
If one of your endpoints stops answering, the AI keeps replying to leads, just without offering times, and the problems panel in your account lets you know. As soon as the endpoint is back, scheduling resumes on its own.
Endpoint contract
Section titled “Endpoint contract”Common to both endpoints
Section titled “Common to both endpoints”POSTmethod with a JSON body.- Headers ZeroChats sends:
Content-Type: application/json,Accept: application/json,User-Agent: ZeroChats-Scheduling/1and, only if you configured an API key,Authorization: Bearer <api key>. - 10-second timeout. If your endpoint takes longer, the call counts as failed.
- No redirects. ZeroChats doesn’t follow a 3xx: it’s treated as an error. Point straight at the final URL.
- The response must be JSON. An empty body on booking is fine; HTML or plain text is not.
- All dates are ISO 8601 strings. ZeroChats sends instants in UTC (
2026-09-14T09:00:00.000Z). Your endpoint may answer with any ISO 8601 timestamp that carries an offset orZ. timezoneis the IANA time zone configured for your business (Europe/Madrid, for example). It’s sent for convenience, in case your system wants to compute slots in local time.
Availability endpoint
Section titled “Availability endpoint”This is the Availability URL. ZeroChats asks it for the free slots within a range.
{ "start": "2026-09-14T00:00:00.000Z", "end": "2026-09-20T23:59:59.000Z", "timezone": "Europe/Madrid"}ZeroChats asks for windows of up to 7 days, starting tomorrow. It only asks for later weeks when the earlier ones returned few slots, up to about one month ahead.
HTTP status 200 with the list of slots:
{ "slots": [ { "start": "2026-09-14T09:00:00.000Z" }, { "start": "2026-09-14T10:00:00.000Z" }, { "start": "2026-09-15T16:30:00.000Z" } ]}Response rules:
slotsis required. An empty list means no availability, and it’s a valid answer.- Each item needs
start. Any extra field you add is ignored. - Slots outside the requested window, or already in the past, are discarded.
- The AI doesn’t show the whole list: it proposes a few slots spread across different days.
If the endpoint answers with a non-2xx status, a non-JSON body or without a valid slots list, the AI skips scheduling for that reply and carries on with the conversation.
Questions before booking
Section titled “Questions before booking”If you want the AI to ask a few questions before booking — budget, type of business, phone… — declare them in the availability response with an optional questions field. The AI asks them inside the conversation, one per message and in the order of the list, doesn’t book until it has the required ones, and sends you the answers in the booking request (answers field).
{ "slots": [{ "start": "2026-09-14T09:00:00.000Z" }], "questions": [ { "id": "budget", "label": "What is your monthly budget?", "type": "single_select", "required": true, "options": ["Under €1,000", "€1,000 to €5,000", "Over €5,000"] }, { "id": "company", "label": "What is your company called?" } ]}| Field | What it is |
|---|---|
id | Required. Stable identifier of the question; it comes back unchanged in answers. |
label | Required. The question, as you want the AI to understand it. |
type | text (default), phone, email, number, date, single_select or multi_select. |
required | true if the booking can’t happen without it. Defaults to false. |
options | Allowed answers of single_select and multi_select. The AI maps what the lead says to one of them and sends you the exact text. |
- At most 20 questions. If
questionsdoesn’t have the shape described, the whole response is considered invalid and the AI doesn’t offer to book. - ZeroChats uses the questions of the first window it requests; return the same ones in every window.
- Test availability tells you how many questions it read.
Booking endpoint
Section titled “Booking endpoint”This is the Booking URL. ZeroChats calls it once the lead has confirmed a slot and left their details.
{ "start": "2026-09-14T09:00:00.000Z", "timezone": "Europe/Madrid", "name": "María García", "leadId": "b3f6c1f2-4d0e-4c8a-9d5e-1a2b3c4d5e6f", "test": false, "answers": [ { "id": "budget", "question": "What is your monthly budget?", "answer": "€1,000 to €5,000" } ]}| Field | What it is |
|---|---|
start | The chosen slot, as your availability endpoint returned it, normalized to UTC. |
timezone | The business time zone. |
name | The name the lead gave. |
email | The email the lead gave. |
leadId | The lead’s identifier in ZeroChats, the same one the ZeroChats API uses. It’s null on test bookings. |
test | true only when the request comes from the Test booking button. Use it to validate without creating anything. |
answers | Answers to the questions you declared: one { "id", "question", "answer" } per answered question. Empty list if you declared none. For multi_select, one option per line. |
HTTP status 200 or 201. The body may be empty or include optional links:
{ "cancelUrl": "https://...", "rescheduleUrl": "https://..." }Error codes
Section titled “Error codes”When the booking can’t be completed, answer with the status that best describes why. The AI reacts differently to each one:
| Status | Meaning for ZeroChats | What the AI does |
|---|---|---|
409 | The slot is no longer free. | Tells the lead and offers other times. |
422 | The contact data is invalid (typically the email). | Asks the lead to check their details. |
401 / 403 | The API key is missing or wrong. | Skips scheduling; the problem shows in the dashboard. |
400 | Rejected for another reason. | Tells the lead the booking didn’t go through and offers other times. |
5xx, timeout, non-JSON body | The system is unavailable. | Skips scheduling for now. |
Any error response may include { "message": "..." }. ZeroChats keeps it for the test result and for diagnostics, but never shows it to the lead: write it for whoever maintains the endpoint.
Example flow
Section titled “Example flow”A physiotherapy clinic manages its appointments in its own system and wants the AI to book first visits from Instagram.
- They set the condition: “when the lead asks about availability or requests a first-visit appointment”.
- A lead writes: “Do you have a slot this week for a first visit?”.
- ZeroChats calls the Availability URL with the next 7 days as the range. The system answers with the free slots across the therapists’ agendas.
- The AI proposes three times on different days. The lead picks Tuesday at 10:00 and leaves their name and email.
- ZeroChats calls the Booking URL with that slot and the details. The system checks it’s still free, creates the appointment and answers
201. - The AI confirms the appointment in the chat and the lead moves to Booked.
Had another patient taken that slot between steps 3 and 5, the system would answer 409 and the AI would offer alternatives without the lead having to start over.
Best practices
Section titled “Best practices”- Check the slot is still free before answering 2xx. Minutes can pass between the AI proposing it and the lead confirming; if it’s already taken, answer
409and the AI sorts it out on its own. - Make booking idempotent. If your own infrastructure retries a request, the same
leadIdandstartcombination shouldn’t create two appointments. - Respond fast. You have 10 seconds per call. If your system is slow at reading availability, cache the slots for a few minutes.
- Handle
test: truewithout side effects. Validate the request and answer 2xx without creating the appointment; that way you can test the integration as often as you like without cluttering your calendar. - Set the API key even if the URL is hard to guess. Without it, anyone who finds it can create appointments in your system.
- Return a useful
messageon errors. You’ll see it in the test results and it saves a lot of debugging time. - Test again with Test availability and Test booking every time you change the time zone, the URLs or the API key.