WEBAPI + WEBHOOK BUNDLE

Connect any CRM to 3CX

Two add-ons on your 3CX server: WebAPI for click-to-call and Webhook for real-time call events.

Your CRM opens the customer card when an agent answers, logs every incoming, outgoing and missed call, and stores the recording and AI summary.

Works with 3CX on Debian or Windows, on your own server or VPS. From €438 per year, see pricing.
3CX connected to a CRM system

What your CRM gets

Everything is built on standard HTTP requests, so it works with any CRM, ERP or helpdesk
  • Customer card on answer

    The CRM opens the caller's record the moment an agent picks up the phone
  • Every call logged

    Incoming and outgoing calls with duration, result and the reason a call failed
  • Missed calls in IVR and queues

    See who called and where the call was lost, so your team can call back
  • Click-to-call

    One GET request from the CRM starts the call on the agent's phone or app
  • Call recordings

    A link to the MP3 or WAV recording is attached to the call record
  • AI summary

    Transcription, short summary and sentiment score arrive after the call

How it works

WebAPI and the Webhook generator are installed as a service (Windows) or daemon (Debian) on the same server as 3CX.

3CX → CRM. The Webhook generator sends every call event to your CRM as an HTTPS POST request with a JSON body: ringing, answered, finished, missed, recording ready, AI summary ready. All events of one call share the same chid.

CRM → 3CX. Your CRM calls the WebAPI REST methods, for example makecall for click-to-call. The response contains the chid of the new call, so the CRM can match the webhooks that follow.

No middleware and no cloud service in between: data goes directly from your 3CX server to your CRM.
Watch: 3CX and any CRM
A short video on how the WebAPI + Webhook bundle connects 3CX to a CRM system

Integration guide

What your CRM developer needs to do, step by step. Full field reference: Webhook documentation and WebAPI documentation.
Before you start

  1. Install the WebAPI + Webhook bundle on your 3CX server (Debian or Windows, your own server or VPS; 3CX hosted by 3CX is not supported).
  2. Create an HTTPS endpoint in your CRM that accepts POST requests with a JSON body (Content-Type: application/json) from the IP address of your 3CX server and returns HTTP 200.
  3. In the [Webhooks] section of TCXWebAPI.ini, set POST = 1 and WEBHOOK_URL = your endpoint, for example https://crm.company.com/webhooks/. Set RECORDING_FULL_INFO = 1 to get call details together with the recording link. Restart the WebAPI service. All webhook settings
  4. To start calls from the CRM, create an access key in AuthKeys.csv and allow the CRM server's IP address in AllowedIP.txt.

Tip: 3CX sends numbers without "+" (for example 381629759787). Normalize phone numbers in your CRM to digits only to find the customer reliably.

1. Incoming calls

Step 1. Create the call record on the first ringing event
  • callerid - external number of customer
  • user - internal number of the IVR
  • chid - unique ID of the call chain
  • inbound_did - DID number
POST /webhooks/ HTTP/1.1
Host: crm.company.com
Content-Type: application/json

{
    "event": "ringing",
    "callerid": "381629759787",
    "user": "809",
    "usertype": "other",
    "did": "DID Serbia 021 3220 030",
    "id": "250917161728_41-0",
    "chid": "00000000-01dc-27dd-cc8a-799100000029",
    "inbound_did": "381213220030",
    "sip_displayname": "381629759787",
    "phonebook": "Smith, John",
    "call_id1": "e1d9f75e-0e73-123f-b3a2-005056be101b;to-tag=8a5c6e0d;from-tag=Ue91FUB2ZBF6B",
    "call_id2": ""
}
Step 2. Log a missed call when it happens in the IVR menu or a queue
  • callerid - external number of customer
  • user - internal number of the IVR
  • chid - unique ID of the call chain
  • inbound_did - DID number
POST /webhooks/ HTTP/1.1
Host: crm.company.com
Content-Type: application/json

{
    "event": "incoming",
    "callerid": "381629759787",
    "user": "809",
    "finishtype": "Missed",
    "transfer": "False",
    "breakside": "Undef",
    "did": "DID Serbia 021 3220 030",
    "title": "DID Serbia 021 3220 030:Missed call  by IVR 809 from 381629759787",
    "id": "250917161728_41-0",
    "chid": "00000000-01dc-27dd-cc8a-799100000029",
    "inbound_did": "381213220030",
    "sip_displayname": "381629759787",
    "phonebook": "Smith, John",
    "call_id1": "e1d9f75e-0e73-123f-b3a2-005056be101b;to-tag=8a5c6e0d;from-tag=Ue91FUB2ZBF6B",
    "call_id2": "fbOC_H_YLvjdus8WVW7ocw..;from-tag=94183327;to-tag=8e77c732",
    "termination_reason_details": "by_did",
    "source_presentation": "Smith, John:DID Serbia 021 3220 030"
}
Step 3. Open the customer's CRM card on the pickupincoming event
  • callerid - external number of customer
  • user - user extension
  • chid - unique ID of the call chain
  • inbound_did - DID number
POST /webhooks/ HTTP/1.1
Host: crm.company.com
Content-Type: application/json

{
    "callerid": "381629759787",
    "event": "pickupincoming",
    "user": "105",
    "did": "DID Serbia 021 3220 030",
    "trtype": "NotDef",
    "id": "250917190514_45-1",
    "chid": "00000000-01dc-27f5-3c43-81de0000002d",
    "inbound_did": "381213220030",
    "sip_displayname": "381629759787",
    "phonebook": "Smith, John",
    "call_id1": "51860fab-0e8b-123f-b3a2-005056be101b;to-tag=e4206478;from-tag=mDm0KNr2r4rKD",
    "call_id2": "fe63887e-c64d-4f89-ada6-309ce28a5e4b;to-tag=6f0d405e;from-tag=36dd9a2c-6039-4a65-87b2-22f787792d62"
}
Step 4. Log the result and duration of an answered call and attach the .mp3 or .wav recording
  • callerid - external number of customer
  • user - user extension
  • chid - unique ID of the call chain
  • inbound_did - DID number
POST /webhooks/ HTTP/1.1
Host: crm.company.com
Content-Type: application/json

{
    "FILES": [
        "https://{3CXFQDN}/webapi/recording/250917190514_45-1-1.mp3"
    ],
    "event": "incoming",
    "callerid": "381629759787",
    "user": "105",
    "finishtype": "Ok",
    "transfer": "False",
    "breakside": "External",
    "did": "DID Serbia 021 3220 030",
    "title": "DID Serbia 021 3220 030:Answered call from 381629759787 (0:07)",
    "id": "250917190514_45-1",
    "chid": "00000000-01dc-27f5-3c43-81de0000002d",
    "inbound_did": "381213220030",
    "sip_displayname": "381629759787",
    "phonebook": "Smith, John",
    "call_id1": "51860fab-0e8b-123f-b3a2-005056be101b;to-tag=e4206478;from-tag=mDm0KNr2r4rKD",
    "call_id2": "cg0tTWS7tWqn2aJzJU39PA..;from-tag=425b177d;to-tag=9524b651",
    "termination_reason_details": "none",
    "source_presentation": "Smith, John:DID Serbia 021 3220 030"
}
Step 5. Add the AI transcription and summary (a separate webhook after the call)
POST /webhooks/ HTTP/1.1
Host: crm.company.com
Content-Type: application/json

{
    "event": "ai",
    "id": "250917190514_45-1",
    "chid": "00000000-01dc-27f5-3c43-81de0000002d",
    "summary": "Customer contacted the bank’s service desk about an unknown €120 transaction from the previous day. The agent created a case and forwarded it to the fraud team. Resolution expected within 48 hours.",
    "transcription": "Hi i need to check something on my account please… sure can you tell me what the issue is… yes i see a transaction from yesterday for 120 euros that i dont recognize… okay i will open a case and send it to our fraud team you should hear back within forty eight hours… thank you very much… youre welcome have a nice day",
    "sentiment_score": "5"
}

2. Outgoing calls

Step 1. Start the call from the CRM (click-to-call) with a GET request
  • {AccessKey} - access key from AuthKeys.csv
  • {3CXFQDN} - address of your 3CX server
  • first - extension of the employee who makes the call
  • second - customer's external number
  • contact - device to use (optional)
  • timeout - response timeout in milliseconds
GET /webapi/{AccessKey}/makecall?first=100&second=381629759787&contact=100&timeout=2000 HTTP/1.1
Host: {3CXFQDN}
Save the chid from the response: the following webhooks of this call carry the same chid
{
    "chid": "00000000-01dc-27fa-d1eb-64b00000002e"
}
Step 2. Log a failed outgoing call with the reason
  • callerid - external number of customer
  • user - user extension
  • termination_reason_details - rejection reason
  • source_presentation - outgoing DID number
POST /webhooks/ HTTP/1.1
Host: crm.company.com
Content-Type: application/json

{
    "event": "outgoing",
    "callerid": "381629759787",
    "user": "105",
    "finishtype": "Missed",
    "transfer": "False",
    "breakside": "Undef",
    "did": "",
    "title": "Unanswered call to 381629759787",
    "id": "250917194513_46-0",
    "chid": "00000000-01dc-27fa-d1eb-64b00000002e",
    "inbound_did": "381629759787",
    "sip_displayname": "",
    "phonebook": "",
    "call_id1": "mf5zBO50gjyzLA3rLgaZkA..;from-tag=3510c33e;to-tag=2c2c4b61",
    "call_id2": "a2c4c06a-21d7-4d43-b58c-db3871740d61;to-tag=59329b7a;from-tag=81865a8a-e9a9-4bf6-a597-9e496bfda25a",
    "termination_reason_details": "declined",
    "source_presentation": "381213220030"
}
Step 3. Open the customer's CRM card on the pickupoutgoing event
  • callerid - external number of customer
  • user - user extension
  • chid - unique ID of the call chain
  • source_presentation - outgoing DID number
POST /webhooks/ HTTP/1.1
Host: crm.company.com
Content-Type: application/json

{
    "callerid": "381629759787",
    "event": "pickupoutgoing",
    "user": "105",
    "did": "",
    "trtype": "NotDef",
    "id": "250917195359_47-1",
    "chid": "00000000-01dc-27fc-0bdb-88fd0000002f",
    "inbound_did": "",
    "sip_displayname": "",
    "phonebook": "",
    "call_id1": "170f530d-7af4-4081-9af1-6c3d88afc411;to-tag=3d10a53b;from-tag=eca65e6e-efc4-436a-8bcf-041f27b8267c",
    "call_id2": "0-I_xdErJxAvrSrfWr4eNA..;from-tag=ba2c291a;to-tag=as0775c705"
}
Step 4. Log the result and duration of an answered call and attach the .mp3 or .wav recording
  • callerid - external number of customer
  • user - user extension
  • chid - unique ID of the call chain
  • source_presentation - outgoing DID number
POST /webhooks/ HTTP/1.1
Host: crm.company.com
Content-Type: application/json

{
    "FILES": [
        "https://{3CXFQDN}/webapi/recording/250917195359_47-1-1.mp3"
    ],
    "event": "outgoing",
    "callerid": "381629759787",
    "user": "105",
    "finishtype": "Ok",
    "transfer": "False",
    "breakside": "Internal",
    "did": "",
    "title": "Successful call to 381629759787 (0:05)",
    "id": "250917195359_47-1",
    "chid": "00000000-01dc-27fc-0bdb-88fd0000002f",
    "inbound_did": "381629759787",
    "sip_displayname": "",
    "phonebook": "",
    "call_id1": "MQdyDv4dHEvGFw8FZ6u49w..;from-tag=2950160b;to-tag=34643343",
    "call_id2": "170f530d-7af4-4081-9af1-6c3d88afc411;to-tag=3d10a53b;from-tag=eca65e6e-efc4-436a-8bcf-041f27b8267c",
    "termination_reason_details": "polling",
    "source_presentation": "381213220030"
}
Step 5. Add the AI transcription and summary (a separate webhook after the call)
POST /webhooks/ HTTP/1.1
Host: crm.company.com
Content-Type: application/json

{
    "event": "ai",
    "id": "250917195359_47-1",
    "summary": "Customer received a positive outbound call about a weekend swimming pool discount and accepted the offer.",
    "transcription": "Hello this is the call center we have a special offer for you there is a weekend discount for the swimming pool would you like to take advantage. Yes that sounds great thank you very much. Wonderful have a nice day",
    "sentiment_score": "5"
}
“
The fastest and simplest integration our team has ever done. It took us just 3 days to fully integrate a CRM system with 3CX using the WebAPI + Webhook bundle from Creomate.
— SAP CRM developer

Pricing

Annual license for the WebAPI + Webhook bundle, priced by simultaneous calls (SC). The license must cover the same number of SC as your 3CX license. Support is included; taxes and VAT are not.
8 SC
— WebAPI + Webhook
— Support included
€438
per year
16 SC
— WebAPI + Webhook
— Support included
€658
per year
24 SC
— WebAPI + Webhook
— Support included
€878
per year
32 SC
— WebAPI + Webhook
— Support included
€1 098
per year

FAQ

More answers in the 3CX WebAPI FAQ