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>.json with 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> then GET /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 listSlots and bookConsult tools 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 to gpt-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

ProviderError messageFix
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.