Skip to content

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.

[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:

  1. Check availability — fetch bookable slots for the requested day.
  2. Create lead — push the caller’s contact info into the Lead Pool.
  3. Book appointment — reserve a slot and link it to the lead.
  • A fonio.ai account with a configured voice agent.
  • A RocketLead Connect API token with write scope. Generate one in Settings → API Tokens (the secret is shown once — copy it).
  • The IDs you’re going to hardcode (next section).

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:

Terminal window
# Tables (Lead Pools) and their default lead states
curl -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>
# Calendars
curl -H "Authorization: Bearer $RL_TOKEN" \
https://api.rocketlead.io/connect/calendar/
# Appointment types
curl -H "Authorization: Bearer $RL_TOKEN" \
https://api.rocketlead.io/connect/appointment_types/
# Optional: resources
curl -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.

In the fonio dashboard, create an HTTP action checkAvailability:

  • Method: GET
  • URL:
    https://api.rocketlead.io/connect/availability/?calendarId={calendarId}&appointmentTypeId={appointmentTypeId}&start={start}&end={end}
    Append &resourceId={resourceId} if you have one in the location map.
  • Headers:
    Authorization: Bearer {RL_TOKEN}
  • Inputs from the agent:
    • calendarId, appointmentTypeId, resourceId — pulled from locationMap[location].
    • start / end — derived from the caller’s stated preference (e.g., “morgen vormittag” → 09:00–12:00 next 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?”

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.

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.

EventWhenUse
table.entry.addedLead createdConfirmation SMS, CRM sync, sales notification
calendar.appointment.bookedBooking createdCalendar invite, resource notification
calendar.appointment.hasStartedAt appointment startStaff dashboard reminder
calendar.appointment.hasEndedAt appointment endFollow-up flow

Wire any of these up in Automations in the console. See the full event catalog in Automation triggers.

Static (this guide)Dynamic
API calls per booking36+
LatencyLowestHigher (cascading lookups)
Setup complexityLow — one variable mapHigher — six actions
MaintenanceManual when IDs changeAutomatic
Best forSingle-org, stable schedulesMulti-org, frequently-changing schedules

The static pattern wins for most fonio.ai deployments. Switch to dynamic only when you actually need it.

SymptomCause
401 UnauthorizedToken missing Bearer prefix or wrong scope.
403 Forbidden on POSTToken has read only — issue a new token with write.
400 The selected time slot is no longer availableRace 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 calendarVariable map key (location name) doesn’t match what the agent extracts from the conversation. Check fonio’s intent training.