CAM API v2.5 is compatible with Cherwell Asset Management v13.0 and higher.
The following changes were made to the API in v2.5.
The CAM API is a collection of web services that allows you to interchange data with external systems. Typical uses might involve:
The following services are provided:
CAM API v2.5 is for use with Cherwell Asset Management v13.0 and must be installed manually. IIS must also be configured manually. The API is delivered in a file called CAMAPI.zip which can be found in the CAM/ folder of the distribution .ZIP file.
To install the API:
CAM API v2.5 is for use with Cherwell Asset Management v13.0 and must be upgraded manually. The API is delivered in a file called CAMAPI.zip which can be found in the CAM/ folder of the distribution .ZIP file.
To upgrade the API:
CAM API is a collection of web services that structures information using REST design principles. This means:
The HTTP verbs GET, POST, PUT, and DELETE are used to tell the web service what it is you want to do. Query parameters and the HTTP message body provide the parametric data required.
For the GET request, you just provide a URI. The web service reads the query parameters you provide and returns the requested data if it can.
Each result returned contains a URI field that uniquely identifies each object.
The response is an HTTP status code 200 (OK) if the GET succeeded.
The POST request uses a URI to identify the kind of thing you want to create (such as order/purchase), and an XML message body (using the same schema generated by a GET) to provide the data to initialize the new object. The output of the POST is the XML that describes the new object, including the URI assigned by the system.
To add a new order with several line items, you would first create the order (purchase or lease) and remember its assigned URI. Then you would create any line items, filling in the line item's order URI with the URI of the new order. Then you would do the same for any line item details (serial numbers and assignments).
The response is an HTTP status code 201 (Created) if the POST succeeded.
To update existing data, you do a PUT and provide the URI of the record you want to update. You must also provide XML data with updated data for each field in the record. Fields without values will be set to a suitable default.
To guard against updating records that are out of date (have been modified since the last time you read them), there is a VersionStamp field. You must get the current record before updating it, because the update will fail if the VersionStamp doesn't match what is currently saved.
The PUT response is an XML representation of the updated record.
The response is an HTTP status code 200 (OK) if the PUT succeeded.
To delete something, you simply use a DELETE command with a URI that identifies the record to be deleted. Referential integrity rules will delete any other objects "owned" by what the system deletes.
The response is an HTTP status code 200 (OK) if the object was deleted successfully.
The web service provides and consumes data in XML. A few important notes:
Here is the XML data for a purchase:
<Purchase> <Uri>http://myserver/CAMAPI/Order.svc/Purchase/3</Uri> <VersionStamp>2</VersionStamp> <Date>2010-01-05</Date> <Description>Expiring maintenance test</Description> <OrderNumber>9290930293029039</OrderNumber> <AccessProfile>Purchasing Administrator</AccessProfile> <PONumber /> <TotalPrice>493.00000</TotalPrice> <Vendor> <Uri /> <Name>Cherwell Software</Name> </Vendor> <Notes /> <CreatedBy>Kathy</CreatedBy> <RelatedDocuments /> <CustomFields> <CustomField> <Name>Division</Name> <Type>Text</Type> <Required>False</Required> <Value /> </CustomField> </CustomFields> <LineItems> <Uri>http://myserver/CAMAPI/LineItem.svc/Software/License/219</Uri> <Uri>http://myserver/CAMAPI/LineItem.svc/Maintenance/Software/15</Uri> </LineItems> <InvoiceNumber>54-134</InvoiceNumber> </Purchase>
Orders are either purchases or leases. In this example each field is labeled with a tag, and references to other things, such as line items, are represented as URIs. The URI for the order itself is provided in the first URI tag. If you present any of these URIs to the web service you will get back whatever the URI addresses.
Here is an example of a software line item:
<SoftwareLineItem> <Uri>http://myserver/CAMAPI/LineItem.svc/Software/License/219</Uri> <VersionStamp>2</VersionStamp> <Order>http://myserver/CAMAPI/Order.svc/Purchase/3</Order> <ItemType>Software</ItemType> <Name>Microsoft Office</Name> <Quantity>3</Quantity> <UnitPrice>499.00000</UnitPrice> <Status /> <Contract>http://myserver/CAMAPI/Contract.svc/4</Contract> <Notes /> <CustomFields> <CustomField> <Name>Location</Name> <Type>Text</Type> <Required>False</Required> <Value /> </CustomField> </CustomFields> <Details> <Uri>http://myserver/CAMAPI/LineItemDetail.svc/Software/License/39410</Uri> </Details> <IncludesMaintenance>False</IncludesMaintenance> <Attributes> <Attribute> <Name>IncludesMaintenance</Name> <Description>Contract: Includes software maintenance (boolean)</Description> <Type>Boolean</Type> <Value>False</Value> </Attribute> </Attributes> <ManufacturerName>Microsoft Corporation</Manufacturer> <LicenseType>Per seat</LicenseType> <LicenseUnit> <Uri>http://myserver/CAMAPI/Inventory.svc/LicenseUnit/261</Uri> <Name>Microsoft Office</Name> <Type>License Unit</Type> <Manufacturer> <Uri>http://myserver/CAMAPI/Manufacturer.svc/199</Uri> <Name>Microsoft Corporation</Name> </Manufacturer> <LicenseType>Per seat</LicenseType> <Licenses>5</Licenses> <LastPerUnitCost>499.0000</LastPerUnitCost> </LicenseUnit> </SoftwareLineItem>
Each line item can itself be composed of a number of detail items. For example, a line item used to purchase five computers may have five detail records for the computers. Here is a line item detail for software:
<SoftwareDetail> <Uri>http://myserver/CAMAPI/LineItemDetail.svc/Software/License/39410</Uri> <VersionStamp>2</VersionStamp> <LineItem>http://myserver/CAMAPI/LineItem.svc/Software/License/219</LineItem> <Order>http://myserver/CAMAPI/Order.svc/Purchase/3</Order> <Quantity>1</Quantity> <SerialNumber>6493-2944-TOY1-1234</SerialNumber> <Assignment /> <AssignmentGroup /> <Notes /> <ReconciledWith /> <ActivationKey /> </SoftwareDetail>
And so forth. In each case the URI provides a unique reference to a record that the web service will retrieve when you do an HTTP GET operation.
The CAM API authenticates your requests to identify and verify who is sending the request. If you do not wish to authenticate, then you can edit the web.config file to turn off authentication. Search for "authenticationEnabled" and set its value to "false".
When authentication is enabled, you must provide the following items with each request so the request can be authenticated:
In the request header, you must send an authentication header containing your customer id and the request signature.
Authorization: <Customer ID>:<Signature>
You must also send a date header containing the timestamp. It can either be sent in the Date header or if you cannot set the Date header, then use the x-api-date header.
Date: <timestamp>
-or-
x-api-date: <timestamp>
To calculate your signature, do the following:
Example:
Request headers for the above example using evaluation customer ID:
x-apiversion: 2.5 Date: Mon, 28 Mar 2016 13:09:22 GMT Authorization: 0:f+BnSiuw2C3Xpz11yAtpAA==
Java Sample Code for Calculating HMAC-MD5 Signatures. Note: Strings passed into this function are expected to be UTF-8 encoded.
import java.security.SignatureException; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; public class Signature { public static String calculateHMAC(String data, String key) throws java.security.SignatureException { String result; try { // get an hmac_md5 key from the raw key bytes SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacMD5"); // get an hmac_md5 Mac instance and initialize with the signing key Mac mac = Mac.getInstance("HmacMD5"); mac.init(signingKey); // compute the hmac on input data bytes byte[] rawHmac = mac.doFinal(data.getBytes()); // base64-encode the hmac result = Base64.encode(rawHmac); } catch (Exception e) { throw new SignatureException("Failed to generate HMAC : " + e.getMessage()); } return result; } }
The CAM API checks to ensure that the version of the API that you are using is compatible with your client application. In the request header, send a version header called "x-apiversion" containing the API version number. This header is required and if it is not present or is not the same version as the CAM API, then you will get a 400 (Bad Request) response and the response data will contain the error.
General.svc does not check the version information.
Request header with version information:
x-apiversion: 2.5
When purchasing user profiles are enabled in the CAM Administrator, you can use access profiles in Purchasing to control who can view, edit, and create orders and contracts. A CAM API application is assumed to be the user "CAM-API" and if purchasing profiles are enabled, "CAM-API" must be a Purchasing administrator or CAM administrator, or in the Purchasing Administrator access profile.
If you add or update an order or contract through the CAM API and purchasing profiles are enabled you must specify an existing access profile. If purchasing profiles are disabled and you do not specify an access profile then it will be assigned to Purchasing Administrators.
For more information see the "Overview: Access profiles" topic in Purchasing help.
When a web service fails, detailed error descriptions will be returned in the response. Here is an example.
<ErrorCollection> <Error> <Field>Date</Field> <Message>Unable to convert date field.</Message> </Error> <Error> <Field>TotalPrice</Field> <Message>Field is not a currency or numeric value.</Message> </Error> <Error> <Field>Custom field value for "Order Number Test 765"</Field> <Message>Field is not a numeric value.</Message> </Error> <Error> <Field>InvoiceNumber</Field> <Message>The maximum length of the "InvoiceNumber" field is 256 characters.</Message> </Error> </ErrorCollection>
When doing a GET operation that returns a list of objects, the web service will accept and parse a particular set of query parameters. These are particularly useful when searching for an item or when paging through result sets. The query operations supported are:
The search parameter accepts a column name, a comparison operator, and a constant value to be compared against. For example:
http://myserver/CAMAPI/Order.svc/Purchase?search=vendor+notlike+cdw
In this case the request is to return all purchases whose vendor name is not like "CDW". (The comparison is case-insensitive.)
Columns of all types can be searched on (string, date, number, currency). The comparisons available include equality tests and pattern-matching like comparisons.
Operand | Meaning | Valid for these types | Example |
---|---|---|---|
empty | Returns record if the field is empty | String Date |
search=Description+empty |
notempty !empty |
Returns record if the field is not empty | String Date |
search= StartDate+notempty |
like | Returns record if the string specified is contained in the field | String | search=Description+like+Optiplex |
notlike !like |
Returns record if the string specified is not contained in the field | String | search=Description+notlike+Optiplex |
= eq |
Returns record if the field is equal to the parameter | String Number Currency Date License Type |
search=Quantity+eq+5 |
<> != ne |
Returns record if the field is not equal to the parameter | String Number Currency Date License Type |
search=UnitPrice+ne+100.00 |
< lt |
Returns record if the field is less than the parameter | Number Currency Date |
search=BuyoutDate+lt+2000-01-10 |
<= le |
Returns record if the field is less than or equal to the parameter | Number Currency Date |
search=BuyoutDate+le+2000-01-10 |
> gt |
Returns record if the field is greater than the parameter | Number Currency Date |
search=Quantity+gt+5 |
>= ge |
Returns record if the field is greater than or equal to the parameter | Number Currency Date |
search=UnitPrice+ge+100.00 |
Notes:
The orderby parameter accepts a column name and an optional direction. The following example lists all leases by lease end date in a descending order.
http://myserver/CAMAPI/Order.svc/Lease?orderby=enddate+desc
Notes:
The page and size parameters provide information about paging lists of results. The default page size is 10. The following example will return the fifth page of twenty results.
http://myserver/CAMAPI/LineItem.svc/Software?page=5&size=20
You can add values for custom fields in orders and line items through the CAM API. First you need to add the custom field definitions for either orders or line items in Purchasing. Then using either Order.svc or LineItem.svc you can create orders or line items and set the values for your custom fields. The values are Text, Number, Currency, Date, Shortcut, or List depending on your custom field definition.
This example will create a purchase. It will add a software line item and assign licenses to a machine group. You can also add software maintenance. In this example, Purchasing user policies are disabled so the access profile does not need to be set.
<Purchase> <Date>2010-01-05</Date> <Description>My order</Description> <OrderNumber>9290930293029039</OrderNumber> <PONumber /> <TotalPrice>493.00000</TotalPrice> <Vendor> <Uri /> <Name>Cherwell Software</Name> </Vendor> <Notes /> <CreatedBy>Kathy</CreatedBy> <RelatedDocuments /> <InvoiceNumber>54-134</InvoiceNumber> </Purchase>
<Purchase> <Uri>http://myserver/CAMAPI/Order.svc/Purchase/23163</Uri> <VersionStamp>1</VersionStamp> <Date>2010-01-05</Date> <Description>My order</Description> <OrderNumber>9290930293029039</OrderNumber> <AccessProfile>Purchasing Administrator</AccessProfile> <PONumber /> <TotalPrice>493.00000</TotalPrice> <Vendor> <Uri>http://myserver/CAMAPI/Manufacturer.svc/27</Uri> <Name>Cherwell Software</Name> </Vendor> <Notes /> <CreatedBy>Kathy</CreatedBy> <RelatedDocuments /> <CustomFields /> <LineItems /> <InvoiceNumber>54-134</InvoiceNumber> </Purchase>
Notice that the URI of the vendor was filled in because the name matched a manufacturer in the CAM database.
<SoftwareLineItem> <Order>http://myserver/CAMAPI/Order.svc/Purchase/23163</Order> <Name>Microsoft Office</Name> <Quantity>3</Quantity> <UnitPrice>500.00</UnitPrice> <Status></Status> <Notes></Notes> <ManufacturerName></ManufacturerName> <LicenseType>Unmanaged</LicenseType> </SoftwareLineItem>
If the Name matches an existing License Unit name, this line item will be automatically reconciled after it is created.
<SoftwareLineItem> <Uri>http://myserver/CAMAPI/LineItem.svc/Software/License/38075</Uri> <VersionStamp>1</VersionStamp> <Order>http://myserver/CAMAPI/Order.svc/Purchase/23163</Order> <ItemType>Software</ItemType> <Name><![CDATA[CAM Purchasing]]></Name> <Quantity>3</Quantity> <UnitPrice>500.00</UnitPrice> <Status /> <Notes /> <Details /> <ManufacturerName /> <LicenseType>Unmanaged</LicenseType> <LicenseUnit i:nil="true" /> </SoftwareLineItem>
Notice that the line item has not been reconciled yet. Reconciliation happens on a SQL trigger so you will need to GET the line item again (step 3) to see whether it has been reconciled or not.
<ItemCollection> <Group> <Uri>http://myserver/CAMAPI/Group.svc/Machine/327</Uri> <Type>Machine Group</Type> <Name><![CDATA[Marketing]]></Name> </Group> </ItemCollection>
<SoftwareDetail> <LineItem> http://myserver/CAMAPI/LineItem.svc/Software/License/38075 </LineItem> <Quantity>3</Quantity> <AssignmentGroup>http://myserver/CAMAPI/Group.svc/Machine/327</AssignmentGroup> </SoftwareDetail>
<SoftwareMaintenanceLineItem> <Order>http://myserver/CAMAPI/Order.svc/Purchase/23163</Order> <Name>Microsoft Office</Name> <Quantity>6</Quantity> <UnitPrice>100.00</UnitPrice> <Status> </Status> <Notes> </Notes> <Manufacturer> <Name>My manufacturer</Name> </Manufacturer> <StartDate>2011-03-11</StartDate> <EndDate>2012-03-10</EndDate> <ContractNumber> </ContractNumber> <ServiceDescription> </ServiceDescription> <MaintainedLicenseUnit> http://myserver/CAMAPI/Inventory.svc/LicenseUnit/162 </MaintainedLicenseUnit> </SoftwareMaintenanceLineItem>
<SoftwareMaintenanceLineItem> <Uri>http://myserver/CAMAPI/LineItem.svc/Maintenance/Software/66933</Uri> <VersionStamp>1</VersionStamp> <Order>http://myserver/CAMAPI/Order.svc/Purchase/23163</Order> <ItemType>Software Maintenance</ItemType> <Name>Microsoft Office</Name> <Quantity>6</Quantity> <UnitPrice>100.00000</UnitPrice> <Status/> <Notes/> <CustomFields> <CustomField> <Name><![CDATA[CAM$$LicenseAssignmentGroup]]></Name> <Type>Text</Type> <Required>False</Required> <Value/> </CustomField> </CustomFields> <Details/> <Manufacturer> <Uri/> <Name><![CDATA[My manufacturer]]></Name> </Manufacturer> <StartDate>2011-03-11</StartDate> <EndDate>2012-03-10</EndDate> <ContractNumber/> <ServiceDescription/> <MaintainedLicenseUnit> http://myserver/CAMAPI/Inventory.svc/LicenseUnit/162 </MaintainedLicenseUnit> </SoftwareMaintenanceLineItem>