fonio.ai — static integration (recommended)
fonio.ai is an AI voice agent that takes inbound and outbound calls. This guide wires it up to RocketLead so the agent can check availability, book appointments, and create lead entries — all without a human in the loop.
This is the static pattern: you hardcode the RocketLead IDs (tableId, leadStateId, calendarId, appointmentTypeId, optional resourceId) per location in a fonio variable map. The agent picks the right IDs based on which location the caller wants, then calls only three endpoints. Fewer round-trips, simpler conversation flows, and fewer moving parts.
For organizations with many locations or frequently-changing schedules, see the dynamic integration instead.
Architecture
Section titled “Architecture”[Caller] → [fonio.ai voice agent] → HTTP actions → [RocketLead Connect API]fonio.ai actions are configured in their dashboard as HTTP requests. We’ll define three:
- Check availability — fetch bookable slots for the requested day.
- Create lead — push the caller’s contact info into the Lead Pool.
- Book appointment — reserve a slot and link it to the lead.
Prerequisites
Section titled “Prerequisites”- A fonio.ai account with a configured voice agent.
- A RocketLead Connect API token with
writescope. Generate one in Settings → API Tokens (the secret is shown once — copy it). - The IDs you’re going to hardcode (next section).
Step 0 — Build the location map
Section titled “Step 0 — Build the location map”Look up your IDs once and paste them into a fonio variable. The agent picks the right block based on which location the caller mentions.
// fonio.ai variable: locationMap{ "Bernau": { "tableId": "tbl_...", "leadStateId": "ls_default", "calendarId": "cal_bernau", "appointmentTypeId": "apt_trial_session", "resourceId": "res_trainer_a" }, "Ahrensfelde": { "tableId": "tbl_...", "leadStateId": "ls_default", "calendarId": "cal_ahrensfelde", "appointmentTypeId": "apt_trial_session" }}resourceId is optional — leave it out and the agent gets availability across every resource on the calendar.
To find these IDs, run:
# Tables (Lead Pools) and their default lead statescurl -H "Authorization: Bearer $RL_TOKEN" \ https://api.rocketlead.io/connect/tables/
# Pick one, then fetch its lead states:curl -H "Authorization: Bearer $RL_TOKEN" \ https://api.rocketlead.io/connect/tables/<TABLE_ID>
# Calendarscurl -H "Authorization: Bearer $RL_TOKEN" \ https://api.rocketlead.io/connect/calendar/
# Appointment typescurl -H "Authorization: Bearer $RL_TOKEN" \ https://api.rocketlead.io/connect/appointment_types/
# Optional: resourcescurl -H "Authorization: Bearer $RL_TOKEN" \ https://api.rocketlead.io/connect/resources/Save the values. You’ll re-run these whenever you add a location or change a schedule type — that’s the trade-off of the static pattern.
Step 1 — Check availability
Section titled “Step 1 — Check availability”In the fonio dashboard, create an HTTP action checkAvailability:
- Method:
GET - URL:
Appendhttps://api.rocketlead.io/connect/availability/?calendarId={calendarId}&appointmentTypeId={appointmentTypeId}&start={start}&end={end}
&resourceId={resourceId}if you have one in the location map. - Headers:
Authorization: Bearer {RL_TOKEN}
- Inputs from the agent:
calendarId,appointmentTypeId,resourceId— pulled fromlocationMap[location].start/end— derived from the caller’s stated preference (e.g., “morgen vormittag” →09:00–12:00next day in the calendar’s timezone).
Response: see Availability reference. Filter data[] by available: true and pick a slot.
In the fonio response template:
“I have openings at {{ data[0].startDateTime | localTime }} and {{ data[1].startDateTime | localTime }}. Which works for you?”
Step 2 — Create the lead
Section titled “Step 2 — Create the lead”Action createLead:
- Method:
POST - URL:
https://api.rocketlead.io/connect/table_entries/ - Headers:
Authorization: Bearer {RL_TOKEN}Content-Type: application/json
- Body:
{"tableId": "{tableId}","leadStateId": "{leadStateId}","data": {"firstName": "{firstName}","lastName": "{lastName}","phone": "{phone}","email": "{email}"}}
tableId and leadStateId come from locationMap[location]. The four data fields are collected from the caller during the conversation.
Response: the created TableEntry. Save id as leadId for the next step.
Step 3 — Book the appointment
Section titled “Step 3 — Book the appointment”Action bookAppointment:
- Method:
POST - URL:
https://api.rocketlead.io/connect/calendar_bookings/ - Body:
{"calendarId": "{calendarId}","appointmentTypeId": "{appointmentTypeId}","resourceId": "{resourceId}","resourceSlotId": "{resourceSlotId}","startDateTime": "{startDateTime}","endDateTime": "{endDateTime}","tableEntryId": "{leadId}","name": "{firstName} {lastName}"}
resourceId, resourceSlotId, startDateTime, endDateTime come straight from the slot the agent picked in step 1. tableEntryId is the lead created in step 2.
What happens after the call
Section titled “What happens after the call”| Event | When | Use |
|---|---|---|
table.entry.added | Lead created | Confirmation SMS, CRM sync, sales notification |
calendar.appointment.booked | Booking created | Calendar invite, resource notification |
calendar.appointment.hasStarted | At appointment start | Staff dashboard reminder |
calendar.appointment.hasEnded | At appointment end | Follow-up flow |
Wire any of these up in Automations in the console. See the full event catalog in Automation triggers.
Trade-offs
Section titled “Trade-offs”| Static (this guide) | Dynamic | |
|---|---|---|
| API calls per booking | 3 | 6+ |
| Latency | Lowest | Higher (cascading lookups) |
| Setup complexity | Low — one variable map | Higher — six actions |
| Maintenance | Manual when IDs change | Automatic |
| Best for | Single-org, stable schedules | Multi-org, frequently-changing schedules |
The static pattern wins for most fonio.ai deployments. Switch to dynamic only when you actually need it.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause |
|---|---|
401 Unauthorized | Token missing Bearer prefix or wrong scope. |
403 Forbidden on POST | Token has read only — issue a new token with write. |
400 The selected time slot is no longer available | Race between availability fetch and booking — retry with fresh availability. |
400 Invalid combination (booking) | Resource isn’t mapped to the appointment type, or appointment type isn’t on this calendar. Check via Lookups. |
| Agent picks wrong calendar | Variable map key (location name) doesn’t match what the agent extracts from the conversation. Check fonio’s intent training. |
Related
Section titled “Related”- fonio.ai — dynamic integration — for cases where hardcoded IDs aren’t an option.
- Connect API → Workflows → Book a slot after lead capture.
- Availability resource.
- Bookings resource.
- Race conditions.