CTC API Convention
REST over HTTP
General
The CalAmp Telematics Cloud API is a REST over HTTP implementation. As such, you can make requests to the API via any HTTP client with TLS 1.1 or higher.
This section covers REST basics, as well as CTC-specific items such as the data exchange format, required HTTP headers, and several supported HTTP request parameters.
HTTP Verbs
Verb | Description |
---|---|
GET | To read a resource. |
POST | To create a new resource. |
PUT | To update an existing resource. Requires the full resource to be sent in the request body as it completely replaces the old with the new. |
DELETE | To delete a resource. |
HEAD | Similar to making a GET call on the URL, except it has no response body. |
OPTIONS | To request information about the communication options supported by the API endpoint. |
HTTP Status Codes in Responses
CTC follows the standard HTTP status codes. In general, the meaning of the status codes is as defined by RFC2616, but there might be some semantic differences.
Status | Description |
---|---|
200 | The request completed as expected. In the case of a GET or PUT request, the latest state of the resource acted on is returned in the response body. In the case of a HEAD or OPTIONS request, only the metadata is returned in headers. |
201 | The request to create a new resource completed as expected. The new resource is returned in the response body. |
202 | The request was received, but the task has not completed yet. Usually in response to a request to perform an asynchronous task. |
400 | Bad request. Generally because of missing required parameters or invalid supplied values. |
401 | Not authenticated. |
403 | Forbidden. The authenticated user is not authorized to perform the requested action on the specified resource. |
404 | Either the specified resource or an associated resource was not found. |
405 | The requested action is not supported on the specified resource. |
409 | The resource state is in conflict. Generally in response to a PUT request where the supplied state of the resource is not the latest state in the system. |
417 | The expectations specified in the request could not be fulfilled (for example, in the case of link expansion or some expectation defined in the Expect header). |
422 | The server understands the request content, and valid values are supplied, but it is unable to fulfill the request (for example, "username already exists" constraint). |
500 | The API encountered an unexpected error and cannot complete the request. |
CTC Data Exchange Formats
The API uses JSON as the data exchange format and UTF-8 encoding, for both requests and responses. In order of precedence, the format can be specified via the following:
-
A URL extension of the form .json
https://connect.calamp.com/connect/services/accounts/{id}.json -
A request parameter ?ext=json
https://connect.calamp.com/connect/services/accounts/{id}?ext=json -
A mime-type in the Accept header as application/json[;charset="UTF-8"]
If the request does not explicitly state the default data exchange format, it will be JSON, and the encoding is UTF-8.
WARNING: Support for XML as a data exchange format has been discontinued. It is not being maintained or enhanced and could be completely removed at any time. Clients MUST not use it when communicating with CTC APIs.
For brevity and generality, the https scheme, hostname, and port are omitted from further examples. Instead, the endpoints and URLs will show only the context, path, and other relevant parameters.
CTC HTTP Headers
The following headers are mandatory for all requests to the API:
- calamp-services-app: This is the application key provided to you when you sign up to be a client of the API. In some contexts, this header is also displayed as an x-app-key. These are interchangeable for most APIs.
NOTE: This can also be provided as a request parameter instead of an HTTP header, although we recommend including this in the header.
- 'Cookie':'authToken={{authToken}}: The authToken is obtained in response to a successful login request. It is valid for 3600 seconds after the time of the last request made by the client.
It is common to also include an Accept header, but this is optional in most APIs:
- Accept: 'Accept':'application/json;charset=UTF-8'
Using CTC GET Endpoints
Like most REST interfaces, CTC's GET endpoints are typically straightforward to use. The GET endpoints usually have an object ID present as part of their path. There are a few GET endpoints that require no prior knowledge of objects to call. These can be used to acquire initial object IDs. Each call then returns data to build context for future calls to other endpoints.
An example GET endpoint is
GET /devices/esn/{ESN}
This endpoint returns the ESN's device object, which includes a link to the device (self), as well as the device's account link and other information.
The way the path for the GET /devices/esn/{ESN}
endpoint is represented omits the base path.
Here is an example of a full URL for this endpoint:
https://connect.calamp.com/connect/services/devices/esn/3272001160?status=Enabled
Nearly all CTC endpoints have a base path of https://connect.calamp.com/connect.
This particular endpoint is part of entity services, which explains the addition of "services" in the path. Although we omit full paths in much of the top-level documentation, they are typically available in the API section of the site.
The preceding example also takes advantage of a request parameter. There are several request parameters that are commonly used with CTC APIs, and a whole section on request parameters is available for review.
Using CTC PUT/POST Endpoints
Most PUT and POST CTC endpoints require generating a properly formatted JSON object that contains the information required to modify or create an object.
The API documentation has a description of the object models used as part of the request. The object model in the API documentation is complete, including both required and optional parameters. Although not all the optional parameters need to be included, most endpoints will not return an HTTP 200 message unless all the required parameters are present and the JSON object is properly formatted. If the object is formatted correctly with the required parameters, you may find the request is received, but an error message was provided in the response. These error messages typically clearly state why the request failed and lead to straightforward corrective actions.
Many of the CTC endpoints require links to accounts, devices, and such. In CTC, a link is an object that contains four fields (href/rel/title/status). When formatting requests, the title and status fields are optional. Omitting status when creating a new device will default to an enabled device, and the titles are informational. href and rel are required fields that must be present.
{
"href" : (string) The URI to the resource this Link represents,
"rel" : (string) Relation to the resource represented by the link, in the context of the containing resource,
"title" : (string, optional) Some additional information about the resource.
"status" : (string, optional) Status of the resource. One of 'Enabled', 'Disabled', 'Suspended', 'Deleted'.
}
The link object model is shown above. All the parameters within a link are strings. A common practice to determine what is required for the "href" and "rel" strings is to first make a GET call to retrieve a link to the existing object or a similar object that can be modified for a POST. The formatting of the "href" and "rel" string resource will be returned.
You tag any device IDs on to the end of the “device” endpoint. For example, you would use this full endpoint to change a device whose device ID is 420776 with a PUT command:
JSON
"device": {
"_self": {
"href": "https://connect.calamp.com:443/connect/services/devices/420776",
"rel": "self",
"status": "Enabled"
},
Other links are also given in the response, including the href for the account, PEG configuration, asset, and device type.
CTC Request Parameters
Below is a description of several request parameters supported by CTC. Pagination request parameters are covered separately.
v - version
v - version
Some CTC endpoints have API version requirements, and to make a proper call to these APIs, you must include the version in the request. One option to include the version is using the v request parameter. The format of the API version is v=NN.NN.
Example:
GET /services/groups/123/members?v=2.1
If the version is left out of an otherwise properly formatted request, the request may return the HTTP status code 200, with an error response in the body. For example,
GET /services/groups/123/members
will return the following response body:
{
"response": {
"errors": [
"Version must be supplied for this endpoint and must be 2.1 or greater"
],
"results": []
}
}
NOTE: You can also specify the API version as a Content-Type HTTP header.
expand
expand
You use the expand parameter to request that certain associated resources also be read and fully embedded in the response of a related request. This is a way to reduce the number of round trips between the client and the API servers; however, keep in mind that this might make each such request take longer (although the process will still be faster than multiple individual requests). For example,
GET /connect/services/devices/1?expand=type,configuration
equates to making the following requests in order:
GET /connect/services/devices/1
GET
ondevice
.type
.href
from the device returned in response to #1GET
ondevice
.configuration
.href
from the device returned in response to #1
The expanded objects are returned embedded in the . expanded
property
The following is an example of a response to GET /connect/services/devices/1?expand=type
:
(Note that this is abridged to focus on relevant parts.)
{
"response": {
"searchableProperties": {},
"results": [
{
"device": {
"_self": {},
"name": "Device_1",
"id": 1,
"version": 5,
"deviceConfiguration": {},
"account": {},
"type": {
"href": "/connect/services/devicetypes/3",
"rel": "deviceType",
"title": "lmu2620"
},
"expanded": {
"type": [
{
"_self": {
"href": "/connect/services/devicetypes/3",
"rel": "self"
},
"name": "lmu2620",
"id": 3,
"lastModifiedOn": "2017-02-16T22:45:44.712Z",
"appId": null,
"sku": "CPS-2620-00-SP6001",
"createdOn": "2017-02-16T22:45:44.712Z",
"image": null,
"version": 0
}]}
}}
]}}
There are certain restrictions and semantics for the expand
parameter, as follows:
- It must be provided as a request parameter.
- Include a comma-separated list for any association names of the requested resource — for example,
GET /connect/services/devices/2?expand=type,asset
,GET /connect/services/users/1?expand=account
, and so on. - Only first-level associations can be expanded. Trying to expand other associations, such as
GET /connect/services/devices/2?expand=
asset.account
, will result in an error. - Only single-value associations can be expanded; associations that are collections cannot be expanded. In other words,
user.account
can be expanded, butuser.roles
cannot be expanded.
withLocation
withLocation
The withLocation request parameter is specific to any requests that return device or a collection of device resources. When this parameter is present in the request, the response will also include the latest geolocation data reported by the device(s). This data is populated in the device. lastCommunication
property.
The presence of this parameter in the request is equivalent to saying withLocation=true
.
The absence of this parameter in the request is equivalent to saying withLocation=false
.
Example:
GET /connect/services/account/123/devices?withLocation
is equivalent to
GET /connect/services/account/123/devices?withLocation=true
hierLevel
hierLevel
CTC is a multitenant platform that allows organizing resources in account hierarchies. By default, when a search for resources is performed by account(s), only the resources that are directly owned by the specified account(s) are returned. The hierLevel
request parameter offers clients a way to specify how deep in the account hierarchy the API should search for resources.
The absence of this parameter is the same as the default value 0, meaning that only the specified account(s)' direct entities are to be searched.
The parameter can be specified as hierLevel=[N|(ALL)]
, where 0 <= N <= 100 and ALL means full hierarchy.
Examples:
GET /accounts/123/devices?hierLevel=ALL
will return all Enabled devices in Account.id:123 and its non-Deleted child accounts.GET /accounts/123/devices?hierLevel=0
ORGET /accounts/123/devices
will return Enabled devices only in Account.id:123.GET /peglabels?hierLevel=2
will return Enabled PegLabels in the authenticated user’s account hierarchy, up to two levels deep.POST /assets/search?hierLevel=3
with a request body of {"search": {"searchTerms":{"account":"123,456"}}} will return all Enabled assets in Account.id:123 and Account.id:456 and their respective non-Deleted child accounts that are up to three levels deep.
include
include
The include request parameter has multiple values, each with their own semantic and API applicability. Specify it in the request as include=x,y,z,...
, where x,y,z are one or more of the following values:
-
pegEvents, pegAccumulators
: These two values of theinclude
parameter are applicable only to the PegBehavior APIs (/pegbehaviors/XXX
). Without these present in the request,GET /pegbehaviors/{id}
will return only the PegBehavior, not the embeddedpegEvents
and their respectivepegAccumulator
collections.pegAccumulator
takes effect only ifpegEvents
is also included. -
extensions
: This allows clients to ask for the API to act onextensions
properties of the resource(s) involved in the request. -
extAttribs
: This allows clients to specify that theextendedAttributes
, if any for the application, for the requested resource(s) also be returned in the response. Existing APIs that already supplyextendedAttributes
by default will continue to work as before, but any new endpoints/APIs MUST use this value. -
deviceSettings
: This value of the include parameter is applicable only for the APIs that return device(s). Without this present in the request,GET devices/{id}
will return only the device details, not the embedded deviceSettings. It is applicable only for SCI devices and tags.
Examples:
GET /connect/services/users/23?include=extensions
GET /connect/services/assets/vin/12351223?include=extAttribs,extensions
POST /connect/services/assets/search?include=extAttribs
GET /connect/services/devices/41?include=deviceSettings
POST /connect/services/devices/search?include=deviceSettings
Rate Limiting
CTC rate limiting is up to 200 calls per minute.
CTC generally offers this rate limit but user discretion is required while calling individual APIs example login API should never be called 200 times per minute because login API has its own guideline.
Pagination in CTC
Introduction
Requests to the CalAmp Telematics Cloud platform could result in a lot of data being returned. In some cases, it can be too much data for the client to handle; fetching, collating, and transforming it can cause unnecessary load on the server. An overly large data load can lead to bandwidth wastage, especially on mobile devices. Moreover, the client might not even be interested in receiving that amount of data.
To limit the exposure to such unwanted side effects of fetching data, CTC includes paginated responses as explained below.
We have added these new request parameters:
- pg: The page number, starting at 1.
- pgsize: How many records to retrieve per query. The default is 10, with a maximum of 100. This parameter overrides maxResults defined in
/search
requests. - sort: A comma-separated list of searchable properties. If this isn't supplied, CTC will default to the id property. You can specify sort direction using +/-. No sign == + == ascending.
Only top-level collections are paginated. Collection-type properties of a resource are not paginated.
Examples:
GET /accounts/123/devices
response returns a list of devices that can be paginated.account.subAccounts
in response toGET /accounts/123
is not paginated.
Responses with collections will now include two additional properties:
- totalCount : The total number of resources, accessible by the logged in user, that satisfy the request.
- _links : A collection of Links with well-defined relations that are not direct properties of the resource(s) retrieved. Each member of this collection has an href and rel property. The following relations will be used for pagination: self, prev, next, first, last (as defined by RFC5988.) The following rules apply to the
_links
collection:- self is always present. This is analogous to a resource's _self property and represents the request.
- first is always present.
- prev is present only if you’re not on the first page.
- next is present only if you’re not on the last page.
- last is always present.
- The order of the elements in the _links collection is not defined.
The pagination parameters can be added to any request.
The minimum API version for which pagination will be enforced is 2.1:
- The format of the API version is v=NN.NN.
- The API version can be specified as a Content-Type HTTP header or as a request parameter.
- For any API version prior to 2.1, pagination is not enforced.
- For API versions lower than 2.1, pagination can still be used by explicitly providing the pagination parameters.
- Some endpoints have minimum version requirements. If the version is left out of an otherwise properly formatted request, the request may return an HTTP status code 200, with an error response in the body.
{
"response": {
"errors": [
"Version must be supplied for this endpoint and must be 2.1 or greater"
],
"results": []
}
}
If a request is made with v=2.1, and no pagination parameters are provided, they will default as follows: pg=1, pgsize=10, sort=id.
If the pagination parameters are specified multiple times in the request, the following rules apply:
- pg: Only the first value is used.
- pgsize: Only the first value is used.
- sort: All occurrences are combined into a single sort in the order they are specified.
Structured Search
Introduction
The CalAmp Telematics Cloud platform supports a structured function that enables users to filter and sort data based on a variety of searchable properties. This section discusses how to determine the searchable properties of a resource and issue queries.
NOTE: For brevity, the scheme, hostname, and port are omitted from URIs in the examples below.
Search Endpoints
New service endpoints have been added to support the search feature.
/searchableProperties
Example:
GET /services/{resourceType}/searchableproperties
This endpoint returns a searchableProperties document that lists the properties of the given resourceType that can be searched on. For example, GET /services/users/searchableproperties
returns the following:
{
"response": {
"searchableProperties": {
"account (long[])": "",
"createdOn (date[])": "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"username (string[])": "",
"crmId (string[])": "",
"status (resourcestatus[])": "Enabled, Disabled, Suspended, Deleted",
"firstName (string[])": "",
"activationDate (date[])": "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"lastName (string[])": "",
"id (long[])": ""
}
}
}
In addition to the above endpoint for each resource, the standard CTC response will also include the searchableProperties object if a response of HTTP status 200 is received from the service. For example, GET /services/users/3
will return this:
{
"response": {
"searchableProperties": {
"account (long[])": "",
"createdOn (date[])": "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"username (string[])": "",
"crmId (string[])": "",
"status (resourcestatus[])": "Enabled, Disabled, Suspended, Deleted",
"firstName (string[])": "",
"activationDate (date[])": "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"lastName (string[])": "",
"id (long[])": ""
},
"results": [
{ "user": {
"_self": {
"href": "/connect/services/users/3",
"rel": "self",
"status": "Enabled"
},
"version": 0,
"extendedAttribute": null,
"enabled": true,
"status": "Enabled",
"password": null,
"id": 3...
}
}]
}}
/search
/search
/search
endpoints are for performing a search against the given resource type. To search, the client should POST a search with a search object in the body of the endpoint. The search object has the following schema:
{
"search": {
"maxResults": Integer,
"searchTerms": Map[string,string],
"sort": Array[string]
}
}
- maxResults: If this is not provided, CTC defaults to 10. The maximum allowed currently is set at 999.
- searchTerms: This parameter is required. searchTerms is a map of strings. A blank search is not a valid request.
- sort: Allowed values are any of the searchableProperties for the resourceType. Sorting is done in the listed order. You can specify the sort direction using +/- before the property name. The default sort order is Ascending == + == no sign.
searchTerms is a map with searchable property name(s) as the key, and comma-delimited strings are the value(s).
- Different keys are combined via AND.
- Different values for the same key are combined via OR.
- The search is case sensitive.
- Spaces in the search values are valid and not stripped off. So in the comma-separated list of values for each key, spaces matter.
Wildcard Support
The wildcards * and ? are now supported anywhere in the search value(s) provided for the searchTerms of type String. Both the supported wildcards have the same meaning as in regular expressions, where * matches multiple characters and ? matches a single character.
A wildcard-only search is not supported. The following examples are considered no-ops, and they return no results:
- "name":"*"
- "name":"?"
Date Range Support
CTC supports searching based on the date and time with both equality operators and date ranges.
Equality searches require an exact match of the timestamp of the object, down to the nanosecond. In rare instances, the exact time of an event may be known, and it is a valid way to search for objects.
However, that means typically time-based searches will leverage date/time ranges. It is strongly recommended to use time ranges for all searches to avoid frustration.
A time range is specified as [lower bound TO upper bound].
The upper and lower bounds of a date range can be specified in multiple ways:
- As an ISO 8601-compliant string.
- As the number of seconds since epoch.
- In natural language.
- * can be used to specify no bound.
- NOW represents the current server time.
- Both bounds are inclusive.
In addition, date arithmetic can be used to specify the bounds. The supported arithmetic operators are +, -, and /, where / is the floor operator. Flooring means to zero out parts of a time smaller than the time unit supplied.
<date>+N<time unit> means, add N number of <time unit> to the given <date>
<date>-N<time unit> means, subtract N number of <time unit> from the given <date>
<date>/<time unit 1>+N<time unit 2> means, floor the <date> based on <time unit 1>,
then add N number of <time unit 2> to the floored result.
Supported time units are
- MILLI, MILLIS, MILLISECOND, MILLISECONDS
- SECOND, SECONDS
- MINUTE, MINUTES
- HOUR, HOURS
- DAY, DATE, DAYS
- MONTH, MONTHS
- YEAR, YEARS
Sorting Results
The structured search's sorting capability is particularly useful when the search may return a long list of results. You can use any of the searchableProperties provided for a resource type to sort the results.
The sort parameter is an array of strings. As mentioned previously, sorting can be done by ascending or descending order by using + and -, respectively. Omitting the sort direction results in ascending order. Because sort
is an array, it is important that your search terms are formatted as an array (including the [ ]), even if only one term is required.
Example:
"sort" : ["-lastModifiedOn"]
The following example is for a device resource. If you are searching for devices, there are many searchable properties. As mentioned previously, this can be found in multiple ways, including using the /searchableProperties endpoint for a resource type.
{
"response": {
"searchableProperties": {
"account (long[])": "",
"imei (string[])": "",
"id (long[])": "",
"mdn (string[])": "",
"externalId (string[])": "",
"ipAddress (string[])": "",
"shipDate (date[])": "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"networkMode (string[])": "",
"activationDate (date[])": "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"deviceConfiguration (long[])": "",
"name (string[])": "",
"pegBehavior (long[])": "",
"groups (list[])": "",
"lastModifiedOn (date[])": "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"provisionStatus (string[])": "",
"status (resourcestatus[])": "",
"serialNumber (string[])": "",
"meid (string[])": "",
"type (long[])": "",
"category (devicecategory[])": "",
"createdOn (date[])": "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"architecture (devicearchitecture[])": "",
"min (long[])": "",
"esn (string[])": "",
"iccid (string[])": "",
"airId (string[])": "",
"imsi (string[])": "",
"networkCarrier (string[])": "",
"dmDevice (boolean[])": "",
"networkCurrentMode (string[])": "",
"phoneNumber (string[])": "",
"signalStrength (string[])": "
}
}
}
An example that searches for all devices with an ESN beginning with 467, sorted in ascending order, could use the following search object:
POST /services/devices/search
{
"search": {
"maxResults": 100,
"searchTerms": {
"esn": "467*"
},
"sort" : ["+esn"]
}
}
Example User Searches
Search for Users by id
POST /connect/services/users/search
{
"search":{
"searchTerms":{
"id":"2,5,1,4,7"
}
}
}
The search results will return as follows:
{
"response": {
"searchableProperties": {
"id (long[])": "",
"lastName (string[])": "",
"crmId (string[])": "",
"username (string[])": "",
"firstName (string[])": ""
},
"search": {
"maxResults": 10,
"searchTerms": {
"id": "2,5,1,4,7"
}
},
"queryTime": 79,
"results": [
{"user": {"id": 2...}},
{"user": {"id": 5...}},
{"user": {"id": 1...}},
{"user": {"id": 4...}},
{"user": {"id": 7...}}
]
}
}
Search for Users by username and firstName
POST /connect/services/users/search
{
"search":{
"searchTerms":
{
"username":"abcAdmin,JDoe",
"firstName":"John"
}
}}
results in the following:
{
"response": {
"searchableProperties": {},
"search": {
"maxResults": 10,
"searchTerms": {
"username":"abcAdmin,JDoe",
"firstName":"John"
}
},
"queryTime": 31,
"results": [
{
"user": {
"_self": {
"href": "/connect/services/users/2",
"rel": "self"
},
"id": 2,
"username": "JDoe",
"firstName": "John"...
}
}
]
}
}
Wildcard Search Examples
Here are various wildcard search examples using the POST /services/users/search
endpoint:
- Returns users whose name begins with "abc."
{
"search":{
"searchTerms": {
"username":"abc*"
}
}
}
- Returns users whose name begins with "abc" and ends with "Admin."
{
"search":{
"searchTerms":{
"username":"abc*Admin"
}
}
}
- Returns users whose name contains "bcAd" after the first character.
{
"search":{
"searchTerms":{
"username":"?bcAd*"
}
}
}
- Returns users whose name begins with "Calamp R."
{
"search":{
"searchTerms":{
"username":"Calamp R*"
}
}
}
Date Range Search Examples
Here are some wildcard/date range search examples using the POST /services/users/search
endpoint:
- Returns user resources with createdOn dates between 2014-11-01T10:00:00Z and 2015-01-01T20:00:00Z.
{
"search":{
"searchTerms":{
"createdOn":"[2014-11-01T10:00:00Z TO 2015-01-01T20:00:00Z]"
}
}
}
- Returns users with createdOn dates 2014-11-01T10:00:00.000Z and later.
{
"search":{
"searchTerms": {
"createdOn":"[2014-11-01T10:00:00.000Z TO *]"
}
}
}
- Returns users with createdOn dates less than or equal to 2015-01-01T20:00:00.000Z.
{
"search":{
"searchTerms": {
"createdOn":"[* TO 2015-01-01T20:00:00.000Z]"
}
}
}
- Returns users created before the current server time.
{
"search":{
"searchTerms": {
"createdOn":"[* TO NOW]
}
}
}
- Returns users created more than three days ago.
{
"search":{
"searchTerms": {
"createdOn":"[* TO NOW-3DAYS]"
}
}
}
- Returns users created in the last three days.
{
"search":{
"searchTerms": {
"createdOn":"[NOW-3DAYS TO NOW]"
}
}
}
- Returns users with createdOn dates in the range floor(NOW)-3DAYS TO NOW-2DAYS.
{
"search":{
"searchTerms": {
"createdOn":"[NOW/DAYS-3DAYS TO NOW-2DAYS]"
}
}
}
Example (NOW = 2014-03-23T12:13:14.560Z):
- Lower bound = 2014-03-20T00:00:00.000Z
- Upper bound = 2014-03-21T12:13:14.560Z
Updated over 2 years ago