Logo API Integration Guide

API Integration Guide

Complete reference for integrating with the System reporting and analytics API. All endpoints are secured with JWT Bearer tokens.

v1.0 JWT Auth REST / JSON Base URL: https://your-domain.com/api

1 Authentication

All endpoints except /api/login require the header:
Authorization: Bearer <your_jwt_token>

Login

POST/api/login
Request Body
{ "email": "user@example.com", "password": "your_password" }
cURL Example
curl -X POST https://your-domain.com/api/login \ -H "Content-Type: application/json" \ -d '{"email":"user@example.com","password":"your_password"}'
Response 200
{ "success": true, "data": { "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", "user": { "id": 12, "name": "Agent Name", "email": "user@example.com" } } }
Response 401
{ "success": false, "errors": { "error": "invalid_login_or_password" } }

2 Inbound Calls

2.1 List Inbound Calls

GET/api/reporting/inbound
ParameterTypeRequiredDescription
daterangestringNo"YYYY-MM-DD HH:mm:ss - YYYY-MM-DD HH:mm:ss"
did_extstringNoFilter by DID number
user_extstringNoFilter by agent extension or user ID
group_extstringNoFilter by queue / group ID
searchstringNoSearch by queue name, agent, caller number
pageintNoDefault: 1
per_pageintNoDefault: 10, max: 200
cURL Example
curl -H "Authorization: Bearer $TOKEN" \ "https://your-domain.com/api/reporting/inbound?daterange=2025-01-01+00:00:00+-+2025-01-31+23:59:59&group_ext=101"
Response 200
{ "success": true, "data": { "data": { "data": [{ "call_time": "2025-01-15 09:22:10 AM", "queue_description": "Sales Queue", "agent": "Agent Name", "hangup_by": "Caller", "ring_time": "00:00:18", "talk_time": "00:04:32", "caller_number": "0501234567", "listen_url": "https://your-domain.com/api/reporting/listen/1736929330.1452" }], "total": 342, "per_page": 10, "current_page": 1, "last_page": 34 } }, "message": "Inbound calls retrieved successfully" }

2.2 Get Call Transfers

GET/api/reporting/inbound/{linkedid}/transfers
cURL Example
curl -H "Authorization: Bearer $TOKEN" \ https://your-domain.com/api/reporting/inbound/1736929330.1452/transfers
Response 200
{ "success": true, "data": [ { "calldate": "2025-01-15 09:23:11", "src": "1001", "dst": "1002", "duration": 95, "billsec": 88, "disposition": "ANSWERED" } ], "message": "Transfers retrieved successfully" }

2.3 Mark Inbound Call as Done

POST/api/reporting/inbound/done/{id}
Response 200
{ "success": true, "data": { "id": "1736929330.1452" }, "message": "Inbound call marked as done" }

2.4 Inbound Distribution

GET/api/reporting/inDist

Data source: inbound_reports (one row per call; rows are classified by call_status — answered or missed) — same table as the Inbound and Inbound & Missed reports; no CDR / queuelog dependency. Response structure unchanged; filters additionally echoes the applied group_ext (additive, null when not provided).

ParameterTypeRequiredDescription
daterangestringNo"YYYY-MM-DD HH:mm:ss - YYYY-MM-DD HH:mm:ss"
group_extintNoGroup (queue) ID — narrows to that one queue within the caller's visible queues (same as Inbound)
Response includes
{ "hours_table": [ { "label": "08:00", "answord": 45, "missed": 5, "rate": "90.0 %" } ], "days_table": [ { "label": "Sunday", "answord": 120, "missed": 18, "rate": "87.0 %" } ], "months_table": [ { "label": "2025-01", "answord": 890, "missed": 110, "rate": "89.0 %" } ] }

3 Outbound Calls

3.1 List Outbound Calls

GET/api/reporting/outbound
ParameterTypeRequiredDescription
daterangestringNoDate range filter
did_extstringNoFilter by source extension
user_extstringNoFilter by user ID
searchstringNoSearch by destination number
pageintNoDefault: 1
per_pageintNoDefault: 10
Response 200
{ "status": true, "data": { "data": { "current_page": 1, "data": [ { "call_time": "2025-01-15 10:05:22 AM", "linkedid": "1736929330.1452", "total_duration": "00:02:05", "talk_time": "00:01:50", "ring_time": "00:00:15", "disposition": "ANSWERED", "dialed_number": "0501234567", "agent_ext": "1001", "agent_name": "Agent Name", "listen_url": "/api/reporting/listen/1736929330.1452", "listen_status": "done" } ], "total": 87, "per_page": 10, "last_page": 9 }, "filters": { "daterange": "2025-01-15 00:00:00 - 2025-01-15 23:59:59", "did_ext": null, "user_ext": null, "search": null } }, "message": "Outbound calls retrieved successfully", "errors": [] }

3.2 Mark Outbound Call as Done

POST/api/reporting/outbound/done/{id}
Response 200
{ "status": true, "data": { "id": "1736929330.1452" }, "message": "Outbound call marked as done", "errors": [] }

3.3 Outbound Distribution

GET/api/reporting/outDist

Data source: outbound_reports (one row per call) — same table and query logic as the Outbound Calls report; no CDR / queuelog dependency. Response structure, field names, labels, and formats unchanged.

ParameterTypeRequiredDescription
daterangestringNo"YYYY-MM-DD HH:mm:ss - YYYY-MM-DD HH:mm:ss"
Response 200
{ "status": true, "data": { "months": { "labels": ["01-2025", "02-2025"], "data": [320, 410], "chart_data": { "answered": [260, 340], "busy": [20, 30], "failed": [15, 18], "unanswered": [25, 22] } }, "days": { "labels": ["2025-01-15", "2025-01-16"], "data": [48, 92], "chart_data": { "answered": [38, 78], "busy": [3, 6], "failed": [2, 4], "unanswered": [5, 4] } }, "hours": { "labels": ["08", "09"], "data": [12, 35], "chart_data": { "answered": [10, 29], "busy": [1, 2], "failed": [0, 2], "unanswered": [1, 2] } }, "summary": { "total_answered": 600, "total_unanswered": 95, "total_busy": 50, "total_failed": 33, "total_calls": 695, "success_rate": 86.3 }, "filters": { "daterange": "2025-01-15 00:00:00 - 2025-01-31 23:59:59" } }, "message": "Outbound distribution data retrieved successfully", "errors": [] }

4 Missed Calls

4.1 List Missed Calls

GET/api/reporting/missed
ParameterTypeRequiredDescription
daterangestringNoDate range filter
queuenamestringNoFilter by queue ID
searchstringNoSearch by queue name, caller number, or DID
pageintNoDefault: 1
per_pageintNoDefault: 10
Response 200
{ "status": true, "data": { "data": { "current_page": 1, "data": [ { "callid": "1736929282.1440", "call_time": "2025-01-15 09:08:02 AM", "queuename": "101", "queue_name": "Sales Queue", "hangup_type": "ABANDON", "hangup_reason": "NO AGENT", "ring_duration": "00:00:45", "caller_number": "0501234567", "ring_details": [ { "agent": "SIP/1001", "event": "RINGNOANSWER", "ring_duration": "00:00:18", "time": "2025-01-15 09:08:05" } ], "done_by": null } ], "total": 42, "per_page": 10, "last_page": 5 }, "filters": { "daterange": "2025-01-15 00:00:00 - 2025-01-15 23:59:59", "queuename": null, "search": null }, "options": { "queues": { "1": "Sales", "2": "Support" } } }, "message": "Missed calls retrieved successfully", "errors": [] }

4.2 Get Ring Details

GET/api/reporting/ring-details/{callid}
Response 200
{ "status": true, "data": { "ring_details": [ { "agent": "SIP/1001", "event": "RINGNOANSWER", "ring_duration": "00:00:18", "time": "2025-01-15 09:10:05" } ], "inbound_calls": [], "outbound_calls": [], "active_missed_calls": [], "ring_details_count": 1, "inbound_calls_count": 0, "outbound_calls_count": 0, "active_missed_calls_count": 0 }, "message": "Ring details retrieved", "errors": [] }

4.3 Mark Missed Call as Done

POST/api/reporting/missed-done/{num}
Response 200
{ "status": true, "data": { "caller_number": "0501234567", "done_by": 12 }, "message": "Missed call marked as done", "errors": [] }

4.4 Missed Call Statistics

GET/api/reporting/missed/stats
Response 200
{ "status": true, "data": { "status_data": { "labels": ["ABANDON", "EXITWITHTIMEOUT"], "counts": [65, 22] }, "reason_data": { "labels": ["Unknown", "Busy", "Timeout"], "counts": [45, 28, 14] }, "total_missed": 87, "filters": { "daterange": "2025-01-15 00:00:00 - 2025-01-15 23:59:59" } }, "message": "Missed call stats retrieved successfully", "errors": [] }

5 Attendance

5.1 Attendance Log

GET/api/reporting/attendance

Data source: attendance — the canonical AMI event store, the same source as the web Attendance report (activity_log is no longer used). Response structure, field names, labels, and formats unchanged.

ParameterTypeRequiredDescription
daterangestringNoDate range filter
user_extintNoFilter by user ID
group_extintNoFilter by group ID
searchstringNoSearch by user name
pageintNoDefault: 1
per_pageintNoDefault: 10
Response 200
{ "success": true, "data": { "current_page": 1, "data": [ { "created_at": "2025-01-15 08:01:22", "agent_id": 12, "status": "logged in", "pause_reason": null, "agent_name": "Agent Name", "agent_email": "agent@company.com", "duration": "00d 00h 58m 30s" } ], "total": 158, "per_page": 10, "last_page": 16 }, "filters": { "daterange": "2025-01-15 00:00:00 - 2025-01-15 23:59:59", "user_ext": null, "group_ext": null }, "message": "Attendance data retrieved successfully" }

5.2 Attendance Summary

GET/api/reporting/attendance/summary
Response 200
{ "success": true, "data": { "summary": [ { "agent_id": 12, "agent_name": "Agent Name", "agent_email": "agent@company.com", "total_online": "07:30:00", "total_paused": "00:45:00", "total_offline": "00:15:00", "code": "1001", "logged_in_time": "07:30:00", "pause_time": "00:45:00", "reachable_time": "00:15:00", "total_time": "08:30:00", "LOGGED_IN_formatted": "07:30:00", "pause_formatted": "00:45:00", "Reachable_formatted": "00:15:00", "total_formatted": "08:30:00" } ], "filters": { "daterange": "2025-01-15 00:00:00 - 2025-01-15 23:59:59", "user_ext": null, "group_ext": null } }, "message": "Attendance data retrieved successfully" }

5.3 List Users

GET/api/reporting/attendance/users
Response 200
{ "success": true, "data": { "agents": [ { "id": 12, "name": "Agent Name", "email": "agent@company.com" }, { "id": 13, "name": "Agent Two", "email": "agent2@company.com" } ] }, "message": "Users retrieved" }

5.4 List Groups

GET/api/reporting/attendance/groups
Response 200
{ "success": true, "data": { "groups": [ { "id": 101, "name": "Sales Queue" }, { "id": 102, "name": "Support Queue" } ] }, "message": "Groups retrieved" }

6 Performance

6.1 Inbound Performance

GET/api/reporting/performance
ParameterTypeRequiredDescription
daterangestringNoDate range filter
user_extstringNoFilter by agent extension
group_extintNoFilter by queue / group ID
Response 200
{ "summary": { "overall_total_calls": 500, "overall_answered_calls": 440, "overall_dropped_calls": 40, "overall_failover_calls": 20, "overall_talk_time": "01:20:35", "average_ring_time": "00:00:22", "average_call_time": "00:02:50", "service_level": { "0_to_5": 120, "6_to_10": 95, "11_to_15": 80, "16_to_20": 60, "21_to_25": 40, "26_to_30": 25, "31_to_35": 12, "36_to_40": 5, "41_to_up": 3 }, "overall_ring_time": "00:03:02", "overall_total_transfers": 5, "service_level_over": 82.4 }, "agents": [ { "agent_id": 5, "agent_name": "Agent Name", "agent_calls": 42, "inbound_rejected": 3, "inbound_noanswer": 5, "avg_ring_time": "00:00:10", "total_talk_time": "03:12:00", "avg_talk_time": "00:04:34", "agent_hangup": 18, "customer_hangup": 24, "avg_handle_time": "00:09:08", "agent_transfers": 2, "transferred_out": 0, "transferred_in": 0, "agent_code": "1001" } ], "queues": [ { "overall_total_callsForQueue": 210, "overall_answered_callsForQueue": 190, "overall_dropped_callsForQueue": 12, "overall_failover_callsForQueue": 8, "overall_ring_timeForQueue": 2520, "overall_talk_timeForQueue": "01:10:00", "average_ring_timeForQueue": "00:00:12", "average_call_timeForQueue": "00:02:13", "queueExt": "101", "queueName": "Sales Queue", "overall_transfers_countForQueue": 3 } ], "filters": { "daterange": "2025-01-01 00:00:00 - 2025-01-31 23:59:59", "group_ext": null } }

6.2 Outbound Performance

GET/api/reporting/outPerformance
ParameterTypeRequiredDescription
daterangestringNoDate range filter
user_extintNoFilter by user ID
Response 200
{ "summary": { "agents_count": 8, "total_calls": 320, "answered_calls": 210, "no_answer_calls": 70, "busy_calls": 25, "failed_calls": 15, "total_duration": "28:14:00", "avg_duration": "00:05:17", "total_talk_time": "22:08:00", "avg_talk_time": "00:06:19" }, "by_agent": [ { "agent_ext": "1001", "agent_name": "Agent Name", "agent_code": "1001", "total_calls": 40, "answered_calls": 28, "avg_talk_time": "00:05:50" } ], "by_date": [ { "call_date": "2025-01-15", "agent_ext": "1001", "total_calls": 12, "answered_calls": 9 } ], "filters": { "daterange": "2025-01-01 00:00:00 - 2025-01-31 23:59:59", "user_ext": null } }

7 Blacklist

7.1 List Blacklist

GET/api/reporting/blacklist
ParameterTypeRequiredDescription
searchstringNoFilter by phone number (partial match)
pageintNoDefault: 1
per_pageintNoDefault: 10
Response 200
{ "success": true, "data": { "current_page": 1, "data": [ { "number": "0501112233", "description": "Spam caller" }, { "number": "0509998877", "description": null } ], "total": 24, "per_page": 10, "last_page": 3 }, "total": 24 }

7.2 Add to Blacklist

POST/api/reporting/blacklistAdd
The number field is required. Returns 422 if missing. The value "1" is reserved and not allowed for desc.
Request Body
{ "number": "0509999999", "desc": "Spam caller" }
FieldTypeRequiredDescription
numberstringYesPhone number or CallerID to block
descstringNoHuman-readable reason. Value "1" is reserved.
Response 200
{ "success": true, "data": { "number": "0509999999" }, "message": "0509999999 Blocked Successfully" }

8 Call Recordings

8.1 List Calls with Recordings

GET/api/reporting/calls
ParameterTypeRequiredDescription
daterangestringNoDate range filter
searchstringNoFree-text search
pageintNoDefault: 1
Response 200
{ "success": true, "data": { "calls": { "current_page": 1, "data": [ { "linkedid": "1736929330.1452", "direction": "Inbound", "status": "Answered", "talktime_formatted": "01:45", "recording_path": "/api/reporting/listen/1736929330.1452" } ], "total": 214, "per_page": 10, "last_page": 22 }, "filters": { "daterange": "2025-01-15 00:00:00 - 2025-01-15 23:59:59", "search": null } }, "message": "Calls retrieved successfully" }

8.2 Stream a Recording

GET/api/reporting/listen/{id}
Returns the audio file as a stream (audio/wav). Use the listen_url field returned in call list responses.
cURL Download Example
curl -H "Authorization: Bearer $TOKEN" \ -o call.wav \ https://your-domain.com/api/reporting/listen/1736929330.1452
@can('leads.browse')

9 Leads API

9.1 List Leads

GET/api/leads/

Returns paginated lead records. Each item contains the complete lead object plus an optional index_fields array of pre-selected display values.

ParameterTypeDescription
searchstringSearches name, email, phone, mobile
lead_status_idint|csvFilter by status ID(s)
lead_source_idint|csvFilter by source ID(s)
lead_industry_idint|csvFilter by industry ID(s)
lead_rating_idint|csvFilter by rating ID(s)
email / phone / mobilestringPartial match
company_namestringPartial company name
created_from / created_toY-m-dDate range
per_pageintDefault 15
Response (each item)
{ "id": 42, "first_name": "Jane", "last_name": "Smith", "email": "jane@example.com", "lead_status_id": 1, "priority_score": 8, /* … all other fields … */ "index_fields": [ { "key": "full_name", "label": "Full Name", "value": "Jane Smith" } ] }

9.2 Get Lead

GET/api/leads/get/{id}
Response
{ "lead": { "id": 42, "first_name": "Jane", "last_name": "Smith", "lead_status_id": 1, "priority_score": 8, /* … all fields as flat keys … */ } }

9.3 Create Lead

POST/api/leads/create
Request body
{ "first_name": "Jane", "last_name": "Smith", "email": "jane@example.com", "lead_status_id": 1, "priority_score": 8 }

9.4 Update Lead

POST/api/leads/update/{id}

Send only the fields you want to change. All fields are optional.

9.5 Delete Lead

DELETE/api/leads/delete/{id}

Lookup helpers

GET/api/leads/all-statuses
GET/api/leads/all-sources
GET/api/leads/all-industries
GET/api/leads/all-ratings
@endcan @can('contacts.browse')

10 Contacts API

10.1 List Contacts

GET/api/contacts/

Returns paginated contact records with all fields as flat keys. The optional index_fields array provides pre-selected display values.

ParameterTypeDescription
searchstringSearches name, email, phone, mobile
contact_status_idint|csvFilter by status
contact_source_idint|csvFilter by source
email / phonestringPartial match
created_from / created_toY-m-dDate range
per_pageintDefault 15

10.2 Create / Update / Get / Delete

POST/api/contacts/create
POST/api/contacts/update/{id}
GET/api/contacts/get/{id}
DELETE/api/contacts/delete/{id}
Create request body
{ "first_name": "John", "last_name": "Doe", "email": "john@example.com", "phone": "01000000000", "contact_status_id": 1 }

Lookup helpers

GET/api/contacts/all-statuses
GET/api/contacts/all-sources
@endcan @can('calllogs.browse')

11 Call Logs API

All request fields are sent as flat top-level keys. Responses always return a uniform flat object — all field types are indistinguishable from the client perspective.

11.1 List Call Logs

GET/api/calllogs/
ParameterTypeDescription
searchstringSearches phone number, subject, notes
directionstringinbound | outbound
statusstringPartial match on call status
sourcestringPartial match on call source
outcomestringPartial match on call outcome
user_idint|csvFilter by agent user ID
lead_id / contact_idint|csvFilter by linked entity
call_date_from / call_date_toY-m-dCall date range
follow_up_from / follow_up_toY-m-dFollow-up date range
created_from / created_toY-m-dCreated date range
sort_bystringphone_number | call_date | status | source | outcome | created_at
sort_dirstringasc | desc (default desc)
per_pageintDefault 15

11.2 Get Call Log

GET/api/calllogs/get/{id}
Response
{ "call_log": { "id": 5, "phone_number": "01000000000", "direction": "inbound", "subject": "Support call", "status": "New", "call_rating": "Good", /* … all other fields … */ } }

11.3 Create / Update / Delete

POST/api/calllogs/create
POST/api/calllogs/update/{id}
DELETE/api/calllogs/delete/{id}
Create request body
{ "phone_number": "01000000000", "direction": "inbound", "call_date": "2026-07-16 10:00:00", "subject": "Support call", "status": "New", "lead_id": 42, "call_rating": "Good" }
For updates, all fields are optional. Send only the fields you want to change.
@endcan @can('tickets.browse')

12 Tickets API

All request fields are sent as flat top-level keys. Responses return a uniform flat object — all field types are indistinguishable from the client perspective.

12.1 List Tickets

GET/api/tickets/
ParameterTypeDescription
searchstringSearches name, description, notes and related entity names
ticket_status_idint|csv|arrayFilter by status
ticket_priority_idint|csv|arrayFilter by priority
ticket_severity_idint|csv|arrayFilter by severity
ticket_category_idint|csv|arrayFilter by category
contact_id / lead_id / account_idint|csvFilter by related entity
ticket_owner_idint|csvFilter by owner
namestringPartial text match
status_name / priority_name / category_namestringPartial match on related name
due_date_from / due_date_toY-m-dDue date range
created_from / created_toY-m-dCreated date range
sort_bystringid | name | due_date | created_at | ticket_status_id
sort_dirstringasc | desc (default desc)
per_pageintDefault 15

12.2 Get Ticket

GET/api/tickets/get/{id}
Response
{ "ticket": { "id": 9, "name": "Login page broken", "ticket_status_id": 1, "owned_by": "user-5", "internal_ref": "BUG-2026-001", /* … all other fields … */ } }

12.3 Create / Update / Delete

POST/api/tickets/create
POST/api/tickets/update/{id}
DELETE/api/tickets/delete/{id}
Create request body
{ "name": "Login page broken", "ticket_status_id": 1, "ticket_priority_id": 2, "contact_id": 7, "description": "Cannot log in since the 2026-07-15 deployment.", "internal_ref": "BUG-2026-001" }
For updates, all fields are optional. Send only the fields you want to change.

Lookup helpers

GET/api/tickets/all-statuses
GET/api/tickets/all-priorities
GET/api/tickets/all-severities
GET/api/tickets/all-categories
@endcan @can('sms.browse')

13 SMS API

13.1 Send SMS

POST/api/sms/send

Sends an SMS message and saves a record to the sms_msg table.

FieldTypeRequiredDescription
phone_numberstringYesDestination phone number (max 30 chars)
messagestringYesSMS text content (max 1000 chars)
cURL Example
curl -X POST https://your-domain.com/api/sms/send \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"phone_number":"01000000000","message":"Hello from API"}'
Response 200
{ "success": true, "data": { "sms_id": 123, "status": "Sent" }, "message": "SMS sent successfully" }
Response 500 (send failure)
{ "success": false, "data": { "sms_id": 123, "status": "Failed" }, "errors": { "error": "Failed to send SMS" }, "message": "Failed to send SMS" }
Requires the sms.create permission.

13.2 Check SMS Quota

GET/api/sms/quota

Returns the remaining SMS balance or credits from the configured provider.

cURL Example
curl -H "Authorization: Bearer $TOKEN" \ https://your-domain.com/api/sms/quota
Response
{ "success": true, "data": { "credits": 450 }, "message": "Quota fetched successfully" }
Requires the sms.browse permission.
@endcan @can('user.settings')

16 User Management

Users are managed with three endpoints. All of them require the same authentication as the rest of the API:
Authorization: Bearer <your_jwt_token>

16.1  List Users

GET/api/users
Query parameters
ParameterTypeRequiredDescription
per_pageintNoUsers per page (default 10)
Example
curl -H "Authorization: Bearer $TOKEN" \ "https://your-domain.com/api/users?per_page=10"
Response (200)
{ "success": true, "data": { "current_page": 1, "data": [ { "extension": 997, "first_name": "Ahmed", "last_name": "", "email": "ahmed@example.com", "server": "https://your-domain.com", "created_at": "2026-10-08 12:00:00" } ], "per_page": 10, "total": 1 } }

16.2  Create User

POST/api/users
Body
ParameterTypeRequiredDescription
namestringYesFull name
emailstringYesValid email address
passwordstringYesPassword
Example
curl -X POST https://your-domain.com/api/users \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"Ahmed","email":"ahmed@example.com","password":"Secret123"}'
Response (201)
{ "success": true, "message": "User created successfully.", "data": { "extension": 997, "name": "Ahmed", "first_name": "Ahmed", "last_name": "", "email": "ahmed@example.com", "server": "https://your-domain.com" } }
Save the returned user ID. The response contains our internal user ID in data.extension. Use it for later calls that take a user id, such as DELETE /api/users/{id}.
Validation error (422)
{ "success": false, "message": "Full Name is required. Valid Email is required.", "errors": [ "Full Name is required.", "Valid Email is required." ] }

16.3  Delete User

DELETE/api/users/{id}
Path parameters
ParameterTypeRequiredDescription
idintYesOur internal user ID (data.extension from create)
Example
curl -X DELETE https://your-domain.com/api/users/997 \ -H "Authorization: Bearer $TOKEN"
Response (200)
{ "success": true, "message": "User deleted successfully." }
Response (404)
{ "success": false, "message": "User not found." }
@endcan @can('help.softphone.integration')

17 External Client Softphone Integration

Embed our Softphone in your own page without asking the user to log in again. One fixed iframe URL is used for every user: https://your-domain.com/softphone/integration.

17.1  Step 1 — Configure the API URL and token

API URL — the base URL of our platform, for example https://your-domain.com.

Token — the user's API token from POST /api/login. Send it on every request below as Authorization: Bearer <token>. The token identifies the user, so you never send a user id.

Send us the exact origin of your page (for example https://app.customer.com) so we can allow-list it. The browser blocks the session request and refuses to display the iframe without it.
const API_URL = 'https://your-domain.com'; const token = '<user_api_token>'; // from POST /api/login

17.2  Step 2 — Request a session

POST/api/softphone/session

Call this from your front-end with the user's token. The response sets the session cookie and returns the iframe URL. No request body.

Request
Authorization: Bearer <user_api_token>
Response (201)
{ "success": true, "iframe_url": "https://your-domain.com/softphone/integration" }
Example
const res = await fetch(`${API_URL}/api/softphone/session`, { method: 'POST', credentials: 'include', // keeps the session cookie in the browser headers: { Authorization: `Bearer ${token}` } }); const { iframe_url } = await res.json();

17.3  Step 3 — Embed the iframe

Use the returned iframe_url. The cookie you just received signs the user in inside the iframe.

<iframe src="https://your-domain.com/softphone/integration" allow="microphone; autoplay" style="width:100%;height:100%;border:0;"> </iframe>

17.4  Step 4 — Revoke the session

POST/api/softphone/session/revoke

Closing the iframe does not end the session. Call this when the user logs out or leaves your page.

Request
Authorization: Bearer <user_api_token>
Response (200)
{ "success": true, "revoked": 1 }
@endcan

14 Error Reference

All responses share this envelope structure:
{ "status": true|false, "data": {}, "message": "...", "errors": [] }
StatusMeaning
200Success
401Invalid or missing token
403Insufficient permissions
404Record not found
422Missing or invalid parameters
500Server error — contact support

15 Route Summary

@can('user.settings') @endcan @can('leads.browse') @endcan @can('contacts.browse') @endcan @can('calllogs.browse') @endcan @can('tickets.browse') @endcan @can('sms.browse') @endcan @can('help.softphone.integration') @endcan
MethodEndpointDescription
POST/api/loginLogin and get access token
GET/api/usersList users
POST/api/usersCreate a user
DELETE/api/users/{id}Delete a user
GET/api/reporting/inboundList answered inbound calls
GET/api/reporting/inbound/{linkedid}/transfersGet transfer legs of a call
POST/api/reporting/inbound/done/{id}Mark inbound call as done
GET/api/reporting/inDistInbound call distribution
GET/api/reporting/outboundList outbound calls
POST/api/reporting/outbound/done/{id}Mark outbound call as done
GET/api/reporting/outDistOutbound call distribution
GET/api/reporting/missedList missed calls
GET/api/reporting/ring-details/{callid}Ring attempt history
POST/api/reporting/missed-done/{num}Mark missed caller as handled
GET/api/reporting/missed/statsMissed call type/reason stats
GET/api/reporting/attendanceAttendance event log
GET/api/reporting/attendance/summaryPer-agent attendance totals
GET/api/reporting/attendance/usersList company users
GET/api/reporting/attendance/groupsList company groups / queues
GET/api/reporting/performanceInbound queue performance
GET/api/reporting/outPerformanceOutbound agent performance
GET/api/reporting/blacklistList blacklisted numbers
POST/api/reporting/blacklistAddAdd number to blacklist
GET/api/reporting/callsList calls with recordings
GET/api/reporting/listen/{id}Stream recording audio file
CRM — Leads
GET/api/leads/Paginated lead list with API index fields
GET/api/leads/get/{id}Lead record with field metadata and values
POST/api/leads/createCreate a lead
POST/api/leads/update/{id}Update a lead
DELETE/api/leads/delete/{id}Delete a lead
GET/api/leads/all-statusesAvailable lead statuses
GET/api/leads/all-sourcesAvailable lead sources
GET/api/leads/all-industriesAvailable industries
GET/api/leads/all-ratingsAvailable ratings
CRM — Contacts
GET/api/contacts/Paginated contact list with API index fields
GET/api/contacts/get/{id}Contact record with field metadata
POST/api/contacts/createCreate a contact
POST/api/contacts/update/{id}Update a contact
DELETE/api/contacts/delete/{id}Delete a contact
GET/api/contacts/all-statusesAvailable contact statuses
GET/api/contacts/all-sourcesAvailable contact sources
CRM — Call Logs
GET/api/calllogs/Paginated call log list with API index fields
GET/api/calllogs/get/{id}Call log record with field metadata
POST/api/calllogs/createCreate a call log
POST/api/calllogs/update/{id}Update a call log
DELETE/api/calllogs/delete/{id}Delete a call log
CRM — Tickets
GET/api/tickets/Paginated ticket list with API index fields
GET/api/tickets/get/{id}Ticket record with field metadata
POST/api/tickets/createCreate a ticket
POST/api/tickets/update/{id}Update a ticket
DELETE/api/tickets/delete/{id}Delete (soft delete) a ticket
GET/api/tickets/all-statusesAvailable ticket statuses
GET/api/tickets/all-prioritiesAvailable ticket priorities
GET/api/tickets/all-severitiesAvailable ticket severities
GET/api/tickets/all-categoriesAvailable ticket categories
SMS
POST/api/sms/sendSend an SMS and save the record
GET/api/sms/quotaGet remaining SMS balance / credits
Integrations — External Client Softphone
POST/api/softphone/sessionCreate the browser session for the authenticated user
POST/api/softphone/session/revokeEnd the authenticated user's sessions
GET/softphone/integrationFixed iframe page (requires the authenticated session)