WEB API: Difference between revisions

From VoIPmonitor.org
(VG-3075: Document getVoipCalls response fields including new lastSIPresponseNum)
 
(80 intermediate revisions by 4 users not shown)
Line 1: Line 1:
= Custom Login =
= VoIPmonitor Web API =


== LDAP example ==
This page documents VoIPmonitor's Web APIs for programmatic access to CDR data, recordings, active calls, and system functions.


You can find complete LDAP example in GUI directory under scripts/ldap_custom_login_example.php
== Overview ==


== custom script ==
<kroki lang="mermaid">
%%{init: {'flowchart': {'nodeSpacing': 15, 'rankSpacing': 30}}}%%
flowchart LR
    subgraph Client
        A[Application]
    end
    subgraph API["API Endpoints"]
        B["/php/api.php"]
        C["/php/model/sql.php"]
    end
    subgraph Tasks
        E[getVoipCalls]
        F[getVoiceRecording]
        G[getPCAP]
        H[listActiveCalls]
        I[getShareURL]
    end
    A -->|user/password| B
    A -->|Session cookie| C
    B --> E & F & G & H & I
</kroki>


Custom login allows to implement your own login mechanism. You need to create file scripts/custom_login.php and function custom_login
{| class="wikitable"
|-
! API !! Endpoint !! Authentication !! Use Case
|-
| '''HTTP API 2''' || <code>/php/api.php</code> || user/password params || CDR queries, recordings, PCAP, active calls
|-
| '''CDR HTTP API''' || <code>/php/model/sql.php</code> || Session cookie || Advanced CDR filtering with GUI filters
|}


custom login script place in: <GUI_INSTALL_DIR>./scripts/custom_login.php  
{{Warning|1='''Correct path is critical:''' Always use <code>/php/api.php</code> (not <code>/api.php</code>). Missing the <code>/php/</code> directory causes "action parameter missing" errors.}}


<?php
== HTTP API 2 ==
function custom_login($user, $password) {
        debug_log('custom_login');
        return(array(
                'username' => $user,
                'is_admin' => false,
                'id' => $userIdUniqueNum,
                'enable_sensors' => array(2,3)
        ));
}
?>


The array can return those parameters:
Preferred API for programmatic access. Requests via HTTP POST or GET to <code>/php/api.php</code>.


*enable_sensors - array(A,B,...) where the number is number of the sensor. If no enable_sensors provided the user will see all sensors CDR.
=== Authentication ===
*username
*name
*secret
*id_group
*group_name
*group_blocked
*can_cdr
*can_write_cdr
*can_play_audio
*can_download_audio
*can_listen_active_call
*can_show_fax
*can_pcap
*can_upload_pcap
*can_messages
*can_view_content_message
*can_view_message_url
*is_admin
*no_rtp
*simple_cdr
*hide_cdr_groups
*can_graphs
*can_tracker
*can_activecalls
*can_register
*can_sip_msg
*can_livesniffer
*can_capture_rules
*crules_remove_expire_time
*can_audit
*can_alerts_edit
*can_alerts_show_sent
*can_reports_edit
*can_reports_show_sent
*can_cdr_share_local_public
*can_cdr_share_local_private
*can_cdr_share_voipmonitor_org
*hide_license_information
*can_ipacc
*can_mtr
*can_show_sql_query
*can_sensors_operations
*show_only_connected_calls
*can_dashboard
*dashboard_read_only
*can_report_functions
*hide_change_password
*hide_user_configuration
*password_expired
*can_svg_paint
*can_3d_rtp_charts
*can_network
*can_edit_codebooks
*can_edit_all_templates
*can_delete_all_templates
*ip
*number
*domain
*vlan
*custom_headers_cdr
*custom_headers_message
*ip_number_domain_or
*note
*email
*blocked
*blocked_reason
*max_bad_login_attempt
*password_expiration_days
*enable_login_ip
*uc_color_theme_shift_h
*uc_color_theme_shift_s
*uc_color_theme_shift_v
*uc_color_theme_shift
*uc_font_main_menu
*uc_disable_confirm_before_unload
*uc_enable_dns_cdr
*uc_enable_dns_message
*uc_enable_flags_cdr_number
*uc_enable_flags_cdr_ip
*uc_enable_flags_message_number
*uc_enable_flags_message_ip
*uc_csv_field_separator
*count_audit_log
*req_2fa


= CDR HTTP API =
Include <code>user</code> and <code>password</code> parameters in every request:


This method allows to get CDR rows formatted in JSON which you can see in the WEB GUI using the same filter which you can see in the WGB GUI: [[Call_Detail_Record_-_CDR#Filter_Form_button]]
<syntaxhighlight lang="bash">
curl 'http://server/php/api.php?task=getVoipCalls&user=USER&password=PASSWORD&params=...'
</syntaxhighlight>


You need to have valid session [[GUI_automate_login]] and you have to send those parameters via POST request
{{Note|1=API authentication uses local VoIPmonitor database credentials. It does NOT use LDAP or custom_login.php.}}


== INPUT ==
'''Rate Limiting:''' Enable in GUI > Settings > System Configuration > "API maximal concurrent connections".


HTTP POST address - php/model/sql.php
=== getVoipCalls ===


=== Mandatory parameters ===
Retrieve CDR records by search criteria.


task:LISTING module:CDR
'''Parameters:'''
{| class="wikitable"
fdatefrom:DATE or fdateto:DATE is required due to mysql overloading
|-
! Parameter !! Description
|-
| <code>startTime</code> || Calls starting >= this time (required)
|-
| <code>startTimeTo</code> || Calls starting <= this time
|-
| <code>callEnd</code> || Calls ending <= this time
|-
| <code>caller</code> / <code>called</code> || Caller/called number
|-
| <code>callId</code> || SIP Call-ID
|-
| <code>cdrId</code> || Database ID
|-
| <code>id_sensor</code> || Sensor number
|-
| <code>msisdn</code> || Match caller OR called (instead of AND)
|-
| <code>onlyConnected</code> || <code>1</code> = only answered calls
|-
| <code>customHeaders</code> || Comma-separated custom header names to return
|}


=== suppress_results ===
'''Examples:'''


suppress_results:1
<syntaxhighlight lang="bash">
# HTTP GET - by time range and caller
curl 'http://server/php/api.php?task=getVoipCalls&user=USER&password=PASSWORD&params={"startTime":"2024-01-01","startTimeTo":"2024-01-31","caller":"123456"}'


will not list CDR but only {"total":"135"}  
# HTTP POST - by Call-ID
echo '{"task":"getVoipCalls","user":"USER","password":"PASSWORD","params":{"startTime":"2024-01-01","callId":"abc123"}}' | curl -X POST -d @- http://server/php/api.php


=== Datetime range ===
# With custom headers
curl -G 'http://server/php/api.php?task=getVoipCalls&user=USER&password=PASSWORD' \
  --data-urlencode 'params={"startTime":"2024-01-01","caller":"123","customHeaders":"X-Custom-Header"}'
</syntaxhighlight>
'''Response fields:'''
{| class="wikitable"
|-
! Field !! Description
|-
| <code>cdrId</code> || Database CDR ID
|-
| <code>id_sensor</code> || Sensor ID
|-
| <code>calldate</code> / <code>callend</code> || Call start/end time
|-
| <code>duration</code> / <code>connect_duration</code> || Total / connected duration
|-
| <code>caller</code> / <code>called</code> || Caller/called numbers
|-
| <code>sipcallerip</code> / <code>sipcalledip</code> || SIP endpoint IPs
|-
| <code>codec_a</code> / <code>codec_b</code> || Audio codecs
|-
| <code>lastSIPresponseNum</code> || '''(New in 2026.1)''' Final SIP response code (e.g., 200, 404, 503)
|-
| <code>callId</code> || SIP Call-ID
|}
=== getVoiceRecording ===


fdatefrom:1986-01-09T00:00:00 fdateto:2013-05-28T00:00:00
Download audio recording (WAV format).


=== Caller / called numbers ===
'''Parameters:'''
{| class="wikitable"
|-
! Parameter !! Description
|-
| <code>cdrId</code> || Database CDR ID (preferred)
|-
| <code>callId</code> || SIP Call-ID
|-
| <code>calldate</code> || Date hint (default: today)
|-
| <code>zip</code> || <code>true</code> = return ZIP archive
|-
| <code>ogg</code> || <code>true</code> = return OGG format
|-
| <code>saveaudio_afterconnect</code> || <code>"yes"</code> = audio only after call connect
|}


fcaller: caller num
'''Examples:'''
fcalled: called num
fcallerd_type: 0 (if type is 0 searching is done for fcaller OR fcalled and value is taken from fcaller. If value is 1 searching is done for fcaller AND fcalled)


<syntaxhighlight lang="bash">
# By CDR ID
curl 'http://server/php/api.php?task=getVoiceRecording&user=USER&password=PASSWORD&params={"cdrId":12345}' > call.wav


=== Domain ===
# By Call-ID
fcaller_domain: caller domain fcalled_domain: caller domain
curl 'http://server/php/api.php?task=getVoiceRecording&user=USER&password=PASSWORD&params={"callId":"abc123"}' > call.wav
fcallerd_domain_type:0 (if type is 0 searching is done for fcaller OR fcalled and value is taken from fcaller. If value is 1 searching is done for fcaller AND fcalled)


=== Caller id name ===
# Multiple recordings (returns ZIP)
echo '{"task":"getVoiceRecording","user":"USER","password":"PASSWORD","params":{"cdrId":[6,7]}}' | php api.php > calls.zip
</syntaxhighlight>


fcallername: caller name
=== getPCAP ===
=== SIP caller / called IP ===


fsipcallerip: caller SIP IP fsipcalledip: called SIP IP
Download PCAP file. Automatically merges multiple legs and returns ZIP if needed.
fsipcallerdip_type:0 (if type is 0 searching is done for fcaller OR fcalled and value is taken from fcaller. If value is 1 searching is done for fcaller AND fcalled)
=== RTP source / destination IP ===


'''Parameters:'''
{| class="wikitable"
|-
! Parameter !! Description
|-
| <code>cdrId</code> || Database CDR ID
|-
| <code>callId</code> || SIP Call-ID
|-
| <code>cidInterval</code> || Time window (seconds) to search for matching Call-ID
|-
| <code>cidMerge</code> || <code>true</code> = merge multiple legs
|-
| <code>zip</code> || <code>true</code> = force ZIP output
|}


fa_saddr: 192.168.0.1
'''Examples:'''
fb_saddr: 192.168.0.2
fab_saddr_type:0 (if type is 0 searching is done for fcaller OR fcalled and value is taken from fcaller. If value is 1 searching is done for fcaller AND fcalled)


=== Codecs ===
<syntaxhighlight lang="bash">
# By CDR ID
curl 'http://server/php/api.php?task=getPCAP&user=USER&password=PASSWORD&params={"cdrId":"12345"}' > call.pcap


fcodec: 4, 12
# By Call-ID with merge
list of numbers delimited by ','. Here is list of numbers and its codecs
curl -G 'http://server/php/api.php?task=getPCAP&user=USER&password=PASSWORD' \
  --data-urlencode 'params={"callId":"abc123","cidInterval":60,"cidMerge":true}'
</syntaxhighlight>


define("PAYLOAD_PCMU", 0); define("PAYLOAD_GSM", 3); define("PAYLOAD_G723", 4); define("PAYLOAD_PCMA", 8); define("PAYLOAD_G722", 9); define("PAYLOAD_QCELP", 12); define("PAYLOAD_CN", 13); define("PAYLOAD_G729", 18); define("PAYLOAD_ILBC", 97); define("PAYLOAD_SPEEX", 98); define("PAYLOAD_SILK", 301); define("PAYLOAD_SILK8", 302); define("PAYLOAD_SILK12", 303); define("PAYLOAD_SILK16", 304); define("PAYLOAD_SILK24", 305); define("PAYLOAD_ISAC", 306); define("PAYLOAD_ISAC16", 307); define("PAYLOAD_ISAC32", 308); define("PAYLOAD_T38", 1000);
{{Tip|Use <code>curl -G --data-urlencode</code> for complex JSON params to avoid encoding issues.}}
=== Call duration ===
example: less than 30 and greater than 10 seconds


fdurationgt: 30 fdurationlt: 10
=== listActiveCalls ===


=== PDD ===
Get currently active calls from sensor.


example: greater than 10 and less than 30 seconds
'''Parameters:''' <code>sensorId</code> (optional), <code>callId</code> (optional)
fpddgt: 10 fpddlt: 30


=== Sip response code ===
<syntaxhighlight lang="bash">
fsipresponse: 503
curl 'http://server/php/api.php?task=listActiveCalls&user=USER&password=PASSWORD&params={"sensorId":"1"}'
</syntaxhighlight>


=== Interrupted call ===
{{Note|1=IP addresses in response are integers. Convert with <code>INET_NTOA()</code> in MySQL or equivalent in your code.}}


false or true
=== handleActiveCall ===


fbye:false
Pause/unpause RTP recording on active call.
Direction (by trunk)


false or true
'''Parameters:'''
* <code>sensorId</code> - Sensor number
* <code>command</code> - <code>pausecall</code> or <code>unpausecall</code>
* <code>callRef</code> - Call reference from listActiveCalls


ftrunk:
<syntaxhighlight lang="bash">
curl 'http://server/php/api.php?task=handleActiveCall&user=USER&password=PASSWORD&params={"sensorId":"1","command":"pausecall","callRef":"0x7f0e4c3c2680"}'
</syntaxhighlight>


SIP user agent
=== getShareURL ===
fa_ua: caller agent string fb_ua: called agent string
fab_ua_type:0 (if type is 0 searching is done for fcaller OR fcalled and value is taken from fcaller. If value is 1 searching is done for fcaller AND fcalled)
SIP Call-ID header
fcallid: string


SIP sensor ID (database ID)
Generate public shareable link for a CDR.
fsensor_id:


'''Parameters:'''
{| class="wikitable"
|-
! Parameter !! Description
|-
| <code>callId</code> or <code>cdrId</code> || Call identifier
|-
| <code>cidInterval</code> || Time window for Call-ID search
|-
| <code>rtp</code> || <code>true</code> = include RTP data
|-
| <code>sip_history</code> || <code>true</code> = SIP history only (no RTP)
|-
| <code>anonIps</code> || <code>true</code> = anonymize IPs
|-
| <code>validDays</code> || Link validity in days
|}


<syntaxhighlight lang="bash">
curl 'http://server/php/api.php?task=getShareURL&user=USER&password=PASSWORD&params={"callId":"abc123","rtp":true,"validDays":15}'
</syntaxhighlight>


=== Paging ===
=== reportSummary ===


page:1 start:0 limit:30
Generate pre-configured summary report as image or JSON.


=== Ordering ===
{{Warning|1=Reports must be created in '''GUI → Reports → Daily Report''' BEFORE using the API. The <code>report_name</code> parameter must match the report's Description field.}}


sort:[{"property":"calldate2","direction":"DESC"}]
'''Parameters:'''
* <code>report_name</code> - Description field from GUI report
* <code>datetime_from</code> / <code>datetime_to</code> - Date range
* <code>json</code> - <code>true</code> = return JSON instead of image


<syntaxhighlight lang="bash">
curl 'http://server/php/api.php?task=reportSummary&user=USER&password=PASSWORD&params={"report_name":"Daily Summary","datetime_from":"2024-01-01","datetime_to":"2024-01-31"}'
</syntaxhighlight>


=== Special Ordering ===
=== Other Tasks ===
orderByLoss: orderByDelay: orderByFixed1: orderByFixed2: orderByAdapt: orderByCallDuration_asc: orderByCallDuration_desc: orderBySrcSIP_IP_asc: orderBySrcSIP_IP_desc: orderByDstSIP_IP_asc: orderByDstSIP_IP_desc: orderBySrcNumber_asc: orderBySrcNumber_desc: orderByDstNumber_asc: orderByDstNumber_desc: orderByCallerName_asc: orderByCallerName_desc: orderByLastSIPrespNum_asc: orderByLastSIPrespNum_desc:
=== RTP ===
frtcp_maxjitter: frtcp_avgjitter: frtcp_maxfr: frtcp_avgfr: fmosf1: fmosf2: fmosadapt: f_d50: f_d70: f_d90: f_d120: f_d150: f_d200: f_d300: floss1: floss2: floss3: floss4: floss5: floss6: floss7: floss8: floss9: floss10: ffilterTemplate:


== OUTPUT ==
{| class="wikitable"
Output is JSON formated array of CDR  
|-
=== GUI is in default DocumentRoot location ===
! Task !! Description
Example /var/www/html
|-
| <code>listCdrIds</code> || List CDR IDs with basic info. Params: <code>offset</code>, <code>size</code>
|-
| <code>getAudioGraph</code> || Get spectrogram/waveform image. Params: <code>cdrId</code>, <code>type</code> (S/P/ALL), <code>side</code> (L/R)
|}


curl -X POST '192.168.76.201/php/model/sql.php?module=bypass_login&user=voipmonitor&pass=voipmonitor'
== CDR HTTP API ==


returns something like this
Session-based API using GUI filter parameters. Requires login first.


{"SID":"ahs2ubdhc0ukb262be60v900ko","cookie_name":"PHPSESSID","success":true,"_vm_version":240034,"_debug":false}
=== Authentication ===


take the SID which you will put to cookie_name variable
<syntaxhighlight lang="bash">
# Step 1: Login and get session
curl -X POST 'http://server/php/model/sql.php?module=bypass_login&user=USER&pass=PASSWORD'
# Returns: {"SID":"abc123...","cookie_name":"PHPSESSID","success":true}


curl -X POST -k --cookie "PHPSESSID=ahs2ubdhc0ukb262be60v900ko" "http://192.168.76.201/php/model/sql.php?task=LISTING&module=CDR&fdatefrom=2013-05-08T00:00:00&fcaller=190"
# Step 2: Use session cookie for requests
curl -X POST --cookie "PHPSESSID=abc123..." \
  'http://server/php/model/sql.php?task=LISTING&module=CDR&fdatefrom=2024-01-01T00:00:00&fcaller=123'
</syntaxhighlight>


{{Note|1=If GUI is in subdirectory (e.g., <code>/demo</code>), cookie name changes to <code>PHPSESSID-demo</code>.}}


=== GUI is in demo subdirectory ===
'''Disable authorization:''' GUI > Settings > System Configuration > "Disable authorization for API usage"
Example /var/www/html/demo


curl -X POST '192.168.76.201/demo/php/model/sql.php?module=bypass_login&user=voipmonitor&pass=voipmonitor'
=== Filter Parameters ===


returns something like this
'''Mandatory:''' <code>task=LISTING</code>, <code>module=CDR</code>, and at least one of <code>fdatefrom</code> or <code>fdateto</code>.


{"SID":"ahs2ubdhc0ukb262be60v900ko","cookie_name":"PHPSESSID-demo","success":true,"_vm_version":240034,"_debug":false}
{| class="wikitable"
|-
! Parameter !! Description !! Example
|-
| <code>fdatefrom</code> / <code>fdateto</code> || Date range || <code>2024-01-01T00:00:00</code>
|-
| <code>fcaller</code> / <code>fcalled</code> || Caller/called number || <code>123456</code>
|-
| <code>fcallerd_type</code> || <code>0</code>=OR, <code>1</code>=AND || <code>1</code>
|-
| <code>fcaller_domain</code> / <code>fcalled_domain</code> || SIP domain || <code>sip.example.com</code>
|-
| <code>fsipcallerip</code> / <code>fsipcalledip</code> || SIP IP address || <code>192.168.1.1</code>
|-
| <code>fcallid</code> || SIP Call-ID || <code>abc123</code>
|-
| <code>fsipresponse</code> || SIP response code || <code>503</code>
|-
| <code>fdurationgt</code> / <code>fdurationlt</code> || Duration (seconds) || <code>10</code>
|-
| <code>fsensor_id</code> || Sensor ID || <code>1</code>
|-
| <code>fcodec</code> || Codec numbers (comma-sep) || <code>0,8</code>
|-
| <code>suppress_results</code> || <code>1</code>=count only || <code>1</code>
|}


take the SID which you will put to cookie_name variable
'''Paging:''' <code>page</code>, <code>start</code>, <code>limit</code>


curl -X POST -k --cookie "PHPSESSID-demo=ahs2ubdhc0ukb262be60v900ko" "http://192.168.76.201/demo/php/model/sql.php?task=LISTING&module=CDR&fdatefrom=2013-05-08T00:00:00&fcaller=190"
'''Sorting:''' <code>sort=[{"property":"calldate","direction":"DESC"}]</code>


=== Example Output for the LISTING task ===
{{Warning|1=Use <code>=</code> (equals) for parameters, not <code>:</code> (colon). Example: <code>fcallerd_type=1</code> (correct), not <code>fcallerd_type:1</code> (wrong).}}


{"total":"25","results":[{"lastSIPresponseNum":"200","lastSIPresponse_id":"3","cnt_all":"110011","duration_all":"5388692","acd_all":"49.3737","asr_all":"99.2092","mos_all":"4.36034442","packets_lost_all":"0.15386185","jitter_all":"1.03656707","delay_all":"116.5833","cnt_ok":null,"cnt_err":null,"lastSIPresponse":"200 OK","id":"200 OK"},{"lastSIPresponseNum":"487","lastSIPresponse_id":"27","cnt_all":"535","duration_all":"256","acd_all":"6.2439","asr_all":"7.6636","mos_all":"3.67647059","packets_lost_all":"0.05965854","jitter_all":"1.00000000","delay_all":"0.5042","cnt_ok":null,"cnt_err":null,"lastSIPresponse":"487 Request Terminated","id":"487 Request Terminated"}]}
=== Wildcards ===


= Share CDR =
Use <code>%25</code> (URL-encoded <code>%</code>) for SQL LIKE patterns:


Sharing CDR is possible by sending request to php/model/utilities.php with following parameteres. If you want to share SIP+RTP set type2 to "rtp" and if only SIP set type2:null
<syntaxhighlight lang="bash">
# Caller starting with "00"
curl -G 'http://server/php/api.php?task=getVoipCalls&user=USER&password=PASSWORD' \
  --data-urlencode 'params={"startTime":"2024-01-01","caller":"%2500%25"}'
</syntaxhighlight>


== show link local public ==
=== Codec Values ===


task=shareCdr&params={"type":"share_cdr_show","type2":null,"subType":"self_protected_link","id":[128024514],"emailFields":null}
{| class="wikitable"
|-
! Value !! Codec !! Value !! Codec
|-
| 0 || PCMU (G.711 μ-law) || 8 || PCMA (G.711 A-law)
|-
| 3 || GSM || 9 || G.722
|-
| 4 || G.723 || 12 || QCELP
|-
| 18 || G.729 || 97 || iLBC
|-
| 98 || Speex || 301-305 || SILK variants
|-
| 306-308 || iSAC variants || 1000 || T.38 (Fax)
|}


=== RTP Quality Filters ===


== show link local private ==
{| class="wikitable"
|-
! Parameter !! Description
|-
| <code>fmosf1</code>, <code>fmosf2</code>, <code>fmosadapt</code> || MOS score filters
|-
| <code>frtcp_maxjitter</code>, <code>frtcp_avgjitter</code> || RTCP jitter
|-
| <code>frtcp_maxfr</code>, <code>frtcp_avgfr</code> || RTCP frame rate
|-
| <code>floss1</code> - <code>floss10</code> || Packet loss distribution
|-
| <code>f_d50</code>, <code>f_d70</code>, <code>f_d90</code>, ... || Delay distribution (50ms, 70ms, etc.)
|}


== Utility Endpoints ==


task=shareCdr&params={"type":"share_cdr_show","type2":null,"subType":"self_login_link","id":[128024514],"emailFields":null}
=== Direct PCAP Download ===


<syntaxhighlight lang="bash">
curl 'http://server/php/pcap.php?id=12345'          # Full PCAP
curl 'http://server/php/pcap.php?id=12345&disable_rtp=1'  # SIP only
</syntaxhighlight>


=== CDR URL for Browser ===


== show link share.voipmonitor.org ==
<syntaxhighlight lang="text">
http://server/admin.php?cdr_filter={fcallid:"abc123"}
</syntaxhighlight>


=== SIP History ===


task=shareCdr&params={"type":"share_cdr_show","type2":null,"subType":"share_link","id":[128024590],"emailFields":null}
Requires session authentication first.


= get PCAP file =  
<syntaxhighlight lang="bash">
# JSON data
curl --cookie "PHPSESSID=..." 'http://server/php/pcap2text.php?action=brief_data&id=12345'


To get pcap file send GET or POST request with id of the CDR:
# HTML table
curl --cookie "PHPSESSID=..." 'http://server/php/pcap2text.php?action=brief&id=12345'


http://voipmonitor/php/pcap.php?id=203800251
# MSC diagram
curl --cookie "PHPSESSID=..." 'http://server/php/pcap2text.php?action=getMSC&id=12345'
</syntaxhighlight>


optinaly RTP can be filtered out by adding parameter disable_rtp=1
=== License Check ===


= Search CDR by URL =
<syntaxhighlight lang="bash">
# Basic license check
curl 'http://server/php/apilicensecheck.php?task=licenseCheck'


If you would like to build URL which will show CDR in web browser matching filter you can use cdr_filter parameter for admin.php
# Concurrent calls limit check
curl 'http://server/php/apilicensecheck.php?task=licenseCallsLimitCheck'
</syntaxhighlight>


http://localhost/admin.php?cdr_filter={fcallid:"uDR8mtloKFa1F8625VL2OXSFp.RuG73v"}
== Share CDR Configuration ==


cdr_filter takes the same arguments like in section [[WEB_API#CDR_HTTP_API]]
=== Share Link Types ===


= HTTP API 2 =
Use <code>/php/model/utilities.php</code> with <code>task=shareCdr</code>:


This API was created for getting audio files based on various search criteria. Requests are over HTTP POST or GET
{| class="wikitable"
|-
! Type !! subType !! Description
|-
| Local Public || <code>self_protected_link</code> || Password-protected local link
|-
| Local Private || <code>self_login_link</code> || Requires GUI login
|-
| voipmonitor.org || <code>share_link</code> || Public via share.voipmonitor.org
|}


== getVoipCalls ==
=== Custom Branding ===


=== Input data ===
'''Product Name:''' Edit <code>config/system_configuration.php</code>:
<syntaxhighlight lang="php">
define('BRAND_NAME', 'YourCompany');
</syntaxhighlight>


*startTime - all calls which started >= startTime
'''Share Domain:''' Edit <code>brand.php</code> to use your domain instead of share.voipmonitor.org:
*startTimeTo - all calls which started <= startTimeTo (not mandatory)
<syntaxhighlight lang="php">
*callEnd - all calls which ends <= callEnd (not mandatory)
define('BRAND_SHARESITE', 'share.yourdomain.com');
*caller - caller number
define('BRAND_DOMAIN', 'yourdomain.com');
*called - called number
</syntaxhighlight>
*onlyConnected - 0 or 1 - get only connected calls or all calls (ringing)


task: getVoipCalls,
== Custom Login (LDAP/SSO) ==
user: USER,
password: PASSWORD,
params: {
  startTime: YYYY-MM-DD HH:II:SS,
  startTimeTo: YYYY-MM-DD HH:II:SS,
  callEnd: YYYY-MM-DD HH:II:SS,
  caller: 9999999,
  called: 9999999
}


=== Examples ===
Custom authentication via <code>scripts/custom_login.php</code>. This applies to GUI login only, NOT to API authentication.
==== HTTP POST Simple parameter ====
echo '{"task": "getVoipCalls", "user": "USER", "password": "PASSWORD", "params": {"startTime": "2013-01-01", "endTime": "2013-08-01", "caller": "910251414"}}' | php php/api.php
==== HTTP POST Array parameter ====
echo '{"task": "getVoipCalls", "user": "USER", "password": "PASSWORD", "params": [{"startTime": "2013-01-01", "endTime": "2013-08-01", "caller": "910251414"},{"startTime": "2013-01-01", "endTime": "2013-08-01", "caller": "910251415"}]}' | php php/api.php       
==== HTTP GET Simple parameter ====
http://localhost/php/api.php?task=getVoipCalls&user=USER&password=PASSWORD&params={"startTime":"2013-01-01","endTime":"2013-08-01","caller":"910251414"}
==== HTTP GET Array parameter ====
http://localhost/php/api.php?task=getVoipCalls&user=USER&password=PASSWORD&params=[{"startTime":"2013-01-01","endTime":"2013-08-01","caller":"910251414"},{"startTime":"2013-01-01","endTime":"2013-08-01","caller":"910251415"}]


== getVoiceRecording by Cdr ID ==
=== Basic Structure ===


=== input data ===
<syntaxhighlight lang="php">
task: getVoiceRecording,
<?php
user: USER,
function custom_login($user, $password) {
password: PASSWORD,
    // Authenticate against external system (LDAP, etc.)
params: {  cdrId: 999999 }
    // ...
}


optional parameters - zip, ogg (true|false)  
    return array(
        'username' => $user,
        'id' => $uniqueNumericId,  // REQUIRED: Must be unique per user!
        'is_admin' => false,
        'id_group' => 1,          // Optional: GUI group ID
        'enable_sensors' => array(1,2,3)  // Optional: restrict to sensors
    );
}
?>
</syntaxhighlight>


=== Examples ===
{{Warning|1='''The <code>id</code> field MUST be unique per user.''' If multiple users return the same ID, they share ALL settings (timezone, dashboard, etc.). Use LDAP <code>uidnumber</code> or <code>crc32($email)</code> for uniqueness.}}
=== HTTP POST ====
echo '{"task": "getVoiceRecording", "user": "USER", "password": "PASSWORD", "params": {"cdrId": "4919"}}' | php api.php


==== HTTP GET ====
=== LDAP Example ===
http://localhost/php/api.php?task=getVoiceRecording&user=USER&password=PASSWORD&params={"cdrId":4919}


== getVoiceRecording by Call ID ==
See <code>scripts/ldap_custom_login_example.php</code> in GUI directory.


=== input data ===
'''Requirements:''' <code>php-ldap</code> package installed.
task: getVoiceRecording,
user: USER,
password: PASSWORD,
params: {  callId: 'XXXXXXXXXXXXXXXXXXXXXX' }}


task: getVoiceRecording,
'''Debug from CLI:'''
user: USER,
<syntaxhighlight lang="bash">
password: PASSWORD,
cd /var/www/html/scripts/
params: {  customHeader: 'name of the column in cdr_next table', customHeaderValue: 'your value', calldate: '2015-03-01' }}
php custom_login.php
</syntaxhighlight>


=== examples ===
Enable debug by uncommenting the debug block at top of script.
==== HTTP POST ====
echo '{"task": "getVoiceRecording", "user": "USER", "password": "PASSWORD", "params": {"callId": "XXXXXXXXXXXXXXXXXXXXXX"}}' | php api.php


==== HTTP GET ====
=== Troubleshooting ===
http://localhost/php/api.php?task=getVoiceRecording&user=USER&password=PASSWORD&params={"callId":"XXXXXXXXXXXXXXXXXXXXXX"}
http://localhost/php/api.php?task=getVoiceRecording&user=USER&password=PASSWORD&params={"callId":"XXXXXXXXXXXXXXXXXXXXXX","cidInterval":10}
== listActiveCalls ==


=== input data ===
'''Users share settings:''' Return unique <code>id</code> per user (see warning above).
task: listActiveCalls,
user: USER,
password: PASSWORD,
params: {  sensorId: 'sensor number' }


sensorId je optional.
'''LDAP users can't view CDRs:''' Ensure <code>is_admin => false</code> and correct <code>id_group</code> is returned.


=== examples ===
'''Script being deleted:''' GUI antivirus deletes scripts with <code>shell_exec()</code>, <code>exec()</code>, etc.
==== HTTP POST ====
echo '{"task": "listActiveCalls", "user": "USER", "password": "PASSWORD", "params": {"sensorId": "1"}}' | php api.php


==== HTTP GET ====
'''Solutions:'''
http://localhost/php/api.php?task=listActiveCalls&user=USER&password=PASSWORD&params={"sensorId":"1"}
# Disable antivirus in <code>config/system_configuration.php</code>:
<syntaxhighlight lang="php">
define('DISABLE_ANTIVIRUS', true);
</syntaxhighlight>
# Or move shell commands to external file outside web directory and <code>require_once()</code> it.


== handleActiveCall ==
=== Azure AD / Microsoft SSO ===


=== input data ===
For Microsoft Entra ID integration, see [[Microsoft_Sign_in_usage]]. For Google, see [[Google_Sign_in_usage]].
task: handleActiveCall,
user: USER,
password: PASSWORD,
params: {
  sensorId: 'sensor number',
  command: 'command (can be only pausecall/unpausecall now)',
  callRef: 'call reference'
}


=== examples ===
=== Return Array Parameters ===
==== HTTP POST ====
echo '{"task": "handleActiveCall", "user": "USER", "password": "PASSWORD", "params": {"sensorId": "1","command":"pausecall","callRef":"0x7f0e4c3c2680"}}' | php api.php


==== HTTP GET ====
Full list of available return parameters for custom_login:
http://localhost/php/api.php?task=handleActiveCall&user=USER&password=PASSWORD&params={"sensorId":"1","command":"pausecall","callRef":"0x7f0e4c3c2680"}


== reportSummary ==
<div class="mw-collapsible mw-collapsed">
Following allows You to get report like this. (api call suports all the subtypes highlighted with brown)
<syntaxhighlight lang="text">
username, name, id, id_group, group_name, is_admin, email
enable_sensors - array of sensor IDs user can access
can_cdr, can_write_cdr, can_play_audio, can_download_audio
can_listen_active_call, can_pcap, can_upload_pcap
can_messages, can_view_content_message, can_graphs
can_activecalls, can_register, can_sip_msg, can_livesniffer
can_capture_rules, can_audit, can_alerts_edit, can_reports_edit
can_dashboard, can_ipacc, can_mtr, can_sensors_operations
can_network, can_edit_codebooks, hide_license_information
ip, number, domain, vlan (user restrictions)
custom_headers_cdr, custom_headers_message
blocked, blocked_reason, req_2fa
</syntaxhighlight>
</div>


[[File:report_summary.png]]
== See Also ==


=== input data ===
* [[Call_Detail_Record_-_CDR#Filter_Form_button|CDR Filter Form]] - GUI filter options
task: reportSummary,
* [[Active_calls|Active Calls]] - Active calls monitoring
user: USER,
* [[User_Management|User Management]] - User permissions
password: PASSWORD,
* [[Google_Sign_in_usage|Google Sign-In]] - Google OAuth setup
params: {
* [[Microsoft_Sign_in_usage|Microsoft Sign-In]] - Azure AD setup
    report_name: name / description of report (only CDR reports allowed),
    datetime_from: datetime from
    datetime_to: datetime to,
    json: true / false
}


=== examples ===
==== HTTP POST ====
echo '{"task": "reportSummary", "user": "USER", "password": "PASSWORD", "params": {"report_name": "test summary", "datetime_from": "2017-12-20", "datetime_to": "2017-12-20"}}' | php api.php


==== HTTP GET ====
== AI Summary for RAG ==
http://localhost/php/api.php?task=reportSummary&user=USER&password=PASSWORD&params={"report_name":"test summary","datetime_from":"2017-12-20","datetime_to":"2017-12-20"}


== getShareURL ==
'''Summary:''' VoIPmonitor Web API reference with two main APIs: (1) HTTP API 2 at <code>/php/api.php</code> using user/password authentication for tasks like getVoipCalls, getVoiceRecording, getPCAP, listActiveCalls, getShareURL, handleActiveCall, reportSummary; (2) CDR HTTP API at <code>/php/model/sql.php</code> using session cookies with full GUI filter support. Critical: correct endpoint path is <code>/php/api.php</code> (not <code>/api.php</code>). reportSummary requires pre-configured reports in GUI. Custom login via <code>scripts/custom_login.php</code> enables LDAP/SSO - requires unique numeric ID per user to avoid shared settings. Antivirus may delete scripts with shell_exec - disable with DISABLE_ANTIVIRUS or move to external file. Branding: BRAND_NAME for product name, BRAND_SHARESITE/BRAND_DOMAIN in brand.php for custom share domain.
will return you the public link where LEGs by CID for given call will be displayed. If '''sip_history''' option is true then only SIP history is displayed (rtp option is ignored).
=== examples ===
==== HTTP GET (with RTP) ====
http://localhost/php/api.php?task=getShareURL&user=USER&password=PASSWORD&params={"callId":"1502262225","cidInterval":60,"rtp":true}
http://localhost/php/api.php?task=getShareURL&user=USER&password=PASSWORD&params={"callId":"1502262225","rtp":true}
==== HTTP GET (only SIP) ====
http://localhost/php/api.php?task=getShareURL&user=USER&password=PASSWORD&params={"callId":"1502262225","cidInterval":60}
http://localhost/php/api.php?task=getShareURL&user=USER&password=PASSWORD&params={"callId":"1502262225"}
==== HTTP GET (SIP history) ====
http://localhost/php/api.php?task=getShareURL&user=USER&password=PASSWORD&params={"callId":"1502262225","cidInterval":60, "sip_history": true}
http://localhost/php/api.php?task=getShareURL&user=USER&password=PASSWORD&params={"callId":"1502262225","sip_history": true}


== getPCAP ==
'''Keywords:''' web api, http api, api.php, sql.php, getVoipCalls, getVoiceRecording, getPCAP, getShareURL, listActiveCalls, reportSummary, handleActiveCall, CDR filter, custom login, LDAP, authentication, session, curl, JSON, branding, BRAND_NAME, BRAND_SHARESITE, antivirus, DISABLE_ANTIVIRUS, unique user id, uidnumber
will return you the pcap file (with merged other legs in case there were more legs(CDR) in the given interval for the call)


=== examples ===
'''Key Questions:'''
==== HTTP GET (with RTP) ====
* What is the correct VoIPmonitor API endpoint path?
http://localhost/php/api.php?task=getPCAP&user=USER&password=PASSWORD&params={"callId":"1502262225"}
* How do I retrieve CDRs via the VoIPmonitor API?
http://localhost/php/api.php?task=getPCAP&user=USER&password=PASSWORD&params={"callId":"1502262225","cidInterval":60}
* How to download PCAP or voice recordings via API?
http://localhost/php/api.php?task=getPCAP&user=USER&password=PASSWORD&params={"callId":"1502262225","cidInterval":60,"cidMerge":true}
* How to list active calls via API?
http://localhost/php/api.php?task=getPCAP&user=USER&password=PASSWORD&params={"callId":"1502262225","cidInterval":60,"cidMerge":true,"zip":true}
* How to generate reports via API?
 
* How to configure LDAP authentication for VoIPmonitor?
= direct links =
* Why do LDAP users share settings? (need unique ID)
 
* Why is custom_login.php being deleted? (antivirus)
 
* How to customize VoIPmonitor branding?
Active calls - index.php?activecalls=1&hidegrid=1&hidemenu=1
* What's the difference between api.php and sql.php?
 
* How to use wildcards in API filter parameters?
.

Latest revision as of 12:16, 19 January 2026

VoIPmonitor Web API

This page documents VoIPmonitor's Web APIs for programmatic access to CDR data, recordings, active calls, and system functions.

Overview

API Endpoint Authentication Use Case
HTTP API 2 /php/api.php user/password params CDR queries, recordings, PCAP, active calls
CDR HTTP API /php/model/sql.php Session cookie Advanced CDR filtering with GUI filters

⚠️ Warning: Correct path is critical: Always use /php/api.php (not /api.php). Missing the /php/ directory causes "action parameter missing" errors.

HTTP API 2

Preferred API for programmatic access. Requests via HTTP POST or GET to /php/api.php.

Authentication

Include user and password parameters in every request:

curl 'http://server/php/api.php?task=getVoipCalls&user=USER&password=PASSWORD&params=...'

ℹ️ Note: API authentication uses local VoIPmonitor database credentials. It does NOT use LDAP or custom_login.php.

Rate Limiting: Enable in GUI > Settings > System Configuration > "API maximal concurrent connections".

getVoipCalls

Retrieve CDR records by search criteria.

Parameters:

Parameter Description
startTime Calls starting >= this time (required)
startTimeTo Calls starting <= this time
callEnd Calls ending <= this time
caller / called Caller/called number
callId SIP Call-ID
cdrId Database ID
id_sensor Sensor number
msisdn Match caller OR called (instead of AND)
onlyConnected 1 = only answered calls
customHeaders Comma-separated custom header names to return

Examples:

# HTTP GET - by time range and caller
curl 'http://server/php/api.php?task=getVoipCalls&user=USER&password=PASSWORD&params={"startTime":"2024-01-01","startTimeTo":"2024-01-31","caller":"123456"}'

# HTTP POST - by Call-ID
echo '{"task":"getVoipCalls","user":"USER","password":"PASSWORD","params":{"startTime":"2024-01-01","callId":"abc123"}}' | curl -X POST -d @- http://server/php/api.php

# With custom headers
curl -G 'http://server/php/api.php?task=getVoipCalls&user=USER&password=PASSWORD' \
  --data-urlencode 'params={"startTime":"2024-01-01","caller":"123","customHeaders":"X-Custom-Header"}'

Response fields:

Field Description
cdrId Database CDR ID
id_sensor Sensor ID
calldate / callend Call start/end time
duration / connect_duration Total / connected duration
caller / called Caller/called numbers
sipcallerip / sipcalledip SIP endpoint IPs
codec_a / codec_b Audio codecs
lastSIPresponseNum (New in 2026.1) Final SIP response code (e.g., 200, 404, 503)
callId SIP Call-ID

getVoiceRecording

Download audio recording (WAV format).

Parameters:

Parameter Description
cdrId Database CDR ID (preferred)
callId SIP Call-ID
calldate Date hint (default: today)
zip true = return ZIP archive
ogg true = return OGG format
saveaudio_afterconnect "yes" = audio only after call connect

Examples:

# By CDR ID
curl 'http://server/php/api.php?task=getVoiceRecording&user=USER&password=PASSWORD&params={"cdrId":12345}' > call.wav

# By Call-ID
curl 'http://server/php/api.php?task=getVoiceRecording&user=USER&password=PASSWORD&params={"callId":"abc123"}' > call.wav

# Multiple recordings (returns ZIP)
echo '{"task":"getVoiceRecording","user":"USER","password":"PASSWORD","params":{"cdrId":[6,7]}}' | php api.php > calls.zip

getPCAP

Download PCAP file. Automatically merges multiple legs and returns ZIP if needed.

Parameters:

Parameter Description
cdrId Database CDR ID
callId SIP Call-ID
cidInterval Time window (seconds) to search for matching Call-ID
cidMerge true = merge multiple legs
zip true = force ZIP output

Examples:

# By CDR ID
curl 'http://server/php/api.php?task=getPCAP&user=USER&password=PASSWORD&params={"cdrId":"12345"}' > call.pcap

# By Call-ID with merge
curl -G 'http://server/php/api.php?task=getPCAP&user=USER&password=PASSWORD' \
  --data-urlencode 'params={"callId":"abc123","cidInterval":60,"cidMerge":true}'

💡 Tip: Use curl -G --data-urlencode for complex JSON params to avoid encoding issues.

listActiveCalls

Get currently active calls from sensor.

Parameters: sensorId (optional), callId (optional)

curl 'http://server/php/api.php?task=listActiveCalls&user=USER&password=PASSWORD&params={"sensorId":"1"}'

ℹ️ Note: IP addresses in response are integers. Convert with INET_NTOA() in MySQL or equivalent in your code.

handleActiveCall

Pause/unpause RTP recording on active call.

Parameters:

  • sensorId - Sensor number
  • command - pausecall or unpausecall
  • callRef - Call reference from listActiveCalls
curl 'http://server/php/api.php?task=handleActiveCall&user=USER&password=PASSWORD&params={"sensorId":"1","command":"pausecall","callRef":"0x7f0e4c3c2680"}'

getShareURL

Generate public shareable link for a CDR.

Parameters:

Parameter Description
callId or cdrId Call identifier
cidInterval Time window for Call-ID search
rtp true = include RTP data
sip_history true = SIP history only (no RTP)
anonIps true = anonymize IPs
validDays Link validity in days
curl 'http://server/php/api.php?task=getShareURL&user=USER&password=PASSWORD&params={"callId":"abc123","rtp":true,"validDays":15}'

reportSummary

Generate pre-configured summary report as image or JSON.

⚠️ Warning: Reports must be created in GUI → Reports → Daily Report BEFORE using the API. The report_name parameter must match the report's Description field.

Parameters:

  • report_name - Description field from GUI report
  • datetime_from / datetime_to - Date range
  • json - true = return JSON instead of image
curl 'http://server/php/api.php?task=reportSummary&user=USER&password=PASSWORD&params={"report_name":"Daily Summary","datetime_from":"2024-01-01","datetime_to":"2024-01-31"}'

Other Tasks

Task Description
listCdrIds List CDR IDs with basic info. Params: offset, size
getAudioGraph Get spectrogram/waveform image. Params: cdrId, type (S/P/ALL), side (L/R)

CDR HTTP API

Session-based API using GUI filter parameters. Requires login first.

Authentication

# Step 1: Login and get session
curl -X POST 'http://server/php/model/sql.php?module=bypass_login&user=USER&pass=PASSWORD'
# Returns: {"SID":"abc123...","cookie_name":"PHPSESSID","success":true}

# Step 2: Use session cookie for requests
curl -X POST --cookie "PHPSESSID=abc123..." \
  'http://server/php/model/sql.php?task=LISTING&module=CDR&fdatefrom=2024-01-01T00:00:00&fcaller=123'

ℹ️ Note: If GUI is in subdirectory (e.g., /demo), cookie name changes to PHPSESSID-demo.

Disable authorization: GUI > Settings > System Configuration > "Disable authorization for API usage"

Filter Parameters

Mandatory: task=LISTING, module=CDR, and at least one of fdatefrom or fdateto.

Parameter Description Example
fdatefrom / fdateto Date range 2024-01-01T00:00:00
fcaller / fcalled Caller/called number 123456
fcallerd_type 0=OR, 1=AND 1
fcaller_domain / fcalled_domain SIP domain sip.example.com
fsipcallerip / fsipcalledip SIP IP address 192.168.1.1
fcallid SIP Call-ID abc123
fsipresponse SIP response code 503
fdurationgt / fdurationlt Duration (seconds) 10
fsensor_id Sensor ID 1
fcodec Codec numbers (comma-sep) 0,8
suppress_results 1=count only 1

Paging: page, start, limit

Sorting: sort=[{"property":"calldate","direction":"DESC"}]

⚠️ Warning: Use = (equals) for parameters, not : (colon). Example: fcallerd_type=1 (correct), not fcallerd_type:1 (wrong).

Wildcards

Use %25 (URL-encoded %) for SQL LIKE patterns:

# Caller starting with "00"
curl -G 'http://server/php/api.php?task=getVoipCalls&user=USER&password=PASSWORD' \
  --data-urlencode 'params={"startTime":"2024-01-01","caller":"%2500%25"}'

Codec Values

Value Codec Value Codec
0 PCMU (G.711 μ-law) 8 PCMA (G.711 A-law)
3 GSM 9 G.722
4 G.723 12 QCELP
18 G.729 97 iLBC
98 Speex 301-305 SILK variants
306-308 iSAC variants 1000 T.38 (Fax)

RTP Quality Filters

Parameter Description
fmosf1, fmosf2, fmosadapt MOS score filters
frtcp_maxjitter, frtcp_avgjitter RTCP jitter
frtcp_maxfr, frtcp_avgfr RTCP frame rate
floss1 - floss10 Packet loss distribution
f_d50, f_d70, f_d90, ... Delay distribution (50ms, 70ms, etc.)

Utility Endpoints

Direct PCAP Download

curl 'http://server/php/pcap.php?id=12345'           # Full PCAP
curl 'http://server/php/pcap.php?id=12345&disable_rtp=1'  # SIP only

CDR URL for Browser

http://server/admin.php?cdr_filter={fcallid:"abc123"}

SIP History

Requires session authentication first.

# JSON data
curl --cookie "PHPSESSID=..." 'http://server/php/pcap2text.php?action=brief_data&id=12345'

# HTML table
curl --cookie "PHPSESSID=..." 'http://server/php/pcap2text.php?action=brief&id=12345'

# MSC diagram
curl --cookie "PHPSESSID=..." 'http://server/php/pcap2text.php?action=getMSC&id=12345'

License Check

# Basic license check
curl 'http://server/php/apilicensecheck.php?task=licenseCheck'

# Concurrent calls limit check
curl 'http://server/php/apilicensecheck.php?task=licenseCallsLimitCheck'

Share CDR Configuration

Share Link Types

Use /php/model/utilities.php with task=shareCdr:

Type subType Description
Local Public self_protected_link Password-protected local link
Local Private self_login_link Requires GUI login
voipmonitor.org share_link Public via share.voipmonitor.org

Custom Branding

Product Name: Edit config/system_configuration.php:

define('BRAND_NAME', 'YourCompany');

Share Domain: Edit brand.php to use your domain instead of share.voipmonitor.org:

define('BRAND_SHARESITE', 'share.yourdomain.com');
define('BRAND_DOMAIN', 'yourdomain.com');

Custom Login (LDAP/SSO)

Custom authentication via scripts/custom_login.php. This applies to GUI login only, NOT to API authentication.

Basic Structure

<?php
function custom_login($user, $password) {
    // Authenticate against external system (LDAP, etc.)
    // ...

    return array(
        'username' => $user,
        'id' => $uniqueNumericId,  // REQUIRED: Must be unique per user!
        'is_admin' => false,
        'id_group' => 1,           // Optional: GUI group ID
        'enable_sensors' => array(1,2,3)  // Optional: restrict to sensors
    );
}
?>

⚠️ Warning: The id field MUST be unique per user. If multiple users return the same ID, they share ALL settings (timezone, dashboard, etc.). Use LDAP uidnumber or crc32($email) for uniqueness.

LDAP Example

See scripts/ldap_custom_login_example.php in GUI directory.

Requirements: php-ldap package installed.

Debug from CLI:

cd /var/www/html/scripts/
php custom_login.php

Enable debug by uncommenting the debug block at top of script.

Troubleshooting

Users share settings: Return unique id per user (see warning above).

LDAP users can't view CDRs: Ensure is_admin => false and correct id_group is returned.

Script being deleted: GUI antivirus deletes scripts with shell_exec(), exec(), etc.

Solutions:

  1. Disable antivirus in config/system_configuration.php:
define('DISABLE_ANTIVIRUS', true);
  1. Or move shell commands to external file outside web directory and require_once() it.

Azure AD / Microsoft SSO

For Microsoft Entra ID integration, see Microsoft_Sign_in_usage. For Google, see Google_Sign_in_usage.

Return Array Parameters

Full list of available return parameters for custom_login:

username, name, id, id_group, group_name, is_admin, email
enable_sensors - array of sensor IDs user can access
can_cdr, can_write_cdr, can_play_audio, can_download_audio
can_listen_active_call, can_pcap, can_upload_pcap
can_messages, can_view_content_message, can_graphs
can_activecalls, can_register, can_sip_msg, can_livesniffer
can_capture_rules, can_audit, can_alerts_edit, can_reports_edit
can_dashboard, can_ipacc, can_mtr, can_sensors_operations
can_network, can_edit_codebooks, hide_license_information
ip, number, domain, vlan (user restrictions)
custom_headers_cdr, custom_headers_message
blocked, blocked_reason, req_2fa

See Also


AI Summary for RAG

Summary: VoIPmonitor Web API reference with two main APIs: (1) HTTP API 2 at /php/api.php using user/password authentication for tasks like getVoipCalls, getVoiceRecording, getPCAP, listActiveCalls, getShareURL, handleActiveCall, reportSummary; (2) CDR HTTP API at /php/model/sql.php using session cookies with full GUI filter support. Critical: correct endpoint path is /php/api.php (not /api.php). reportSummary requires pre-configured reports in GUI. Custom login via scripts/custom_login.php enables LDAP/SSO - requires unique numeric ID per user to avoid shared settings. Antivirus may delete scripts with shell_exec - disable with DISABLE_ANTIVIRUS or move to external file. Branding: BRAND_NAME for product name, BRAND_SHARESITE/BRAND_DOMAIN in brand.php for custom share domain.

Keywords: web api, http api, api.php, sql.php, getVoipCalls, getVoiceRecording, getPCAP, getShareURL, listActiveCalls, reportSummary, handleActiveCall, CDR filter, custom login, LDAP, authentication, session, curl, JSON, branding, BRAND_NAME, BRAND_SHARESITE, antivirus, DISABLE_ANTIVIRUS, unique user id, uidnumber

Key Questions:

  • What is the correct VoIPmonitor API endpoint path?
  • How do I retrieve CDRs via the VoIPmonitor API?
  • How to download PCAP or voice recordings via API?
  • How to list active calls via API?
  • How to generate reports via API?
  • How to configure LDAP authentication for VoIPmonitor?
  • Why do LDAP users share settings? (need unique ID)
  • Why is custom_login.php being deleted? (antivirus)
  • How to customize VoIPmonitor branding?
  • What's the difference between api.php and sql.php?
  • How to use wildcards in API filter parameters?