Skip to content

Guides

Connections

Your AI assistant (Claude, ChatGPT) and the voice agent in a call can both read Google Calendar and Apple Calendar and, once you approve it, update an existing event - and the voice agent on volai's own engine can also check a free slot and book the appointment right there in the call. With Apple, preserve opaque IDs and take care with recurring series.

What it can and can't do

  • Lists connected calendars and their events.
  • Changes the title, start or end of an existing event.
  • The voice agent on volai's own engine checks a free slot and books the appointment during the call.
  • Finds free slots and creates an appointment outside a call too, over REST and MCP.

Can't

  • Never deletes an event.
  • Doesn't search for free slots across more than one attendee.

Connecting a Google account

Connect a Google account in the portal under Connections (the Integrations item in the portal menu). Once the account is connected, the same API key sees the same thing over both REST and MCP - no separate sign-in needed.

You can disconnect an account in the portal or with REST DELETE /v1/integrations/{id}. REST disconnects it immediately and has no additional confirmation field, so call it only after the user has explicitly approved the action. MCP has no disconnect tool.

Apple Calendar

Connects with an app-specific password (not your regular Apple Account password) in the portal under Data and integrations. REST can also connect it with POST /v1/integrations and {provider: "apple-calendar", username, appPassword, calendarUrl?}; MCP does not accept credentials and can only use the account after it has been connected.

list_calendar_events and REST GET /v1/integrations/{id}/events support Apple Calendar. Use the returned opaque externalId unchanged as eventId for get_calendar_event and updates; it is not an iCalendar UID. A row with recurring: true represents the whole recurring series, and updating it changes the series master rather than one occurrence; individual exceptions are preserved.

calendarId must be one of the addresses returned by list_calendars - anything else is rejected with 400 calendar_invalid_calendar.

In-call scheduling

A voice agent on volai's own engine can check a free slot and book the appointment right during the phone call - this isn't a chat AI assistant, it's the voice agent conducting the call itself. Turn it on in the agent editor's Calendar tab: pick the connection, the calendar and the availability rules (windows per weekday, appointment length, a buffer between appointments, minimum notice, search horizon).

  • Works only on volai's own voice engine - on an agent hosted on ElevenLabs the setting is saved and waits for the automatic engine switch.
  • The agent never says what is written in the calendar - only whether a given time is free.
  • The caller's phone number is written into the event only when the agent knows it; a hidden number means no phone number on the event.
  • The same free-slot search and booking also work outside a call, over REST (POST .../availability, POST .../events) and MCP (find_free_slots, create_calendar_event).

Fakturoid and ABRA Flexi

This page covers calendars only. Fakturoid and ABRA Flexi connect in the same place (list_integrations/GET /v1/integrations, the portal's Data and integrations section), but reading invoices and using them in reminder Tasks has its own guide, Invoices.

Sequence for an agent

Updating an event is always six steps, in this order:

  • 1. list_integrations - connected calendars and their integrationId.
  • 2. list_calendars - the calendars of that connection and their calendarId.
  • 3. list_calendar_events, then get_calendar_event with the returned externalId as eventId - reads the event and its current sourceRevision.
  • 4. propose_calendar_update - prepares the change, writes nothing yet.
  • 5. User approval - the agent shows the original values and the proposal, and only then continues.
  • 6. confirm_calendar_update with confirm: true - only this step writes the change to Google/Apple.

REST equivalents: GET /v1/integrations, GET /v1/integrations/{id}/calendars, GET /v1/integrations/{id}/events, GET /v1/integrations/{id}/events/{eventId}, then POST /v1/integrations/{id}/events/{eventId}/propose with {calendarId, sourceRevision, patch}, and after approval PATCH /v1/integrations/{id}/events/{eventId} with the same values and confirm: true.

Errors

  • calendar_stale_revision - The event changed elsewhere in the meantime - read it again (get_calendar_event) and get the new proposal approved.
  • calendar_oauth_failed - Google rejected the sign-in - the connection needs to be redone in the portal.
  • calendar_unauthorized - The connection stopped being valid (access revoked, token expired) - reconnect the account.
  • calendar_confirmation_required - A write without confirm: true - only confirm the proposal after the user has approved it.
  • calendar_verification_failed - The write went through, but a fresh readback doesn't match what was sent - check the state manually, don't blindly retry.

The full table of every code is in the Calendar section of the REST API reference and in the MCP error reference.

Security

Access tokens for a Google or Apple account are never returned over REST or MCP and are stored encrypted. Send an Apple appPassword over REST only when the user has already stored it safely in an environment variable or a file they named - never ask for it in conversation or echo it back. Disconnect an integration in the portal or with REST DELETE /v1/integrations/{id} after explicit user approval; MCP does not offer disconnection.