Phone System Integration

Connect an inbound voice agent to an advanced phone system (PBX) such as 3CX. Your phone system can send caller context — like IVR menu selections — to the agent right before it bridges the call, and retrieve call results (telemetry plus values the agent collected) after the call ends.

What you'll need

How it works

sequenceDiagram
    participant C as Caller
    participant P as Phone system (PBX)
    participant K as KarmaFlow
    participant A as Voice agent
    C->>P: Dials in, makes IVR selections
    P->>K: POST pre-call webhook (caller, IVR data)
    P->>A: Bridges the call to the agent's number
    K->>A: Injects the pre-call context into the agent
    A->>A: Collects configured values during the call
    A->>C: Ends the call (only after required values are saved)
    P->>K: POST post-call webhook
    K->>P: Call telemetry + collected values in the response

Enable the integration

  1. Go to Agents → Voice Agents and open your inbound agent.
  2. Open the Phone System tab.
  3. Turn on Enable Phone System Integration.
  4. Click Save. Saving generates the webhook URLs shown in the sections below.

Send caller context to the agent (pre-call webhook)

  1. In the Pre-call webhook card, turn the toggle on and click Save.
  2. Copy the Webhook URL (POST) with the Copy button and configure your phone system to POST its JSON payload there right before transferring the call.
  1. Set Caller number field (dot-path) to the payload field that holds the caller's number (for example caller or call.from). KarmaFlow matches the webhook to the incoming call using this number.
  2. Under Values sent to the agent, click Add field for each payload value the agent should see:
    • Payload path — dot-path into the JSON body, e.g. ivr.selection
    • Label — how it appears in the agent's context, e.g. IVR Selection
    • Placeholder — a key you can reference in the agent's instructions as {{ivr_selection}}
  3. Optionally require authentication with Header secret (a shared secret in a request header) or HMAC signature (an HMAC-SHA256 signature of the raw body). Each secret field has a Generate button that fills in a strong random secret and reveals it — copy it into your phone system's webhook configuration, then save the agent. The show/hide and copy buttons work on any secret you enter.

When the call arrives, the mapped values appear to the agent as a "Phone system context" block, and any {{placeholder}} keys in the agent's instructions resolve to the received values. If no webhook arrives before the call, the call proceeds normally without the context.

Caller-ID mismatch: some phone systems bridge calls as a three-way call, so the caller ID KarmaFlow sees may differ from the number in the webhook payload. Leave Tolerate caller-ID mismatch on to accept the context anyway when exactly one pending context exists for the agent.

Collect values during the call

  1. In the Values the agent must collect card, click Add value for each item:
    • Label and Key — the key identifies the value in the post-call results
    • Type — Text, Number, Yes/No, or Picklist (with comma-separated options)
    • Guidance for the agent — how to ask for it or what qualifies
    • Required — check to prevent the agent from hanging up before this value is saved
  2. Click Save.

The agent saves values as the caller provides them. If it tries to end the call while required values are missing, the hang-up is refused and the agent is told what to ask for. If the caller hangs up first, the results are still delivered with valuesComplete: false and a missingRequired list.

Retrieve results after the call

Two delivery options — use either or both:

Your phone system pulls (recommended for 3CX-style flows). Turn on Post-call results — phone system pulls, save, and point your phone system's post-call HTTP step at the generated URL. When the PBX POSTs after the hangup, the response contains the results. If the call is still finalizing, the response is { "status": "pending" } — safe to retry the same request. Set Call ID field if your system echoes KarmaFlow's call ID back; otherwise matching falls back to the caller number.

KarmaFlow pushes. Turn on Post-call results — we push and enter your Destination URL. When a call ends, KarmaFlow POSTs the results, retrying on failure. Set a Signing secret (use Generate for a strong one) to receive an X-Karmaflow-Signature: sha256=<hex> header — the HMAC-SHA256 of <X-Karmaflow-Timestamp>.<body>. Add Static headers if your endpoint expects fixed headers such as an API key. Use Send test to deliver a sample payload to your endpoint (save the agent first).

The results payload looks like:

{
  "event": "call.ended",
  "callId": "…",
  "direction": "inbound",
  "from": "+15551234567",
  "to": "+15557654321",
  "startedAt": "2026-07-26T18:02:11.000Z",
  "endedAt": "2026-07-26T18:06:40.000Z",
  "durationSeconds": 269,
  "disposition": "ended",
  "collectedValues": { "ticket_number": "T-4821", "callback_ok": true },
  "valuesComplete": true,
  "missingRequired": [],
  "recordingUrl": null
}

The AI call summary is produced by post-call analysis a few minutes after the call and is not included in this payload — review it on the call detail page.

Troubleshooting

Related