GoHighLevel integration
Send call recordings from GoHighLevel (GHL) into Call Analytics, get back a scored report, and surface it inside GHL. No code required for the basic path — it's a GHL Workflow webhook action pointed at our inbound endpoint.
1. Get an API key
In the app, open Company → API keys
(https://app.callanalyticsapi.com/company/api-keys), create a key with the
calls:write scope, and copy it (the full key is shown once). See
Authentication.
Path 1 — GHL Workflow → Webhook action (recommended)
This is the no-code path. A workflow watches for a completed call and POSTs it to our inbound endpoint.
- In GHL, go to Automation → Workflows and create or open a workflow.
- Add a trigger such as Call Completed (or Customer Replied / whatever fires when the recording exists).
- Add a Webhook action.
- Set Method to
POSTand the URL to:https://api.callanalyticsapi.com/webhooks/inbound/generic - Under Headers, add:
X-Api-Key: cc_3a91f8e2_your_api_key Content-Type: application/json - Set the Body to
JSONand map GHL custom values into the fields our endpoint accepts.
JSON body to configure
Use GHL's {{ }} merge fields. Our inbound endpoint accepts flexible field names, so
GHL's native naming maps cleanly:
{
"external_call_id": "{{contact.id}}-{{message.id}}",
"contact_name": "{{contact.name}}",
"phone": "{{contact.phone}}",
"email": "{{contact.email}}",
"recording_url": "{{message.recording_url}}",
"duration": "{{message.duration}}",
"agent_name": "{{user.name}}",
"agent_email": "{{user.email}}",
"contact_id": "{{contact.id}}",
"source_system": "gohighlevel"
}
| GHL merge field | Maps to call attribute |
|---|---|
{{contact.name}} → contact_name | Customer name |
{{contact.phone}} → phone | Customer phone |
{{message.recording_url}} → recording_url | Recording URL |
{{message.duration}} → duration | Duration (seconds) |
{{user.name}} → agent_name | Rep name |
{{contact.id}} → contact_id | CRM contact id (for write-back) |
Recording URL must be fetchable. We download the audio from
recording_url. If GHL recordings sit behind auth, use a publicly accessible link or a
signed URL. The exact merge field for the recording varies by GHL trigger/channel — confirm it
resolves to a real .mp3/.wav URL when you test the workflow.
What you get back
A 201 with {"call_id":…,"status":"received"}. Resubmitting the same
external_call_id returns 200 "duplicate" instead of creating another call,
so workflow retries are safe.
Path 2 — REST API directly
If you trigger from your own backend (e.g. a GHL marketplace app or a middleware service), call the REST API instead. This gives you the full parameter set and structured responses.
curl -X POST https://api.callanalyticsapi.com/v1/calls \
-H "Authorization: Bearer cc_3a91f8e2_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"external_call_id": "ghl-ct_993-msg_77",
"customer_name": "Acme Corp",
"customer_phone": "+15125550199",
"recording_url": "https://storage.example.com/rec/77.mp3",
"rep_name": "Jordan Lee",
"crm_contact_id": "ct_993",
"source_system": "gohighlevel"
}'
See Calls for the full reference, and uploads if you have the audio file rather than a URL.
Receiving the report back in GHL
To get the finished analysis back into GHL, use an outbound webhook into a GHL Inbound Webhook trigger:
- In GHL, create a workflow with an Inbound Webhook trigger and copy its URL.
- In our app, go to Company → Webhooks, add an endpoint with that GHL URL, and
subscribe it to
call.report_completed(and optionallycall.compliance_alert_detected,call.buying_signal_detected). - When a report is ready, we POST it to GHL. In the GHL workflow, map the report fields
(
report.overall_score,report.summary,report.crm_note) into contact custom fields, notes, or notifications. - Verify the
X-Cadence-Signatureheader if you proxy through your own service. See Webhooks for the signing format.
Because the payload includes crm_contact_id (the {{contact.id}} you sent
in), you can match the report back to the exact GHL contact.
Native connector on the roadmap. A first-class GHL OAuth connector — install from the GHL marketplace, no manual webhook wiring — is in progress (the connector stub already exists). Until it ships, the workflow-webhook path above is the supported integration.