All integrations

Vapi

Vapi is an outbound AI-calling platform with native voicemail detection — the reason CenterLeap evaluates it against the Bland/Telnyx-bridge stack. It dials over our own Telnyx trunk (BYOC), so calls still show our number, and Vapi handles human-vs-machine classification and the after-beep message deposit itself.

Why Vapi

Carrier answering-machine detection (beep-only) is roughly a coin flip in production. Vapi runs a dedicated detection layer (audio + timing classification) and, on voicemail, waits for the beep before delivering a pre-recorded or spoken message — the “classify fast, then wait for the beep” architecture that reliable outbound systems use.

1. Get API keys

From the Vapi dashboard API Keys, copy the private key. Send it as Authorization: Bearer <key> on server-side requests only. The public key is for the browser Web SDK and is not used here. Base URL is https://api.vapi.ai (EU orgs: https://api.eu.vapi.ai).

2. Prepare Telnyx

On the Telnyx SIP connection that owns your caller-ID number, either allowlist Vapi's SBC IPs (IP-auth) or set credential auth and note the SIP username/password. Confirm the number is on a connection Vapi can originate from — otherwise trunk registration fails.

3. Register the BYOC trunk + number

CenterLeap exposes a one-time setup route that registers the Telnyx SIP trunk as a Vapi byo-sip-trunk credential and binds your number as a byo-phone-number. It returns the phone_number_id that becomes the outbound caller ID.

POST /api/vapi/setup
curl -s -X POST https://app.centerleap.com/api/vapi/setup \
  -H "Cookie: <owner/admin session>"
# → { "phone_number_id": "pn_xxx", "credential_id": "...", "status": "active" }

Gateways are created with inboundEnabled: false for an outbound-only trunk (leaving it true is a documented cause of gateway failures). Put the returned phone_number_id in VAPI_PHONE_NUMBER_ID.

4. Webhook secret

Vapi authenticates webhook deliveries with a shared secret it sends in the X-Vapi-Secret header. In the Vapi dashboard create a Bearer-token custom credential with header name X-Vapi-Secret and the Bearer prefix disabled, then set the same value in CenterLeap as VAPI_WEBHOOK_SECRET. CenterLeap does a constant-time compare on every webhook and tool call.

5. Voicemail detection

The assistant carries a voicemailDetection object and a voicemailMessage. Recommended:

assistant.voicemailDetection
{
  "provider": "vapi",
  "backoffPlan": { "startAtSeconds": 2, "frequencySeconds": 2.5, "maxRetries": 5 },
  "beepMaxAwaitSeconds": 12
}

On voicemail, Vapi waits up to beepMaxAwaitSeconds for the beep, then delivers voicemailMessage (plain text for TTS, or a URL to a pre-recorded .wav/.mp3). The call ends with endedReason: "voicemail", which CenterLeap sees on the end-of-call-report webhook.

6. Configure CenterLeap

VAPI_PRIVATE_API_KEYVapi private key (server only).
VAPI_PHONE_NUMBER_IDbyo-phone-number id from /api/vapi/setup.
VAPI_SARA_VOICE_ID11labs voiceId for the agent.
VAPI_WEBHOOK_SECRETShared secret sent as X-Vapi-Secret.
VAPI_WEBHOOK_BASE_URLPublic base URL for webhooks.
VAPI_TELNYX_SIP_USERNAME / _PASSWORDSetup only — omit for IP-auth trunks.
VAPI_TELNYX_GATEWAY_IPSComma-separated Telnyx SIP gateways.
VAPI_CALLER_E164The number to register as caller ID.

7. Place a test call

POST /api/vapi/calls
curl -s -X POST https://app.centerleap.com/api/vapi/calls \
  -H "Content-Type: application/json" \
  -H "Cookie: <owner/admin session>" \
  -d '{ "to_e164": "+1XXXXXXXXXX", "name": "Test" }'
# → { "call_id": "...", "status": "queued" }

Let it reach voicemail on the test, then confirm the end-of-call-report webhook logs endedReason: voicemail and the message landed cleanly after the beep — the head-to-head against the bridge stack.