How to configure UniTalk
Connect UniTalk to ConnectiveOne with the built-in UniTalk provider preset. Completed calls appear in the call archive with recording, assignee, and client card fields.
This is a full implementation guide: preset, webhook, two operator-assignment paths (with ready JSON), client fields, smoke test, and troubleshooting.
Prerequisites
- UniTalk admin access
- ConnectiveOne bot settings (Settings → Bots → Telephony)
- Operator emails in ConnectiveOne match emails in UniTalk (for auto-assignment)
- For path A (recommended): SIP line (line in UniTalk) ↔ operator email table
- For path B (optional): UniTalk API key (Integration → API)
When to use it
- UniTalk is your telephony provider
- You need a quick setup without manual webhook field mapping
- Completed calls should appear in Operator Panel with recording and assignee
Two ways to assign the operator
Path A — operator_mapping |
Path B — action_telephony_staff_enrich |
|
|---|---|---|
| Idea | Static SIP → email table in Advanced Config | UniTalk API /users/list, match on line |
| External API | No | Yes (cache required — UniTalk rate limits) |
| When to choose | Stable line list (typical production setup) | Lines change often; you do not want a manual table |
| Channel setup | operator_mapping block in JSON |
API Key + Webhook enrich action = action_telephony_staff_enrich |
When
operator_mappingmatches, ConnectiveOne skips enrich — no extra API calls.
action_telephony_staff_enrich is a generic internal action (any HTTP staff list via json_config). Below is a ready UniTalk configuration.
Step 1: Open channel settings
- Settings → Bots
- Select the bot
- Open the Telephony tab
- Create a new channel or edit an existing one
Minimum fields:
| Channel field | Value |
|---|---|
| Name | e.g. UniTalk |
| Active | On |
| Default country code | e.g. UA / 380 (as on your instance) |
After the first save you get Webhook URL and token.
Step 2: Apply the UniTalk preset
- In Advanced Config (JSON), select UniTalk from the provider preset list
- Click Apply preset
- Save and copy the Webhook URL (including
?token=...)
The preset adds:
event_detection— onlyCALL_ENDfield_mapping/status_mapping/direction_mappingclient_field_mapping— UTM, source, comment → client card- recordings from
call.link
Preset JSON (without operator_mapping) also lives in the repo: apps/engine/modules/extra/telephony/presets/unitalk.json.
Step 3: Webhook in UniTalk
- UniTalk cabinet → Event handlers
- Add a Send webhook handler
- Bind only to
CALL_END(do not sendCALL_NEW, etc.)
| Field in UniTalk | Value |
|---|---|
| Method | POST |
| URL | Full ConnectiveOne Webhook URL, e.g. https://<your-domain>/kw/telephony/webhook/<channel_id>?token=<webhook_token> |
| Body | Standard JSON |
Token only in the URL (
?token=...). Do not change the/kw/telephony/webhook/...path.
Example CALL_END body (inbound)
{
"event": "CALL_END",
"call": {
"id": "sample-call-id",
"from": "380501234567",
"to": "9578",
"direction": "in",
"state": "ANSWER",
"secondsFullTime": 120,
"secondsTalk": 90,
"date": "2026-09-02T12:00:00.000Z",
"link": "https://example.test/recording.mp3",
"utmSource": "google",
"utmCampaign": "brand",
"source": "ads",
"comment": "Call comment"
}
}
| UniTalk field | After UniTalk preset in ConnectiveOne |
|---|---|
event |
Must be CALL_END, otherwise 200 ignored |
call.id |
Call ID (idempotency — retry does not create a duplicate) |
call.from / call.to |
Client number or operator SIP (depends on direction) |
call.direction |
in / out |
call.state |
ANSWER → answered; NOANSWER, BUSY, … → missed |
call.link |
Recording |
call.utmSource, utmCampaign, source, comment |
Client card (client_field_mapping) |
Direction and operator SIP:
| Direction | Client number | Operator SIP (key in operator_mapping / enrich lookup) |
|---|---|---|
in (inbound) |
call.from |
call.to |
out (outbound) |
call.to |
call.from |
In the ConnectiveOne channel form: webhook format = JSON.
Step 4A: Operator assignment via operator_mapping (recommended)
After Apply preset, add operator_mapping to the same JSON (same level as event_detection, field_mapping, …), then Validate JSON / Save.
Fragment example
"operator_mapping": {
"source": {
"in": "callee_number",
"out": "caller_number"
},
"map": {
"9578": "[email protected]",
"201": "[email protected]"
}
}
Full Advanced Config example (preset + mapping)
Copy, replace SIP → email with your values, save:
{
"event_detection": {
"mode": "event_field",
"event_field": "event",
"call_ended_values": ["CALL_END"]
},
"field_mapping": {
"call_id": "call.id",
"caller_number": "call.from",
"callee_number": "call.to",
"status": "call.state",
"duration": "call.secondsFullTime",
"talk_duration": "call.secondsTalk",
"recording_url": "call.link",
"direction": "call.direction",
"date": "call.date",
"utm_source": "call.utmSource",
"utm_campaign": "call.utmCampaign",
"call_source": "call.source"
},
"status_mapping": {
"ANSWER": "answered",
"NOANSWER": "missed",
"BUSY": "missed",
"CANCEL": "missed",
"AUTOCANCEL": "missed",
"UNREACHABLE": "missed",
"VOICE_MAIL": "missed",
"FAIL": "failed",
"BLOCKED": "failed",
"AUDIO_ERR": "failed"
},
"direction_mapping": {
"in": "in",
"out": "out",
"inbound": "in",
"outbound": "out"
},
"recordings": {
"enabled": true,
"download": false
},
"transcription": {
"enabled": false,
"source": "provider"
},
"client_field_mapping": {
"utm_source": "call.utmSource",
"utm_campaign": "call.utmCampaign",
"call_source": "call.source",
"last_call_comment": "call.comment"
},
"operator_mapping": {
"source": {
"in": "callee_number",
"out": "caller_number"
},
"map": {
"9578": "[email protected]",
"201": "[email protected]"
}
}
}
Rules:
- Keys in
mapare raw SIP strings as in UniTalk ("9578"), before E.164 (not+3809578). - Email in ConnectiveOne must match an active Operator Panel user.
- Each UniTalk operator must have an internal line filled in.
- Webhook enrich action can stay empty.
Step 4B: Dynamic assignment via action_telephony_staff_enrich (optional)
Use when you do not maintain operator_mapping (or as a fallback when a line is missing from the table).
4B.1 Channel fields
| Field | Value |
|---|---|
| API Key | UniTalk API key (Integration → API) |
| API Base URL (if present) | https://api.unitalk.cloud/api |
| Webhook enrich action | action_telephony_staff_enrich |
The key is a secret. Do not publish it in chats or tickets.
4B.2 Action parameters (json_config)
The action ships with the product (internal). If you use an Action Jail wrapper on the instance, put the same parameters in the action JSON config.
Ready UniTalk example:
{
"api_url": "https://api.unitalk.cloud/api/users/list",
"http_method": "POST",
"auth_header_name": "Authorization",
"auth_scheme": "raw",
"request_body": {},
"response_items_path": "",
"match_field": "line",
"lookup_source": {
"in": "callee_number",
"out": "caller_number"
},
"email_field": "email",
"name_fields": ["firstName", "lastName"],
"cache_ttl_seconds": 300,
"timeout_ms": 8000
}
| Parameter | Why |
|---|---|
match_field: line |
Internal PBX SIP in /users/list (not phone — mobile, often null) |
lookup_source |
Where to take SIP from the normalized call: in → callee_number, out → caller_number |
cache_ttl_seconds |
Staff-list cache (UniTalk limits ~15 req/s) |
api_key |
In json_config or only in the channel API Key field |
If the API returns a root array, leave response_items_path as "". If wrapped as { "data": [ … ] }, set "data".
4B.3 Sample UniTalk /users/list fragment
[
{
"id": 1,
"email": "[email protected]",
"firstName": "Ivan",
"lastName": "Petrenko",
"line": "9578",
"phone": null,
"role": "OPERATOR"
}
]
ConnectiveOne finds line = call SIP and writes manager_email / manager_name → assignment by email.
General enrich how-to: Configure webhook enrichment.
Implementor template: docs/developer/engine/modules/telephony/action_telephony_staff_enrich.template.md.
Step 5: Client card fields
The preset already includes client_field_mapping:
Key in extra_data |
Webhook path |
|---|---|
utm_source |
call.utmSource |
utm_campaign |
call.utmCampaign |
call_source |
call.source |
last_call_comment |
call.comment |
For fields to show on the client card, add matching custom fields in Instance Settings (extra_data schema). Telephony merges values without Action Jail.
Step 6: Save and smoke-test
- Save the channel (active).
- Use Test webhook in the form or the curl below.
- Make test inbound and outbound calls in UniTalk.
- Operator Panel → Closed requests:
telephonydialogue, recording (ifcall.link), assignee.
Example curl (local / stage smoke)
Replace URL and token. Body as in step 3; for path A align "to" / emails with your operator_mapping.
curl -X POST 'https://<your-domain>/kw/telephony/webhook/<channel_id>?token=<webhook_token>' \
-H 'Content-Type: application/json' \
-d '{
"event": "CALL_END",
"call": {
"id": "smoke-unitalk-001",
"from": "380501234567",
"to": "9578",
"direction": "in",
"state": "ANSWER",
"secondsFullTime": 60,
"secondsTalk": 45,
"date": "2026-09-02T12:00:00.000Z",
"link": "https://example.test/recording.mp3",
"utmSource": "google",
"utmCampaign": "brand",
"source": "ads",
"comment": "Smoke test"
}
}'
Expected: HTTP 200 with dialogue_id.
Same call.id again → 200, already processed, no duplicate.
Non-CALL_END (e.g. "event": "CALL_NEW") → 200 ignored, no dialogue.
Acceptance checklist
| # | Check | Expected |
|---|---|---|
| 1 | CALL_END |
Dialogue created, telephony channel, completed |
| 2 | Non-CALL_END |
200 ignored, no dialogue |
| 3 | call.link present |
Recording on the dialogue |
| 4 | Inbound / outbound | Client by correct number |
| 5 | SIP in and out | Operator assigned (mapping or enrich) |
| 6 | UTM / comment | Values on client card (if Instance Settings fields exist) |
| 7 | Same call.id twice |
No duplicate |
| 8 | Path B | Cache / no rate-limit lock; or path A without enrich |
Troubleshooting
| Symptom | Check |
|---|---|
| 200 ignored on every webhook | Body has "event": "CALL_END"; UniTalk preset applied (event_detection) |
| Dialogue exists, no operator | Email in map / UniTalk matches C1 user; SIP as "9578", not E.164; for out — line in call.from |
| Enrich not called | Matching operator_mapping — expected (enrich skipped) |
| Enrich error / no email | match_field = line; /users/list has line; channel API Key set |
| Duplicate dialogues | Different call.id from UniTalk; idempotency is per id |
| UTM not visible in UI | Merge into extra_data works — add custom field display in Instance Settings |
| 403 / unauthorized webhook | URL token matches channel token |
What the UniTalk preset includes
- Event detection for
CALL_ENDonly - Field, status, and direction mapping
- Recordings from
call.link client_field_mapping(UTM, source, comment)
operator_mapping and webhook enrich are not in the Apply preset button — add them in steps 4A / 4B.
Limitations
- Only completed calls (
CALL_END); no realtime during the call - Click-to-call from ConnectiveOne is out of scope
- UniTalk transcript / analytics is a separate scope