Cisco CallManager 3.3(3) AXL API Programming Guide

NOTE: To access all AXL SOAP API downloads and AXL requests and responses found in this document, please refer to the following url:

http://www.cisco.com/warp/public/570/avvid/voice_ip/axl_soap/axl_api_down.html

# 1 Introduction

The AVVID XML Layer (AXL) Application Programming Interface (API) provides a mechanism for inserting, retrieving, updating, and removing data from the database using an eXtensible Markup Language (XML) Simple Object Access Protocol (SOAP) interface. This allows a programmer to access Cisco CallManager data using XML and receive the data in XML form, instead of using a binary library or DLL.

The AXL API methods, known as requests, are performed using a combination of HTTP and SOAP. SOAP is an XML remote procedure call protocol. Users perform requests by sending XML data to the Cisco CallManager server. The server then returns the AXL response, which is also a SOAP message.

## 1.1 Target Audience for this Guide

This programming guide is designed for fairly experienced developers who would like access to one or more of the following items:

· Cisco CallManager data

· Cisco CallManager data in XML format

· Cisco CallManager data in a platform-independent manner

This guide assumes the developer has knowledge of a high-level programming language such as C++, Java, or an equivalent language. The developer must also have knowledge or experience in the following areas:

· TCP/IP Protocol

· Hypertext Transport Protocol

· Socket programming

· XML

In addition, the users of the AXL API and this programming guide must have a firm grasp of XML Schema, which was used to define the AXL requests, responses, and errors. For more information on XML Schema, please refer to http://www.w3.org/TR/xmlschema-0/.

## Caution

The AXL API gives enormous power to developers to modify the CallManager system database. The developer must take caution when using AXL, since each API call impacts the system. Abuse of the API can lead to dropped calls and slower system performance. Because AXL is not intended as a real-time feature activation API, for example, as an application that intends to change call forwarding for many phones in a campus during lunch or at the end of the day (such as, forwarding to voice mail); you can use it as a provisioning and configuration API.

# 2 AXL API

Request methods are XML structures that are passed to the AXL API server. The server receives the XML structures and executes the request. If the request completes successfully, then the appropriate AXL response is returned. All responses are named identically to the associated requests, except that the word “Response” has been appended.

For example, the XML response returned from an addPhone request is called addPhoneResponse.

If an error occurs, then an XML error structure is returned wrapped inside of a SOAP Fault structure (see Section 2.2 AXL Error Codes).

## 2.1 AXL Methods

Table 1 lists all the available AXL requests and the associated responses. Click HERE for more detailed information on the contents of the request/response.

The Server Impact column is a sample measuring of the time (in milliseconds) it takes for the AXL server to handle the request. These figures should only be used as a guideline, and can drastically change due to cluster configuration, hardware configuration, and the size of the database.

The database used for these tests had the following entries:

· 1 Conference Bridge

· 2 CTI Route Points

· 2 Media Termination Points

· 1 Music On Hold

· 61 Phones

· 1 Route List

· 2 Call Pick Up Groups

· 2 Call Parks

· 1 Conference

· 74 Directory Numbers

· 1 Route Pattern

· All Cisco services running

Table 1- AXL Requests and Responses

Category | Requests | Responses | Server Impact
CallManagers | addCallManager | addCallManagerResponse | 1031
updateCallManager | updateCallManagerResponse | 2484
getCallManager | getCallManagerResponse | 125
removeCallManager | removeCallManagerResponse | 203
CallManager Group | addCallManagerGroup | addCallManagerGroupResponse | 609
updateCallManagerGroup | updateCallManagerGroupResponse | 125
getCallManagerGroup | getCallManagerGroupResponse | 93
removeCallManagerGroup | removeCallManagerGroupResponse | 141
Call Park | addCallPark | addCallParkResponse | 500
updateCallPark | updateCallParkResponse | 531
getCallPark | getCallParkResponse | 125
removeCallPark | removeCallParkResponse | 1468
Call Pickup Groups | addCallPickupGroup | addCallPickupGroupResponse | 1656
updateCallPickupGroup | updateCallPickupGroupResponse | 391
getCallPickupGroup | getCallPickupGroupResponse | 93
removeCallPickupGroup | removeCallPickupGroupResponse | 266
Calling Search Spaces | addCSS | addCSSResponse | 234
updateCSS | updateCSSResponse | 532
getCSS | getCSSResponse | 78
removeCSS | removeCSSResponse | 78
listCSSByName | listCSSByNameResponse | 187
CTI Route Points | addCTIRoutePoint | addCTIRoutePointResponse | 297
updateCTIRoutePoint | updateCTIRoutePointResponse | 672
getCTIRoutePoint | getCTIRoutePointResponse | 156
removeCTIRoutePoint | removeCTIRoutePointResponse | 422
Device Pools | addDevicePool | addDevicePoolResponse | 1109
updateDevicePool | updateDevicePoolResponse | 406
getDevicePool | getDevicePoolResponse | 157
removeDevicePool | removeDevicePoolResponse | 218
Device Profiles | addDeviceProfile | addDeviceProfileResponse | 906
updateDeviceProfile | updateDeviceProfileResponse | 1047
getDeviceProfile | getDeviceProfileResponse | 141
removeDeviceProfile | removeDeviceProfileResponse | 594
Dial Plan Tags | addDialPlanTag | addDialPlanTagResponse | 94
updateDialPlanTag | updateDialPlanTagResponse | 94
getDialPlanTag | getDialPlanTagResponse | 32
removeDialPlanTag | removeDialPlanTagResponse | 172
Dial Plans | addDialPlan | addDialPlanResponse | 62
updateDialPlan | updateDialPlanResponse | 188
getDialPlan | getDialPlanResponse | 31
removeDialPlan | removeDialPlanResponse | 438
Digit Discard Instructions | addDDI | addDDIResponse | 250
updateDDI | updateDDIResponse | 344
getDDI | getDDIResponse | 78
removeDDI | removeDDIResponse | 188
Directory Numbers | addLine | addLineResponse | 250
updateLine | updateLineResponse | 282
getLine | getLineResponse | 125
removeLine | removeLineResponse | 188
Gateways (Analog, T1, PRI) | addGatewayEndpoint | addGatewayEndpointResponse | 1938
updateGatewayEndpoint | updateGatewayEndpointResponse | 1078
getGatewayEndpoint | getGatewayEndpointResponse | 407
removeGatewayEndpoint | removeGatewayEndpointResponse | 265
Locations | addLocation | addLocationResponse | 93
updateLocation | updateLocationResponse | 141
getLocation | getLocationResponse | 47
removeLocation | removeLocationResponse | 79
MGCP | addMGCP | addMGCPResponse |
updateMGCP | updateMGCPResponse | 391
getMGCP | getMGCPResponse | 375
removeMGCP | removeMGCPResponse | 1469
addMGCPUnit | addMGCPUnitResponse |
removeMGCPUnit | removeMGCPUnitResponse |
addMGCPSubunit | addMGCPSubunitResponse |
removeMGCPSubunit | removeMGCPSubunitResponse |
addMGCPEndpoint | addMGCPEndpointResponse |
removeMGCPEndpoint | removeMGCPEndpointResponse |
Phones | addPhone | addPhoneResponse | 1234
updatePhone | updatePhoneResponse | 1765
getPhone | getPhoneResponse | 422
removePhone | removePhoneResponse | 344
listPhoneByName | listPhoneByNameResponse | 47
listPhoneByDescription | listPhoneByDescriptionResponse | 94
Process Nodes | addProcessNode | addProcessNodeResponse |
updateProcessNode | updateProcessNodeResponse |
getProcessNode | getProcessNodeResponse |
removeProcessNode | removeProcessNodeResponse |
listAllProcessNodes | listAllProcessNodesResponse |
listProcessNodesByService | listProcessNodesByServiceResponse |
Process Node Services | updateProcessNodeService | updateProcessNodeServiceResponse |
getProcessNodeService | getProcessNodeServiceResponse |
Regions | addRegion | addRegionResponse | 218
updateRegionMatrix | updateRegionMatrixResponse | 156
getRegion | getRegionResponse | 94
removeRegion | removeRegionResponse | 156
Route Filters | addRouteFilter | addRouteFilterResponse | 282
updateRouteFilter | updateRouteFilterResponse | 782
getRouteFilter | getRouteFilterResponse | 93
removeRouteFilter | removeRouteFilterResponse | 156
Route Groups | addRouteGroup | addRouteGroupResponse | 594
updateRouteGroup | updateRouteGroupResponse |
getRouteGroup | getRouteGroupResponse | 79
removeRouteGroup | removeRouteGroupResponse | 265
Route Lists | addRouteList | addRouteListResponse | 453
updateRouteList | updateRouteListResponse | 2672
getRouteList | getRouteListResponse | 171
removeRouteList | removeRouteListResponse | 1031
Route Partitions | addRoutePartition | addRoutePartitionResponse | 62
updateRoutePartition | updateRoutePartitionResponses | 156
getRoutePartition | getRoutePartitionResponse | 47
removeRoutePartition | removeRoutePartitionResponse | 93
Route Patterns | addRoutePattern | addRoutePatternResponse | 563
updateRoutePattern | updateRoutePatternResponse | 1094
getRoutePattern | getRoutePatternResponse | 281
removeRoutePattern | removeRoutePatternResponse | 187
listRoutePlanByType | listRoutePlanByTypeResponse | 1063
Service Parameters | updateServiceParameter | updateServiceParameterResponse | 390
getServiceParameter | getServiceParameterResponse | 125
listServiceParameters | listServiceParametersResponse | 94
System Methods | doDeviceLogin | doDeviceLoginResponse | 250
doDeviceLogout | doDeviceLogoutResponse | 110
doDeviceReset | doDeviceResetResponse | 157
createAutogeneratedProfile | createAutogeneratedProfileResponse | 344
getNumDevices | getNumDevicesResponse | 46
Translation Patterns | addTransPattern | addTransPatternResponse | 750
updateTransPattern | updateTransPatternResponse | 516
getTransPattern | getTransPatternResponse | 203
removeTransPattern | removeTransPatternResponse | 2203
listRoutePlanByType | listRoutePlanByTypeResponse | 1063
Users | addUser | addUserResponse |
updateUser | updateUserResponse |
getUser | getUserResponse | 281
removeUser | removeUserResponse |
listUserByName | listUserByNameResponse | 516
Voice Mail Ports | addVoiceMailPort | addVoiceMailPortResponse | 515
updateVoiceMailPort | updateVoiceMailPortResponse | 766
getVoiceMailPort | getVoiceMailPortResponse | 172
removeVoiceMailPort | removeVoiceMailPortResponse | 2437

## 2.2 AXL Error Codes

If an exception occurs on the server, or if any other error occurs during the processing of an AXL request, then an error is returned in the form of a SOAP Fault message:

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <SOAP-ENV:Body>
            <SOAP-ENV:Fault>
                <faultcode>SOAP-ENV:Client</faultcode>
                <faultstring>
                <![CDATA[
                An error occurred during parsing
                Message: End element was missing the character '>'.
                Source = Line : 41, Char : 6
                Code : c00ce55f, Source Text : </re
                ]]>
                </faultstring>
            </SOAP-ENV:Fault>
        </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

SOAP Fault messages can also contain more detailed information. The following is an example of a detailed SOAP Fault.

    <SOAP-ENV:Envelope  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" S
    OAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <SOAP-ENV:Body>
            <SOAP-ENV:Fault>
                <faultcode>SOAP-ENV:Client</faultcode>
                <faultstring>Device not found with name SEP003094C39708.</faultstring>
                <detail  xmlns:axl="http://www.cisco.com/AXL/1.0"
                         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                         xsi:schemaLocation="http://www.cisco.com/AXL/1.0
                                             http://myhost/CCMApi/AXL/V1/axlsoap.xsd">
                    <axl:error  sequence="1234">
                        <code>0</code>
                        <message>
    <![CDATA[
    Device not found with name SEP003094C39708.
    ]]>
                       </message>
                       <request>doDeviceLogin</request>
                   </axl:error>
               </detail>
            </SOAP-ENV:Fault>
        </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Error codes will be included in the <detail> element of a SOAP Fault. The errors are represented by the axl:Error element. If a response to a request contains an <error> element, the user agent can determine the cause of the error by looking at the sub-elements of the <error> tag.

The following list describes the <error> element.

· code

The <code> element is a numerical value that is used by the user agent to find out what type of error has occurred. The error codes are as follows:

Less than 5000: These are errors that directly correspond to DBL Exception error codes. Please refer to the documentation for the DBLException class for explanations of these errors.

5000: Unknown Error: An unknown error occurred while processing the request. This can be due to a problem on the server, but can also be caused by errors in the request.

5002: Unknown Request Error: This error occurs if the user agent submits a request that is unknown to the API.

5003: Invalid Value Exception: This error occurs if an invalid value is detected in the XML request.

5004: AXL Unavailable Exception: This error occurs if the AXL service is too busy to handle the request at that time. The request should be sent again at a later time.

5005: Unexpected Node Exception: This error occurs if the server encounters an unexpected element. For example, if the server expects the next node to be <name>, but encounters <protocol>, then this error is returned. These errors are always caused by malformed requests that do not adhere to the latest AXL Schema.

· message

The <message> element is provided so that the user agent gets a detailed error message explaining the error.

· request

The <request> element is provided so that the user agent can determine what type of request generated this error. This element is optional; therefore it may not always appear.

# 3 Examples

The following examples describe how to make an AXL request and read back the response to the request. Each SOAP request must be sent to the web server via an HTTP POST. The endpoint URL is an ISAPI Extension DLL. The following list contains the only four required HTTP headers.

· POST /CCMApi/AXL/V1/soapisapi.dll

The first header identifies that this particular POST is intended for the AXL SOAP API. The AXL API only responds to the POST method.

· content-type: text/xml

The second header confirms that the data being sent to AXL is XML. If this header is not found then an HTTP 415 error is returned to the client.

· Authorization: Basic <some Base 64 encoded string>

The third header is the Base64 encoding of the user name and password for the administrator of the AXL Server. If authentication of the user fails, then an HTTP 401 Access Denied error is returned to the client.

· content-length: <a positive integer>

The fourth header is the length (in bytes) of the AXL request.

Note: Currently, the content-length cannot exceed 40 kilobytes. If a request is received, which is greater than 40 kilobytes, then an `HTTP 413` error message is returned.

The following example contains an HTTP header for an AXL SOAP request:

    POST /CCMApi/AXL/V1/soapisapi.dll

    Host: axl.myhost.com:80

    Accept: text/*

    Authorization: Basic bGFycnk6Y3VybHkgYW5kIG1vZQ==

    Content-type: text/xml

    Content-length: 613

The following AXL request will be used in the code examples displayed in the following sections. This is an example of a getPhone request:

    POST /CCMApi/AXL/V1/soapisapi.dll
    Host: axl.myhost.com:80
    Accept: text/*
    Authorization: Basic bGFycnk6Y3VybHkgYW5kIG1vZQ==
    Content-type: text/xml
`Content-length: 613` `` <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <axl:getPhone xmlns:axl="http://www.cisco.com/AXL/1.0" xsi:schemaLocation="http://www.cisco.com/AXL/1.0 http:// myhost/schema/axlsoap.xsd" sequence="1234"> <phoneName>SEP222222222245</phoneName> </axl:getPhone> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

## 3.1 C/C++ Example

This code example uses a hard-coded AXL request and sends it to the AXL Server running on the local system (localhost). It then reads the response back, outputting the response to the screen.

#include <winsock2.h> // required for sockets #include <iostream> // required for console I/O #include <sstream> #include <string> // required for std::string using namespace std; int main(int argc, char* argv[]) { // make connection to server WSADATA WSAData; // initialize sockets if (int iError = WSAStartup (MAKEWORD(2,0), &WSAData)) { cout << "Windows Sockets startup error. Aborting." << endl; return -1; } SOCKET Socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (Socket == INVALID_SOCKET) { cout << "Socket creation error. Aborting." << endl; return -1; } SOCKADDR_IN sinRemote; sinRemote.sin_family = AF_INET; sinRemote.sin_port = htons (80) ; sinRemote.sin_addr.s_addr = inet_addr( "127.0.0.1" ); cout << "connecting to service" << endl; int retval = connect(Socket, (SOCKADDR *)&sinRemote, sizeof (sinRemote)); if (retval != 0) { cout << "Error occured while connecting to socket. Aborting." << endl; closesocket(Socket); return -1; } const int BUFSIZE = 2048; char buff[BUFSIZE]; // the temporary receive buffer string strHTTPHeader; // the HTTP Header string strAXLRequest; // the AXL SOAP request // The AXL request: getPhone strAXLRequest = “<SOAP-ENV:Envelope xmlns:SOAP- \ ENV=\”http://schemas.xmlsoap.org/soap/envelope/\” \ xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \ xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> \ <SOAP-ENV:Body> \ <axl:getPhone xmlns:axl=\"http://www.cisco.com/AXL/1.0\" \ xsi:schemaLocation=\"http://www.cisco.com/AXL/1.0 \ http:// myhost/schema/axlsoap.xsd\" sequence=\"1234\"> \ <phoneName>SEP222222222245</phoneName> \ </axl:getPhone> \ </SOAP-ENV:Body> \ </SOAP-ENV:Envelope>”; // temporarily use the buffer to store the length of the request sprintf(buff, “%d”, strAXLRequest.length()); // build the HTTP header strHTTPHeader = "POST /CCMApi/AXL/V1/soapisapi.dll\r\n \ Host: localhost:80\r\n \ Authorization: Basic `bGFycnk6Y3VybHkgYW5kIG1vZQ==\r\n \` Accept: text/*\r\n \ Content-type: text/xml\r\n \ Content-length: "; strHTTPHeader += buff; strHTTPHeader += “\r\n\r\n”; // put the HTTP header and SOAP XML together strAXLRequest = strHTTPHeader + strAXLRequest; // send these bytes to the socket retval = send (Socket, strAXLRequest.c_str(),strAXLRequest.length(), 0); if ( retval != SOCKET_ERROR) { // output response cout << "received response: " << endl; int iTotalRead = 0; // read BUFSIZE at a time, writing to another ostringstream do { iNumRead = recv (Socket, buff, BUFSIZE-1, 0); buff[iNumRead] = NULL; cout << buff; iTotalRead += iNumRead; } while (iNumRead == BUFSIZE-1); cout << "Read " << iTotalRead << " bytes." << endl; } else { cout << "An error occured while sending the data to socket." << endl; } // all finished, close socket closesocket(Socket); return 0; }

## 3.2 Java Example

This code example uses a hard-coded AXL request and sends it to the AXL Server running on the local system (localhost). It then reads the response back, outputting the response to the screen.

import java.io.*; import java.net.*; public class main { public static void main(String[] args) { //Declare references String sAXLSOAPRequest = null; // will hold the complete request, // HTTP header and SOAP payload String sAXLRequest = null; // will hold only the SOAP payload Socket socket = null; // socket to AXL server OutputStream out = null; // output stream to server InputStream in = null; // input stream from server byte[] bArray = null; // buffer for reading response from server // Build the HTTP Header sAXLSOAPRequest = "POST /CCMApi/AXL/V1/soapisapi.dll\r\n"; sAXLSOAPRequest += "Host: localhost:80\r\n"; sAXLSOAPRequest += "Authorization: Basic bGFycnk6Y3VybHkgYW5kIG1vZQ==\r\n"; sAXLSOAPRequest += "Accept: text/*\r\n"; sAXLSOAPRequest += "Content-type: text/xml\r\n"; sAXLSOAPRequest += "Content-length: "; // Build the SOAP payload sAXLRequest = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "; sAXLRequest += "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> "; sAXLRequest += "<SOAP-ENV:Body> <axl:getPhone xmlns:axl=\"http://www.cisco.com/AXL/1.0\" "; sAXLRequest += " xsi:schemaLocation=\"http://www.cisco.com/AXL/1.0 http:// myhost/schema/axlsoap.xsd\" "; sAXLRequest += "sequence=\"1234\"> <phoneName>SEP222222222245</phoneName> "; sAXLRequest += "</axl:getPhone> </SOAP-ENV:Body> </SOAP-ENV:Envelope>"; // finish the HTTP Header sAXLSOAPRequest += sAXLRequest.length(); sAXLSOAPRequest += "\r\n\r\n"; // now add the SOAP payload to the HTTP header, which completes the AXL SOAP request sAXLSOAPRequest += sAXLRequest; // now that the message has been built, we can connect to server and send it try { socket = new Socket("localhost", 80); out = socket.getOutputStream(); in = socket.getInputStream(); // send the request to the host out.write(sAXLSOAPRequest.getBytes()); // read the response from the host StringBuffer sb = new StringBuffer(2048); bArray = new byte[2048]; int ch = 0; int sum = 0; while ( (ch = in.read(bArray)) != -1 ) { sum += ch; sb.append(new String(bArray, 0, ch)); } socket.close(); // output the response to the standard out System.out.println(sb.toString()); } catch (UnknownHostException e) { System.err.println("Error connecting to host: " + e.getMessage()); return; } catch (IOException ioe) { System.err.println("Error sending/receiving from server: " + ioe.getMessage()); // close the socket try { if (socket != null) socket.close(); } catch (Exception exc) { System.err.println("Error closing connection to server: " + exc.getMessage()); } return; }

# 4 Throttling of Requests

The side-effects of updating the Cisco CallManager database can adversely affect system performance; therefore, the system administrator is capable of controlling how many AXL requests are allowed to update the database per minute. This value is controlled via the Database Layer service parameter “MaxAXLWritesPerMinute”.

AXL accommodates all requests until the “MaxAXLWritesPerMinute” value is reached. Subsequent attempts to modify the database with AXL will be rejected with an HTTP 503 Service Unavailable response. Every minute, AXL will reset its internal counter and begin to accept AXL update requests until the limit is reached again.

# 5 The AXL Schema Documentation

The AXL schema is attached as an HTML document, which graphically describes each request and response. The following legend explains the graphics used in the following example XML structure

## 5.1 Example XML Structure

## Request or Response | ## Element Name | ## Description
##  | ## Complex Element | ## A complex element can have child elements, as well as attributes. An element with a solid border is required to appear in an XML instance document.
##  | ## Simple Element | ## A simple element cannot have child elements but can have attributes. An element with a solid border is required to appear in an XML instance document.
##  | ## Optional Element | ## An optional element is not required to appear in an instance of the XML. Any type of element can be optional, including sequence and choice elements.
##  | ## Sequence Element | ## A sequence means that all children of this element must appear in the XML in the order that they are listed.
##  | ## Choice Element | ## A choice element means that only one of the children of this element can appear in the XML.

##

## 5.2 XML Interpretation of Graphic

The following is an XML instance of the addCallManager element.

Notice how the <autoregistration> element is not included. This is acceptable because it is defined as an optional element. Also, notice that <processNodeName> was chosen over <processNode>. Only one child of a choice element can appear in the XML.

Copyright © 2001-2003. Cisco Systems, Inc. All rights reserved.