Using the Mender API: The Basics of the Management API

api Api icons created by DinosoftLabs - Flaticon

Customer engineer Alan Martinovic explores the basics of using the Mender API - specifically the management API

Mender was designed with easy integration into CI CD pipelines and fleet management workflows in mind and this is also reflected in our open core business offering and in our open source offering. Open REST APIs are the practical manifestation of this. This article will provide you with all you need to quickly get started with the Mender API. Refer to the Mender Docs for full implementation details on the management API and the Device API.

Overview of Mender API

The Mender API is separated into two categories:

  • Device API - the IoT device which has the Mender client installed uses the device API to poll for and receive the updates
  • Management API - these are what the UI uses and what you can leverage to create automations in your OTA software deployment workflows.

This tutorial will focus on the use of the Management API.


As you start reading through the Management API documentation you will notice that some sections are seemingly duplicated with a version number in front of it.

Those represent the higher version of the API. As described in the Mender API docs:

The higher version API contains a mix of old and new API endpoints. For endpoints which haven't changed in the new version the previous version endpoints are assumed. Practically, this translates always using the highest API version available. If an endpoint is not there, the one from the previous API version is assumed.


To start working with the API, you will need to authenticate. Practically this means that getting a hold of a JWT token the server considers valid. Only with that token in your API calls will the server grant you access.

There are two ways to get the JWT token:

Directly generate a Personal Access Token in Hosted Mender Call the /api/management/v1/useradm/auth/login API endpoint with your Hosted Mender username and password and have the server return the token for you.

The usage of a PAT is recommended when dealing with the API as it gives the flexibility by allowing to set an expiration period.

For this tutorial we will use the username and password approach to generate a PAT. From there the PAT will be used in the rest of the examples.[1]

Hands on examples - bash

Assumptions: You've registered for the Mender free trial and successfully completed the Get started process.

The following tools are available in your command line:

  • curl - to send the http requests
  • jq - it will be used to parse the json files

Authentication - getting the PAT

Generating a PAT requires an API call. To make this API call, we need to authenticate with a username and password.

USER= <----- The email you use to sign into Hosted Mender i.e.
PASS= <----- The password you use to sign into Hosted Mender

# i.e.
# PASS=123456


JWT_TEMP=$(curl -X POST -H "Content-Type: application/json;" -u "$USER:$PASS" $BASE_URL$API_ENDPOINT)

echo $JWT_TEMP

# A large string of random characters will be printed

Now that we can make API calls, let's generate a PAT.


UNIQUE=$(openssl rand -hex 5)

  "name": "demo-pat-$UNIQUE",
  "expires_in": 7200

  -H 'Content-Type: application/json' \
  -H "Accept: application/json" \
  -H "Authorization: Bearer $JWT_TEMP" \

echo $JWT

This PAT is also a JWT token that will be used in the examples. All future examples rely on the existence of the JWT environment variable.

Example 1 - list all devices by their identity

The Device Identity is:

A unique set of key-value pairs produced by the device and unchangeable for the lifecycle of the device. It is generated by the script on the device located at /usr/share/mender/identity/mender-device-identity.

Not to be confused with Device ID which is a:

A unique, unchangeable identifier the server assigns internally to every device.

When using the API's you are exposed to both of these identifiers, and for this example we're interested in getting the Device Identity for all devices.

Let's first get all the device data and store it in a file:


  -H "Accept: application/json" \
  -H "Authorization: Bearer $JWT"  >  devices.json

jq length devices.json
# Outputs 1

In this example, 1 device is already a part of the system as part of the Getting started.

Now as the json response is stored in the file, we need to understand its structure.

The response schema for the /devices endpoint is listed in the docs for the List Devices API endpoint.

Listing based on the value of identity_data will give us the answer we're looking for.

jq '.[].identity_data' devices.json 
# #{
# "mac": "52:54:00:ce:34:5b"

Example 2 - get the inventory data of a device

In the previous example we've listed the Device Identities. Now we want to know the inventory attributes of a specific device. The device inventory is:

A customizable list of key=value pairs providing information about the device. The inventory key=value pairs are generated by the scripts located at /usr/share/mender/inventory/ on the device. The device sends the updated inventory values to the server with the period defined by InventoryPollIntervalSeconds.

The Get Device Inventory endpoint can be used for that. However it soon becomes obvious that we can't use the Device Identity as input, instead what is needed is the Device ID.

The snippet below is a quick way to get the Device ID[2]:

DEVICE_ID=$(jq -r '.[] | select(.identity_data.mac=="b8:27:eb:d6:95:af") | .id' devices.json)

With the Device ID available we can get the device inventory:


  -H "Accept: application/json" \
  -H "Authorization: Bearer $JWT"    >  inventory-$DEVICE_IDENTITY.json

The device inventory is large so it won't be listed here. You can print and examine it by running jq . inventory-$DEVICE_IDENTITY.json

Example 3 - create a new user and assign it a new role

Let's create a new user now using the Create User API endpoint:


EMAIL="$(openssl rand -hex 5)"
PASSWORD=$(openssl rand -base64 10)

  "email": "$EMAIL",
  "password": "$PASSWORD",
  "login": {}

  -H 'Content-Type: application/json' \
  -H "Accept: application/json" \
  -H "Authorization: Bearer $JWT" \

The above command created the user. [3] Let's locate the new user and get some information about them. We first need to get a list of all the users, and then filter out the one relevant to us:


  -H "Accept: application/json" \
  -H "Authorization: Bearer $JWT"    >  all-users.json

jq --arg EMAIL "$EMAIL"  -r '.[] | select(.email==$EMAIL)' all-users.json
# {
# "id": "22d01bc9-e67d-4a0c-81d1-2fc2061adff5",
# "email": "",
# "tfa_status": "",
# "created_ts": "2022-12-13T13:38:59.228Z",
# "updated_ts": "2022-12-13T13:38:59.228Z",
# "roles": [
# ]
# }

Mender Enterprise plan and free trial have a concept of [Role Based Access Control (RBAC)[(

A Role is a set of permissions you can assign to a user. A user can have multiple Roles and a Role can be assigned to multiple different users.

Seems like our new user was created with an admin role [RBAC_ROLE_PERMIT_ALL]. Let's check the roles for something less permissive.


  -H "Accept: application/json" \
  -H "Authorization: Bearer $JWT"  |  jq .[].name

The RBAC_ROLE_OBSERVER is a much more restrictive, read-only role. Let's assign it to the new user instead.

USER_ID=$(jq --arg EMAIL "$EMAIL"  -r '.[] | select(.email==$EMAIL) | .id' all-users.json)


  "roles": [

  -H 'Content-Type: application/json' \
  -H "Accept: application/json" \
  -H "Authorization: Bearer $JWT" \

Once the new role is set, let's quickly call the List users again to confirm the change:


  -H "Accept: application/json" \
  -H "Authorization: Bearer $JWT"    | jq --arg EMAIL "$EMAIL"  -r '.[] | select(.email==$EMAIL)'

The output confirms the new user has the new role [RBAC_ROLE_OBSERVER].

Try out the Mender API for yourself

The few examples in this tutorial provided a taste of what it's like to use the Mender API. This only scratches the surface of what you can do with the API, but it provides a working reference you can copy and modify to explore the workings of other API endpoints.

[1] - if you have created your account using SSO (Github/Google/Microsoft) you will need to create the PAT using the UI.

[2] - please note that we're assuming that the key for the Device identity is mac which is the default. If you modified this to another value, the script will need to be adjusted.

[3] - for return codes other then success (201) please take a look at the list of responses.

Recent articles

How over-the-air (OTA) updates help emergency response teams

How over-the-air (OTA) updates help emergency response teams

There’s no getting around it—we live in a connected world where almost every industry is dependent on the Internet of Things (IoT).
What’s hot in the open source and embedded community?

What’s hot in the open source and embedded community?

AI, robotics, IoT, AVs, and more – 2024 is proving to be an exciting year for technology. And the open source and embedded tech community is no exception.
How to use over-the-air (OTA) updates & NVIDIA Jetson Microservices

How to leverage over-the-air (OTA) updates with NVIDIA Microservices for Jetson

Mender, in collaboration with NVIDIA, published two critical use cases, providing a step-by-step guide to over-the-air (OTA) updates with NVIDIA Jetson.
View more articles

Learn more about Mender

Explore our Resource Center to discover more about how Mender empowers both you and your customers with secure and reliable over-the-air updates for IoT devices.