Integrations
Twilio, Cal.com, OpenAI, Vapi — what each one does and how it's verified.
Every integration is per-workspace. There is no platform-wide fallback — each workspace brings its own keys, stored encrypted at rest with AES-256-GCM and the platform's INTEGRATIONS_ENCRYPTION_KEY. Plaintext credentials never cross an Inngest step boundary.
Every connected card has a Verify button that hits the provider's API with the stored credentials and reports the outcome in a one-line pill.
Twilio (WhatsApp workspaces only)
- Account SID + Auth Token + From number (in
whatsapp:+44…format). - Powers outbound WhatsApp sends and inbound webhook signature verification.
- Verify call:
GET https://api.twilio.com/2010-04-01/Accounts/<sid>.jsonwith Basic auth. Pass = the account is reachable and active.
If Twilio isn't connected, the workspace can still accept form submissions but the agent has no transport — replies are dropped with a warning in the logs.
Vapi (voice workspaces only)
- API key (private), Assistant ID, Phone number ID.
- Plus a tool bearer token that Coachbot generates and shows in the Vapi card. The operator pastes it as
Authorization: Bearer <token>on every Vapi tool's server URL. - Verify call:
GET /assistant/<id>thenGET /phone-number/<id>— confirms the key works and both IDs resolve. The error message tells you which one is wrong.
Vapi handles voice/model/first-message; Coachbot owns the tools + the event webhook. See Voice setup.
Cal.com
- API key (
cal_live_…), Event Type ID (numeric), Timezone (IANA). - The agent's
listSlotsandbookConsulttools call Cal.com's v2 API directly. - Verify call:
GET /v2/event-types/<id>— confirms the key + event type id.
If Cal.com isn't connected, listSlots and bookConsult return { ok: false, error: "Cal.com not connected" } and the agent tells the lead it can't book right now (and escalates).
OpenAI
- API key (
sk-…), Model (optional; defaults togpt-4o). - Used by the WhatsApp chat agent for every reply, and by the dashboard chatbot.
- Verify call:
GET /v1/models— confirms the key is accepted.
Voice workspaces use Vapi's configured LLM (model + voice live in Vapi), so OpenAI is optional for voice.
Verify button — common failures
| Provider | Error message | Fix |
|---|---|---|
| Vapi | "rejected the API key (401/403)" | Re-copy the Private key (not public) from Vapi dashboard. |
| Vapi | "can't find assistant id …" | Typo in Assistant ID. Vapi → Assistants → top of page. |
| Vapi | "can't find phone number id …" | Typo in Phone Number ID. Vapi → Phone Numbers → row → ID column. |
| Cal.com | "rejected the API key" | Key is wrong or expired. Cal.com → Settings → Developer → API Keys → regenerate. |
| Cal.com | "can't find event type id …" | The event type doesn't exist (or belongs to a different Cal.com account). |
| OpenAI | "rejected the API key" | Key revoked or wrong project. |
| Twilio | "rejected the SID + Auth Token combination" | One or both are wrong. Use the Live credentials, not test. |
Encryption + the key recovery scenario
INTEGRATIONS_ENCRYPTION_KEY is a platform-wide env var. Lose it and every workspace's stored credentials become unrecoverable — the encrypted blobs in workspace_integrations.encryptedData can't be decrypted.
The Settings page refuses to save new credentials with a rose-coloured warning when the key is missing. Treat this env var with the same care as BETTER_AUTH_SECRET.