Detailed Introduction to Remote Manager APIs

Remote Manager at its core is primarily API driven. The vast majority of the services provided by the system are accessible via the Remote Manager web service APIs.

In this article, you’ll see various techniques to discover what the Remote Manager APIs are and how to use them.

Table Of Contents

Notes about examples

These tools are strongly recommended if you like to use web service APIs from the command line.

HTTPie

The examples in this article use the HTTPie tool (https://httpie.io/) to demonstrate the web APIs. The HTTP response headers and response body are included in the output.

The HTTPie tool is a command line tool that can use a user’s netrc file to get credentials for API calls.

It allows the user to completely avoid URL encoding and use simple shortcut syntax to pass HTTP header values, API parameters, data payloads and select what output to display.

The examples are using HTTPie in a zshell environment, so you may have to modify each example for whatever environment and tool you use to call web service APIs. For simplicity, our recommendation is to download HTTPie.

jq and xq

Other tools you’ll see used in these examples consist of jq (https://stedolan.github.io/jq/) and xq (https://github.com/kislyuk/xq).

jq is a JSON command line processing tool, at its simplest, it allows you to format and colorize JSON. At its most complex it allows you to run queries and script like programs over JSON output.

xq is a wrapper for the jq tool that first converts XML input to JSON and then does normal jq processing on it.

API Authentication

The Remote Manager APIs use HTTP Basic Authentication. The username and password are the same as the username and password you use to sign-on to the Remote Manager UI or the application user you create.

In the examples here and in the API reference documentation, we often use the HTTPie tool or curl tool to call the APIs and do not discuss authentication. Authentication is the same for every API call.

Both HTTPie and curl can use the netrc file to load credentials for the API calls, HTTPie does this by default, curl requires a -n option.

If you use another tool, configure the tool to use HTTP Basic Authentication with the username and password. HTTP Basic authentication is well-supported by languages and API tools.

If you are doing basic-auth manually, with a username of fred and a password of secret, do the following steps:

  1. Concatenate the username and password string with a colon, resulting in: fred:secret
  2. Base64 encode the concatenated string, resulting in: ZnJlZDpzZWNyZXQ=
  3. Prefix the value with Basic and a space, resulting in: Basic ZnJlZDpzZWNyZXQ=
  4. Use the resulting value for the HTTP Authorization header, resulting in a header of Authorization: Basic ZnJlZDpzZWNyZXQ=

Application Users

Your application can use any user and password in the system for API calls. The user role defines the access that the call has to the system.

For long term API access to Remote Manager we recommend creating application users in the system. Application users are not allowed to sign-on to the Remote Manager UI and are used for API only access.

  • In the Systems -> Users page, add a user and select the Application or Read only application role.
  • Assign the user a name and strong password
  • Use the name and password for API applications.

API Keys

API keys can be used as an alternative to HTTP Basic Authentication when calling an API. API keys are useful when you have a script that needs to make API calls, your user normally requires two-factor authentication or your user logs in through a SAML identity provider (Single Sign-On).

API key creation is disabled by default and must be enabled by an administrator for your account under the account settings. Once enabled, each user in the account is able to create API keys in their user profile. The API keys work for users logging in through Single Sign-On and do not require two-factor authentication.

Creating an API key will return an id and secret. You must copy the secret and keep it secure as it is never returned after the key is created. Keys will expire after at most one year so you must replace any in use keys before they expire.

The headers X-API-KEY-ID and X-API-KEY-SECRET are used to supply the API key id and secret when making an API call.

curl:

curl -H "X-API-KEY-ID: <your-api-key-id>" -H "X-API-KEY-SECRET: <your-api-key-secret>" https://remotemanager.digi.com/ws/v1/devices/inventory

HTTPie

http https://remotemanager.digi.com/ws/v1/devices/inventory 'X-API-KEY-ID:<your-api-key-id>' 'X-API-KEY-SECRET:<your-api-key-secret>'

API Summary

Remote Manager APIs are typically case sensitive. That means the api /ws/v1/users/inventory exists, but /ws/v1/Users/Inventory will not work.

There are two main types of APIs in Remote Manager. Legacy APIs and Modern APIs.

  • Legacy APIs - /ws/*

    • Have a path starting with /ws/* where the * does NOT begin with “v1/”
      • For example GET /ws/DeviceCore to list devices, DELETE /ws/DeviceCore to remove a device from the system
    • Typical GET, POST (for create), PUT (for update), DELETE APIs
    • GET APIs
      • Page size maximum and default is 1000 items
      • Typically support start and size parameters so you can page through large lists of results
    • Typically use SQL syntax for queries
      • These APIs are very close to the storage model of the Remote Manager system
      • They typically go directly at the data model and do very little conversion to the abstract/logical data they represent
      • The fields of the object are typically bi-capitalized and based on the data model as well
      • Status and type fields are typically opaque enum values
        • For example, the GET /ws/DeviceCore field, “dpConnectionStatus”=“0” means disconnected. UGH!
    • Accept and respond with XML. Typically can respond with json, but json conversion fails in some cases
      • You should do the XML to JSON conversion in your client application (see the description of the xq tool above).
    • Because of these caveats, the legacy APIs are typically harder to use and harder to decipher the data payload/contents
  • Modern “v1” API - /ws/v1/

    • Have a path of /ws/v1/XXXX*
      • The top level API for a v1 API is typically a set of related APIs for a feature
      • For example: The /ws/v1/devices/* API contains 11 APIs in total, more if you count the fact that some APIs can use all of the GET, POST, PUT, and DELETE HTTP methods.
      • We don’t have any version 2 /ws/v2/* APIs yet.
    • Accept and respond with JSON
      • Fields match logical names of items
      • More conversion is done of enumerated types to meaningful names
        • For example, the GET /ws/v1/devices/inventory field “connection_status”=“disconnected” means disconnected.
    • By calling a GET on the top level API, these APIs describe their contract (See the self documenting section)
    • Typically have a top level API with an inventory API for the GET, POST (for create), PUT (for update), and DELETE APIs
      • For example GET /ws/devices/inventory to list device inventory, POST /ws/devices/inventory to add a device to the system
    • Often have bulk or other APIs at the same level as inventory to provide additional service
      • For example GET /ws/devices/bulk to list devices in bulk with CSV output
    • GET Inventory APIs
      • Page size maximum and default is 1000 items
      • Typically support a query, cursor and size parameters so you can page through large lists of results
      • Typically support a modern query language that is NOT SQL and can be used regardless of data model that the backend service uses.
    • Because of these things the modern APIs are typically MUCH easier to use

API Explorer

The Remote Manager UI has a page called “API explorer”. API explorer allows you to graphically explore the available APIs.

If you find a missing API or have questions about using the APIs, use the feedback button in the UI to request changes to the documentation.

The API explorer provides a set of examples, as well as the ability to type Remote Manager APIs and payloads in manually and enter parameters and select the HTTP method type.

In this screen shot for API explorer, there are a couple of things to notice:

  • I selected “Examples → v1/devices → Provision a device” and the example payload was added automatically, the API explorer helps determine payloads
  • I have recently run 2 other APIs a GET /ws/v1/devices/inventory and a GET /ws/v1/jobs/inventory and those are in the history list, I can go back and look at the request and response payload while I’m still in this API explorer session
  • I can pull down the button labeled “POST” to change to a different HTTP method and I can type in the pathname for the API.

You should spend some time experimenting with the APIs.

img

Self Documenting APIs

Our modern APIs provide a bit of self documentation. You can call top level APIs using GET and receive a json payload that describes the sub APIs and their usage.

At the top level, call /ws/v1 API to get a table of contents of all the major API types.

You’ll see in this example, there are 22 major categories of APIs in the Remote Manager system (this was from version 22.7 of Remote Manager).

 http remotemanager.digi.com/ws/v1
HTTP/1.1 200
 
{
  "count": 22,
  "list": [
    {
      "path": "/ws/v1/account"
    },
    {
      "path": "/ws/v1/alerts"
    },
    {
      "path": "/ws/v1/automations"
    },
    {
      "path": "/ws/v1/configs"
    },
    {
      "path": "/ws/v1/containers"
    },
    {
      "path": "/ws/v1/device_logs"
    },
    {
      "path": "/ws/v1/devices"
    },
    {
      "path": "/ws/v1/events"
    },
    {
      "path": "/ws/v1/files"
    },
    {
      "path": "/ws/v1/firmware_updates"
    },
    {
      "path": "/ws/v1/groups"
    },
    {
      "path": "/ws/v1/health_configs"
    },
    {
      "path": "/ws/v1/jobs"
    },
    {
      "path": "/ws/v1/metadata"
    },
    {
      "path": "/ws/v1/monitors"
    },
    {
      "path": "/ws/v1/network_interfaces"
    },
    {
      "path": "/ws/v1/notifications"
    },
    {
      "path": "/ws/v1/reports"
    },
    {
      "path": "/ws/v1/settings"
    },
    {
      "path": "/ws/v1/streams"
    },
    {
      "path": "/ws/v1/subaccounts"
    },
    {
      "path": "/ws/v1/users"
    }
  ]
}

You can use this trick again to see the APIs belonging to any category. In this example we see the automations API documentation.

In the automations API, there are 14 sub APIs (although there are actually more than that if you consider that some APIs support multiple HTTP methods like GET/POST/PUT/DELETE. For example the automations/inventory/{id} API is a GET/PUT/DELETE API

# Use jq to see JUST the API path names
➜ http remotemanager.digi.com/ws/v1/automations | jq -r ".list[] | .path"
/ws/v1/automations
/ws/v1/automations/inventory
/ws/v1/automations/inventory/{id}
/ws/v1/automations/run
/ws/v1/automations/runs
/ws/v1/automations/runs/cancel/{id}
/ws/v1/automations/runs/inventory
/ws/v1/automations/runs/inventory/{id}
/ws/v1/automations/runs/results/{id}/{device_id}
/ws/v1/automations/runs/status/{id}
/ws/v1/automations/runs/status/{id}/{device_id}
/ws/v1/automations/schedules
/ws/v1/automations/schedules/inventory
/ws/v1/automations/schedules/inventory/{id}

Query Language Syntax

One of the features that the self documenting APIs gives you is details on the query language for each API.

In the below output, we see that there’s an automations/inventory API that includes parameters “query”, “orderby”, “size” and “cursor” (like the majority of our v1 inventory APIs do). The payload then goes further to describethe query parameter: what fields can you use to construct your query, what operators each field supports and whether a field supports orderby.

From this description we know that for the objects returned by the automations/inventory API, the objects include the following fields and we can query

  • A “customer_id” field that is a number
  • An “id” field that is a number
  • A “name” field that is text

All of the fields can be used in an orderby clause.

So we could build a query that looks like this (which would have to be correctly URL encoded).

customer_id = 1034 and id > 10 and name contains 'script'

See v1 API Query Language for more information about the query language capabilities

The query field shown in this describes queryable fields for the automations/inventory API.

 http remotemanager.digi.com/ws/v1/automations
HTTP/1.1 200
 
{
    "count": 14,
    "list": [
        {
            "path": "/ws/v1/automations/inventory",
            "requests": [
                {
                    "method": "GET",
                    "params": [
                        "query",
                        "orderby",
                        "size",
                        "cursor"
                    ],
                    "query": [
                        {
                            "field": "customer_id",
                            "operators": [
                                "=",
                                "<>",
                                "<",
                                "<=",
                                ">",
                                ">="
                            ],
                            "orderby": true,
                            "type": "Numeric"
                        },
                        {
                            "field": "id",
                            "operators": [
                                "=",
                                "<>",
                                "<",
                                "<=",
                                ">",
                                ">="
                            ],
                            "orderby": true,
                            "type": "Numeric"
                        },
                        {
                            "field": "name",
                            "operators": [
                                "=",
                                "contains",
                                "startsWith",
                                "endsWith",
                                "<>",
                                "<",
                                "<=",
                                ">",
                                ">="
                            ],
                            "orderby": true,
                            "type": "Text"
                        },
...snip...

Modern API Examples

Adding a device

In order to add a device to your account on Remote Manager, you can use the UI of course, but this article is about the API.

You can use a POST API (which is typically the type of API used for create operations) to the ws/v1/devices/inventory endpoint.

The required fields for posting a device are at least

  • The device ID (A little like a UUID the canonical device ID is represented in the form 00000000-00000000-00000000-00000000). Depending on the type of device, it typically includes the device’s primary mac address or the device’s IMEI number.
  • The install code or default password of the device. Usually printed on the label or part of the QR code on the device. This 10 or 12 character password is how a device is securely registered with the system. NOTE: Some older devices don’t use install codes for registration.
  • Other fields like group, mac, tags, notes, and description can also be used.

For example, this request sends the json payload to the POST devices/inventory API.

The result is HTTP status 201 and we can see the device is created. Right now the device is disconnected and a lot of the fields that are identified the first time the device connects are not present.

 http POST remotemanager.digi.com/ws/v1/devices/inventory <<< '{"id":"00000000-00000000-0040FFFF-FF8001B0", "install_code":"MYPASSW0RD", "group": "test/group"}'
HTTP/1.1 201
 
{
    "count": 1,
    "list": [
        {
            "channels_uri": "/ws/v1/devices/channels/00000000-00000000-0040FFFF-FF8001B0",
            "connection_status": "disconnected",
            "customer_id": 73846,
            "firmware_status": "not_identified",
            "group": "test/group",
            "health_status": "unknown",
            "id": "00000000-00000000-0040FFFF-FF8001B0",
            "mac": "00:40:FF:80:01:B0",
            "maintenance_mode": "off",
            "management_uri": "/ws/v1/devices/management/00000000-00000000-0040FFFF-FF8001B0",
            "metrics_uri": "/ws/v1/devices/metrics/00000000-00000000-0040FFFF-FF8001B0",
            "restricted_status": "unrestricted",
            "type": " "
        }
    ]
}

Deleting a device

It’s a simple matter to remove a device from your account, assuming that its there already.

➜ http DELETE remotemanager.digi.com/ws/v1/devices/inventory/00000000-00000000-0040FFFF-FF8001B0
HTTP/1.1 204

Device queries

We can use the query language in the devices/inventory API to build rather complex queries to search for devices. This becomes particularly useful if using an account that has subaccounts from the API and searching for devices across all subaccounts in the system. See v1 API Query Language for more information about the types of queries you can build.

For example, if I want to search for devices that are currently live and connected to my account, have updated their status in some form in the last day, and are in an office with an IP range of 10.20.1.x, I would use this query.

We can also see here a more full payload describing an in-use device object.

 http remotemanager.digi.com/ws/v1/devices/inventory query=="connection_status = 'connected' and last_update > -1d and ip startswith '10.20.1.'"
HTTP/1.1 200
 
{
    "count": 2,
    "list": [
        {
            "alerts": 1,
            "capabilities": {
                "cli_service_available": true,
                "sm_compression_available": true,
                "sm_encryption_key_distribution_service_available": true,
                "sm_pack_available": true
            },
            "channels_uri": "/ws/v1/devices/channels/00000000-00000000-002704FF-FF30D5A1",
            "connection_status": "connected",
            "contact": "Fred A Kulack",
            "customer_id": 7493,
            "firmware_status": "none",
            "firmware_version": "20.11.32.168",
            "group": "demoGroup",
            "health_status": "error",
            "id": "00000000-00000000-002704FF-FF30D5A1",
            "ip": "10.20.1.109",
            "last_connect": "2021-02-18T14:21:16.883Z",
            "last_disconnect": "2021-02-18T14:19:42.387Z",
            "last_update": "2021-02-18T21:01:39.607Z",
            "location": "Rochester, MN",
            "mac": "00:27:04:30:D5:A1",
            "maintenance_mode": "off",
            "management_uri": "/ws/v1/devices/management/00000000-00000000-002704FF-FF30D5A1",
            "metrics_uri": "/ws/v1/devices/metrics/00000000-00000000-002704FF-FF30D5A1",
            "name": "SilverSurfer",
            "public_ip": "10.20.1.109",
            "registration_date": "2021-01-11T16:36:00.000Z",
            "restricted_status": "unrestricted",
            "serial_number": "6330010536411709",
            "sku": "ASB-6330-MX00-OUS",
            "tags": [
                "TestAutomations"
            ],
            "type": "AcceleratedConcepts 6330-MX",
            "vendor_id": 4261412874
        },
...snip...

Paging through results

By default, inventory and other paging APIs use a page size of 1000 to decrease load and prevent timeouts and make payload sizes manageable.

The APIs typically use the “size”, and “cursor” parameters as the way to page through results. When an API reaches the full page size, and there are still more objects to return, it also returns a cursor value and often a next_uri parameter.

The cursor or next_uri parameter are used to get the next page of results. Do not change the size parameter or any other parameters during subsequent calls.

For example, this is how you page through a set of results. There are 3 objects in my account that match the query. Since I use a page size of 1, I’ll have to page through 3 additional times. If all the remaining data is returned, no cursor or next_uri parameter is returned. In this case, page size is a perfect multiple of available data so one extra query is needed that returns 0 object.

# Initial Query
 http remotemanager.digi.com/ws/v1/devices/inventory query=="connection_status = 'connected'" size==1
HTTP/1.1 200
 
{
    "count": 1,
    "cursor": "b2b8205b-8247-9cdb-8247-9cdaaf6999c6",
    "list": [
        { ... snip out single device object...}
    ],
    "next_uri": "/ws/v1/devices/inventory?query=connection_status+%3D+%27connected%27&size=1&cursor=b2b8205b-8247-9cdb-8247-9cdaaf6999c6",
    "size": 1
}
 
 
# Next Page
 http remotemanager.digi.com/ws/v1/devices/inventory query=="connection_status = 'connected'" size==1 cursor==b2b8205b-8247-9cdb-8247-9cdaaf6999c6
HTTP/1.1 200
 
{
    "count": 1,
    "cursor": "08eef948-3858-60f7-3858-60f563bc71c1",
    "list": [
        { ... snip out single device object...}
    ],
    "next_uri": "/ws/v1/devices/inventory?query=connection_status+%3D+%27connected%27&size=1&cursor=08eef948-3858-60f7-3858-60f563bc71c1",
    "size": 1
}
 
 
# Next Page
 http remotemanager.digi.com/ws/v1/devices/inventory query=="connection_status = 'connected'" size==1 cursor==08eef948-3858-60f7-3858-60f563bc71c1
HTTP/1.1 200
 
{
    "count": 1,
    "cursor": "9ce7cc7a-9fbd-8739-9fbd-873a5d56244b",
    "list": [
        { ... snip out single device object...}
    ],
    "next_uri": "/ws/v1/devices/inventory?query=connection_status+%3D+%27connected%27&size=1&cursor=9ce7cc7a-9fbd-8739-9fbd-873a5d56244b",
    "size": 1
}
 
 
# Final query finds that we're at the end
 http remotemanager.digi.com/ws/v1/devices/inventory query=="connection_status = 'connected'" size==1 cursor==9ce7cc7a-9fbd-8739-9fbd-873a5d56244b
HTTP/1.1 200
 
{
    "count": 0,
    "list": [],
    "size": 1
}

Bulk APIs

Remote Manager bulk APIs are typically the same level and parameters as the inventory APIs. They allow direct CSV return of the json data.

For example, if we do the same query for devices we did in the previous example, we get some output like this:

➜ http remotemanager.digi.com/ws/v1/devices/bulk query=="connection_status = 'connected' and last_update > -1d and ip startswith '10.20.1.'"
HTTP/1.1 200
 
add_tags,address,alerts,capabilities,carrier,carrier2,cellular_modem_id,channels_uri,compliant,connection_status,contact,customer_id,description,extended_address,firmware_id,firmware_status,firmware_version,geoposition,group,health_status,id,install_code,ip,ipsec_status,ipsec_status2,ipsec_status3,ipsec_status4,key,last_compliant,last_connect,last_disconnect,last_noncompliant,last_noncompliant_reason,last_update,location,mac,maintenance_mode,management_uri,metrics_uri,name,network,network2,notes,parent,password,product_id,public_ip,registration_date,remove_tags,restricted_status,serial_number,signal_percent,signal_percent2,signal_quality,signal_quality2,signal_strength,signal_strength2,sku,tags,type,vendor_id
,,1,413696,,,,"/ws/v1/devices/channels/00000000-00000000-002704FF-FF30D5A1",,connected,"Fred A Kulack",7493,,,,none,20.11.32.168,,demoGroup,error,"00000000-00000000-002704FF-FF30D5A1",,10.20.1.109,,,,,,,2021-02-18T14:21:16.883Z,2021-02-18T14:19:42.387Z,,,2021-02-18T21:01:39.607Z,"Rochester, MN",00:27:04:30:D5:A1,off,"/ws/v1/devices/management/00000000-00000000-002704FF-FF30D5A1","/ws/v1/devices/metrics/00000000-00000000-002704FF-FF30D5A1",SilverSurfer,,,,,,,10.20.1.109,2021-01-11T16:36:00.000Z,,unrestricted,6330010536411709,,,,,,,ASB-6330-MX00-OUS,TestAutomations,"AcceleratedConcepts 6330-MX",4261412874
,,0,,"Bugs Bunny's Binary Bandwidth","Daffy Duck's Digital Services",,"/ws/v1/devices/channels/00000000-00000000-0040FFFF-FF10A300",no,connected,,7493,,,,not_identified,4.8.0.10,"44.067327, -92.506738",demoGroup,normal,"00000000-00000000-0040FFFF-FF10A300",,10.20.1.115,,,,,,2019-12-20T19:58:28.000Z,2021-02-18T14:21:19.663Z,2021-02-18T14:19:42.387Z,2020-12-10T21:32:57.740Z,"Firmware 4.8.0.10 is not compliant",2021-02-18T21:15:01.410Z,,00:40:FF:10:A3:00,off,"/ws/v1/devices/management/00000000-00000000-0040FFFF-FF10A300","/ws/v1/devices/metrics/00000000-00000000-0040FFFF-FF10A300",GhostRider,"FourF (44Ghz)","1XRTT, EVDO0",,,,,10.20.1.115,2019-06-17T15:30:00.000Z,,unrestricted,WR54-001854,90,30,-10,-40,-22,-88,,TestAutomations,"TransPort WR54-DUAL-CELLULAR",4261412873
...etc...

Fields for bulk APIs.

You can use the fields parameter for the bulk APIs to only include the desired fields in the CSV output.

➜ http remotemanager.digi.com/ws/v1/devices/bulk query=="connection_status = 'connected' and last_update > -1d and ip startswith '10.20.1.'" fields=id,connection_status,last_update
HTTP/1.1 200
 
id,connection_status,last_update
00000000-00000000-002704FF-FF30D5A1,connected,2021-02-18T21:01:39.607Z
00000000-00000000-0040FFFF-FF10A300,connected,2021-02-18T21:15:01.410Z
...etc...

Legacy API Examples

API conditions

At the beginning we talked about the legacy APIs being a much more direct mapping of the Remote Manager data model than the v1 APIs.

Because of that, instead of having a storage agnostic query capability for filtering and searching, the legacy APIs use SQL syntax.

NOTE: We do scrub the SQL syntax to prevent SQL injection and use of sql functions and other attacks.

Additionally, conditions require the exact use of the field names (and yes, those fields are what’s in the physical DB. Yuck!)

For example, the /ws/DeviceCore is the legacy API that is closest to ws/v1/devices/inventory API. It returns the device core object.

Lets construct a legacy condition that matches our v1/devices/inventory query

connection_status = 'connected' and last_update > -1d and ip startswith '10.20.1.'"

Note the differences and relative difficulty of use with regard to the enumerated type dpConnectionStatus, and the update time not supporting timestamp shortcuts.

➜ http remotemanager.digi.com/ws/DeviceCore condition=="dpConnectionStatus = 1 and dpGlobalIP like '10.20.1.%' and dpLastUpdateTime > '2021-02-17T21:15:01.410Z'"
HTTP/1.1 200
 
<?xml version="1.0" encoding="ISO-8859-1"?>
<result>
   <resultTotalRows>2</resultTotalRows>
   <requestedStartRow>0</requestedStartRow>
   <resultSize>2</resultSize>
   <requestedSize>1000</requestedSize>
   <remainingSize>0</remainingSize>
   <DeviceCore>
      <id>
         <devId>3412224</devId>
         <devVersion>7</devVersion>
      </id>
      <devRecordStartDate>2021-01-20T14:29:00.000Z</devRecordStartDate>
      <devSerialNo>6330010536411709</devSerialNo>
      <devMac>00:27:04:30:D5:A1</devMac>
      <devConnectwareId>00000000-00000000-002704FF-FF30D5A1</devConnectwareId>
      <cstId>7493</cstId>
      <grpId>261067</grpId>
      <devEffectiveStartDate>2021-01-11T16:36:00.000Z</devEffectiveStartDate>
      <devTerminated>false</devTerminated>
      <dvVendorId>4261412874</dvVendorId>
      <dpDeviceType>AcceleratedConcepts 6330-MX</dpDeviceType>
      <dpFirmwareLevel>336273576</dpFirmwareLevel>
      <dpFirmwareLevelDesc>20.11.32.168</dpFirmwareLevelDesc>
      <dpRestrictedStatus>0</dpRestrictedStatus>
      <dpLastKnownIp>10.20.1.109</dpLastKnownIp>
      <dpGlobalIp>10.20.1.109</dpGlobalIp>
      <dpConnectionStatus>1</dpConnectionStatus>
      <dpLastConnectTime>2021-02-18T14:21:16.883Z</dpLastConnectTime>
      <dpContact>Fred A Kulack</dpContact>
      <dpDescription/>
      <dpLocation>Rochester, MN</dpLocation>
      <dpZigbeeCapabilities>0</dpZigbeeCapabilities>
      <dpCapabilities>481907</dpCapabilities>
      <dpTags>,TestAutomations,</dpTags>
      <grpPath>demoGroup</grpPath>
      <dpLastDisconnectTime>2021-02-18T14:19:42.387Z</dpLastDisconnectTime>
      <dpLastUpdateTime>2021-02-18T21:01:39.607Z</dpLastUpdateTime>
      <dpHealthStatus>2</dpHealthStatus>
      <dpName>SilverSurfer</dpName>
      <numFiredAlarms>1</numFiredAlarms>
      <dpSku>ASB-6330-MX00-OUS</dpSku>
      <dpFirmwareStatus>2</dpFirmwareStatus>
   </DeviceCore>
   <DeviceCore>
        ... snip out single device object...
   </DeviceCore>
</result>

Paging through results

The Legacy API pages through results in a slightly different form, using the size and start parameters.

As you go through each query, you start at row 0, and increase your start row by the requested size for each page.

The output pages use the fields requestedSize, resultSize and resultTotalRows and remainingSize.

In this example, you can see we page through 3 pages.

# Initial page, start at row 0
➜ http remotemanager.digi.com/ws/DeviceCore condition=="dpConnectionStatus = 1" size==1
HTTP/1.1 200
 
<?xml version="1.0" encoding="ISO-8859-1"?>
<result>
   <resultTotalRows>3</resultTotalRows>
   <requestedStartRow>0</requestedStartRow>
   <resultSize>1</resultSize>
   <requestedSize>1</requestedSize>
   <remainingSize>2</remainingSize>
   <DeviceCore>
    ... snip out single device object...
   </DeviceCore>
</result>
 
# Next page, start at row 1
➜ http remotemanager.digi.com/ws/DeviceCore condition=="dpConnectionStatus = 1" size==1 start==1
HTTP/1.1 200
 
<?xml version="1.0" encoding="ISO-8859-1"?>
<result>
   <resultTotalRows>3</resultTotalRows>
   <requestedStartRow>1</requestedStartRow>
   <resultSize>1</resultSize>
   <requestedSize>1</requestedSize>
   <remainingSize>1</remainingSize>
   <DeviceCore>
   ... snip out single device object...
   </DeviceCore>
</result>
 
# Final page, start at row 2
➜ http remotemanager.digi.com/ws/DeviceCore condition=="dpConnectionStatus = 1" size==1 start==2
HTTP/1.1 200
 
<?xml version="1.0" encoding="ISO-8859-1"?>
<result>
   <resultTotalRows>3</resultTotalRows>
   <requestedStartRow>2</requestedStartRow>
   <resultSize>1</resultSize>
   <requestedSize>1</requestedSize>
   <remainingSize>0</remainingSize>
   <DeviceCore>
    ... snip out single device object...
   </DeviceCore>
</result>

JSON output for legacy APIs

You can add a retrieve json from many of the Legacy APIs. However because of the way the legacy API works the conversion is IMPERFECT and you can miss data..

Instead, a preferred solution is to convert to json in the client, using for example the xq tool mentioned at the beginning of this document.

 http remotemanager.digi.com/ws/DeviceCore Accept:application/json condition=="dpConnectionStatus = 1" size==1
HTTP/1.1 200
 
{
    "items": [
        {
            "cstId": "7493",
            "devConnectwareId": "00000000-00000000-0004F3FF-FF0E4BD8",
            "devEffectiveStartDate": "2020-06-02T17:55:00.000Z",
            "devMac": "00:04:F3:0E:4B:D8",
            "devRecordStartDate": "2021-01-29T17:05:00.000Z",
            "devSerialNo": "IX14-420042",
            "devTerminated": "false",
            "dpCapabilities": "481907",
            "dpCompliant": "true",
            "dpConnectionStatus": "1",
            "dpContact": "Fred Kulack",
            "dpDescription": "S1luwLvGdnfF0nFnoPQ8Rb0bLeecqV5K0p0BSBlZRd1EddeV8y",
            "dpDeviceType": "Digi IX14",
            "dpFirmwareLevel": "336273576",
            "dpFirmwareLevelDesc": "20.11.32.168",
            "dpFirmwareStatus": "2",
            "dpGlobalIp": "172.20.10.3",
            "dpHealthStatus": "0",
            "dpLastCompliant": "2021-01-29T17:21:42.203Z",
            "dpLastConnectTime": "2021-02-18T14:21:17.130Z",
            "dpLastDisconnectTime": "2021-02-18T14:19:42.387Z",
            "dpLastKnownIp": "172.20.10.3",
            "dpLastNonCompliant": "2021-01-29T17:21:38.583Z",
            "dpLastNonCompliantReason": "1 settings are not compliant: system/1/contact",
            "dpLastUpdateTime": "2021-02-18T22:08:29.560Z",
            "dpLocation": "Rochester, MN 1",
            "dpName": "Vision",
            "dpRestrictedStatus": "0",
            "dpSignalPercent": "47",
            "dpSku": "IX14-M601",
            "dpTags": ",TestAutomations,",
            "dpZigbeeCapabilities": "0",
            "dvVendorId": "4261412874",
            "grpId": "228227",
            "grpPath": "Configs",
            "id": {
                "devId": "3134058",
                "devVersion": "24"
            },
            "numFiredAlarms": "1"
        }
    ],
    "remainingSize": "2",
    "requestedSize": "1",
    "requestedStartRow": "0",
    "resultSize": "1",
    "resultTotalRows": "3"
}