3CX
The 3CX integration imports call recordings from a 3CX phone system. It combines two 3CX features:
- the Remote Archive, which stores recordings somewhere Speechlytics can read;
- a CRM integration template, whose call-journaling step tells Speechlytics each time a call ends.
3CX cannot tell Speechlytics the recording's file name, so Speechlytics finds the recording in your archive by matching the reported call (agent extension or caller number, and call time) against the archive's file names.
1. Archive recordings
Configure the 3CX Remote Archive to store recordings in a location Speechlytics can reach:
| Recordings Location | Example |
|---|---|
| SFTP | sftp://archive.example.com:22/var/lib/3cxpbx/Instance1/Data/Recordings |
| FTP | ftp://archive.example.com/Recordings |
| Network share or mounted folder | \\fileserver\3cx\Recordings or /mnt/3cx/Recordings |
- Include the
sftp://orftp://prefix for SFTP and FTP. A value without a prefix is read as a folder on the Speechlytics server. - Point the location at the Recordings root, the folder that contains one subfolder per extension. Subfolders are read up to four levels deep.
- Only
.wavand.mp3files are imported. - Keep 3CX's default file naming, for example
[John Smith]_101-07700900123_20260928111812(42).wav. Speechlytics needs the date-time stamp (yyyyMMddHHmmss) and either the agent's extension or the other party's number in the file name.
Speechlytics only reads the archive. It copies recordings to its own storage and never modifies or deletes your files.
2. Configure the integration in Speechlytics
Provide your Speechlytics representative with:
| Field | Meaning |
|---|---|
| Recordings Location | The archive location from step 1. |
| Archive Username / Archive Password | Credentials for SFTP or FTP. Not needed for a share Speechlytics can already read. |
| Webhook Secret | A secret you choose. Required: without it every call report is rejected. |
Once saved, the integration shows its Webhook Url: https://<api-host>/api/v1/webhooks/threecx/<integration-id>.
3. Set up the CRM template in 3CX
Create a 3CX CRM integration template with two scenarios, both pointing to the Webhook Url:
Contact lookup. A GET request with a JSON response type. 3CX requires a lookup scenario in every CRM template; Speechlytics holds no contacts and always answers {}.
Call journaling (ReportCall). A POST request with:
- the secret in an
x-3cx-signatureheader, or asAuthorization: <secret>orAuthorization: Bearer <secret>; - a JSON body with the call variables:
| Field | Required | Meaning |
|---|---|---|
startTimeUtc | One of the two times | Call start (ISO 8601; read as UTC when no zone is given). |
endTimeUtc | One of the two times | Call end. |
agent | agent or number | The agent's extension. |
number | agent or number | The other party's number. |
callType | No | Calls reported as Missed or Notanswered are ignored. |
callDirection | No | Inbound or Outbound. |
duration | No | mm:ss, hh:mm:ss or seconds. Measured from the audio when missing. |
agentFirstName, agentLastName | No | The agent's display name. |
4. Switch the integration on
Your representative switches the integration on once the Recordings Location and secret are saved.
How recordings are found
When a call report arrives, Speechlytics:
- lists files written since shortly before the call started, first in the agent's extension folder (
<root>/<extension>), then in the configured folder; - picks the file whose time stamp is within two minutes of the call's start or end and whose name contains the agent's extension or the last seven digits of the other party's number. Time stamps in the phone system's local time zone are recognized;
- if no file is there yet, tries again several times over the next minute, because 3CX archives recordings after the call ends.
An hourly sweep also imports any new archive files that were never matched. Calls found only by the sweep have no agent, numbers or direction.
The recording's file name (without extension) is the call's External Id, so a recording is never imported twice. The agent is identified by display name or extension and created automatically if needed. The customer's name is not stored.
Troubleshooting
| Symptom | What to check |
|---|---|
| Every call report is rejected | The Webhook Secret is empty in Speechlytics, or the template sends a different value. |
| Calls arrive without agent or numbers | They were imported by the hourly sweep because the call report was not matched. Check that file names keep the time stamp and extension, and that the template sends agent, number and the call times. |
| Nothing is imported | Speechlytics cannot read the Recordings Location. Check the sftp:// or ftp:// prefix, host, path and credentials. |
| Only one extension's recordings are swept hourly | The Recordings Location points at an extension folder; point it at the Recordings root. |
| Missed calls do not appear | Expected: missed and unanswered calls are ignored. |