NAV Navigation
HTTP Shell Python Go Java JavaScript PHP Ruby

Introduction

Welcome to the Mender API reference documentation.

REST

The Mender API is a RESTful API. This means that the API is designed to allow you to get, create, update, & delete objects with the HTTP verbs GET, POST, PUT, PATCH, & DELETE. The APIs make use of CORS (cross-origin-request) which also uses the OPTIONS request method.

Device and Management APIs

The public APIs are split into two types - Device and Management. Device APIs are for device-originating requests, the Management APIs are intended for use by the UI and other tools that manage devices, Artifacts or deployments across devices.

Internal APIs

Internal APIs are used by Mender's backend services to communicate with each other. They can also be used to integrate third party systems with the backend when installing Mender on-premise. Note: the API gateway does not expose these endpoints; they are not available for direct consumption by clients on hosted Mender.

API Versioning and compatibility

The APIs are being continuously reviewed and improved.

The following changes are considered backwards-compatible and users of the APIs should be flexible enough to handle them:

If API compatibility needs to be broken at some point, the version number in the URI will be increased, e.g. from /api/management/v1/deployments to /api/management/v2/deployments. In such cases, both versions will be supported by the server for some period to allow for graceful transition.

Device APIs

Device authentication

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for device authentication handling. Intended for use by devices.

Base URLs:

Authenticate Device

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/devices/v1/authentication/auth_requests \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'X-MEN-Signature: string' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/devices/v1/authentication/auth_requests HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json
X-MEN-Signature: string

const inputBody = '{
  "id_data": "{\"mac\":\"00:01:02:03:04:05\"}",
  "pubkey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzogVU7RGDilbsoUt/DdH\nVJvcepl0A5+xzGQ50cq1VE/Dyyy8Zp0jzRXCnnu9nu395mAFSZGotZVr+sWEpO3c\nyC3VmXdBZmXmQdZqbdD/GuixJOYfqta2ytbIUPRXFN7/I7sgzxnXWBYXYmObYvdP\nokP0mQanY+WKxp7Q16pt1RoqoAd0kmV39g13rFl35muSHbSBoAW3GBF3gO+mF5Ty\n1ddp/XcgLOsmvNNjY+2HOD5F/RX0fs07mWnbD7x+xz7KEKjF+H7ZpkqCwmwCXaf0\niyYyh1852rti3Afw4mDxuVSD7sd9ggvYMc0QHIpQNkD4YWOhNiE1AB0zH57VbUYG\nUwIDAQAB\n-----END PUBLIC KEY-----\n"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'X-MEN-Signature':'string',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/devices/v1/authentication/auth_requests',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'X-MEN-Signature' => 'string',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/devices/v1/authentication/auth_requests',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'X-MEN-Signature': 'string',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/devices/v1/authentication/auth_requests', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'X-MEN-Signature' => 'string',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/devices/v1/authentication/auth_requests', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/devices/v1/authentication/auth_requests");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "X-MEN-Signature": []string{"string"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/devices/v1/authentication/auth_requests", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /auth_requests

Submit an authentication request

The device presents its unique identity data and public key, and signs the request with its private key. If the request is valid and the device is known to the system, a valid JWT authentication token is issued.

Unless the device is pre-authorized, the very first authentication request from a device will always result in a 'HTTP 401 Unauthorized' response. At the same time, the identity data is recorded for later inspection by the user, who can then explicitly accepts or rejects the device via the web GUI. A subsequent authentication request will reflect this decision.

Note that when the JWT expires, the device must renew the JWT by sending a new authentication request.

Body parameter

{
  "id_data": "{\"mac\":\"00:01:02:03:04:05\"}",
  "pubkey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzogVU7RGDilbsoUt/DdH\nVJvcepl0A5+xzGQ50cq1VE/Dyyy8Zp0jzRXCnnu9nu395mAFSZGotZVr+sWEpO3c\nyC3VmXdBZmXmQdZqbdD/GuixJOYfqta2ytbIUPRXFN7/I7sgzxnXWBYXYmObYvdP\nokP0mQanY+WKxp7Q16pt1RoqoAd0kmV39g13rFl35muSHbSBoAW3GBF3gO+mF5Ty\n1ddp/XcgLOsmvNNjY+2HOD5F/RX0fs07mWnbD7x+xz7KEKjF+H7ZpkqCwmwCXaf0\niyYyh1852rti3Afw4mDxuVSD7sd9ggvYMc0QHIpQNkD4YWOhNiE1AB0zH57VbUYG\nUwIDAQAB\n-----END PUBLIC KEY-----\n"
}

Parameters

Name In Type Required Description
X-MEN-Signature header string true Request signature.
body body AuthRequest true Authentication request.

Detailed descriptions

X-MEN-Signature: Request signature.

The request signature depends on the public key submitted in the AuthRequest. A summary of signature algorithms and format follows:

Type Digest Format Algorithm
RSA SHA256(AuthRequest) Base64(Signature) [RFC2313]
ECDSA SHA256(AuthRequest) Base64(ASN.1(SEQ{R, S})) [ANSI x9.62]
ED25519 AuthRequest Base64(Signature) [RFC8032]

Remark: For ECDSA, the signature constitutes two integers (R and S) in which case the binary signature is taken as the ASN.1 sequence of the two numbers in the given order.

Example responses

200 Response

"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NzYxMTkxMzYsImp0aSI6Ijg1NGIzMTA5LTQ4NjItNGEyNS1hMWZiLWYxMTE2MWNlN2E4NCIsImlzcyI6Ik1lbmRlciIsInN1YiI6IjlmNzM2YmNiMjhiZmFhOTg5YjVmNWUxNDA5ZGJmMGVhYzdhNjYxMjZiNjMyZDAzYWYwZmUzNGFjMjhiZjRhNzIifQ.PArg_WuoQkOiJ4kDoHYbQRjnxykeF1lIlsgJfUryhivnip2AHz5bkxxaxF20XTq9mIzSDonTSukfOtkaxJTZXjCMHjgh50iwa6_pUivIYWsIJW2O9t_M9T_SC-7Xu7IhE_iKQFb2NXxVfAG4nZKrheUM4MJBt8SxCawT2EOPopiLeIC6MOFBu_sPa9RsagKSZCRaLTBWVhmEGbfn19tLOX3Z06DZql61G-VY-YuyOlBjpEsCc4HiA1cXIdncCZKugrONOa44_m4yx0VsgRg4jCd2VO-Is-A96Jw3zkZshoD2cPXVSKAhFdhHja447ftuYYRq9kIQghKi3hfsPgyFZQ\n"

Missing or malformed request parameters or body.

{
  "error": "missing required parameter: id_data",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188f"
}

The device cannot be granted authentication. See the error message for details.

{
  "error": "device unauthorized",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Internal server error.

{
  "error": "internal error",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188d"
}

Responses

Status Meaning Description Schema
200 OK Authentication successful - a new JWT is issued and returned. string
400 Bad Request Missing or malformed request parameters or body. Error
401 Unauthorized The device cannot be granted authentication. See the error message for details. Error
500 Internal Server Error Internal server error. Error

Schemas

AuthRequest

{
  "id_data": "{\"mac\":\"00:01:02:03:04:05\"}",
  "pubkey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzogVU7RGDilbsoUt/DdH\nVJvcepl0A5+xzGQ50cq1VE/Dyyy8Zp0jzRXCnnu9nu395mAFSZGotZVr+sWEpO3c\nyC3VmXdBZmXmQdZqbdD/GuixJOYfqta2ytbIUPRXFN7/I7sgzxnXWBYXYmObYvdP\nokP0mQanY+WKxp7Q16pt1RoqoAd0kmV39g13rFl35muSHbSBoAW3GBF3gO+mF5Ty\n1ddp/XcgLOsmvNNjY+2HOD5F/RX0fs07mWnbD7x+xz7KEKjF+H7ZpkqCwmwCXaf0\niyYyh1852rti3Afw4mDxuVSD7sd9ggvYMc0QHIpQNkD4YWOhNiE1AB0zH57VbUYG\nUwIDAQAB\n-----END PUBLIC KEY-----\n"
}

Properties

Name Type Required Description
id_data string true Vendor-specific JSON representation of the device identity data (MACs, serial numbers, etc.).
pubkey string true The device's public key (PEM encoding), generated by the device or pre-provisioned by the vendor. Currently supported public algorithms are: RSA, ED25519 and ECDSA.
tenant_token string false Tenant token.

Error

{
  "error": "error description goes here",
  "request_id": "f7881e82-0492-49fb-b459-795654e71877"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID (same as in X-MEN-RequestID header).

Device inventory

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for uploading device attributes. Intended for use by devices.

Devices can upload vendor-specific attributes (software/hardware info, health checks, metrics, etc.) of various data types to the backend.

Base URLs:

Assign Attributes

Code samples

# You can also use wget
curl -X PATCH https://hosted.mender.io/api/devices/v1/inventory/device/attributes \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

PATCH https://hosted.mender.io/api/devices/v1/inventory/device/attributes HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '[
  {
    "name": "ip_addr",
    "value": "1.2.3.4",
    "description": "IP address"
  },
  {
    "name": "mac_addr",
    "value": "00.01:02:03:04:05",
    "description": "MAC address"
  }
]';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/devices/v1/inventory/device/attributes',
{
  method: 'PATCH',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.patch 'https://hosted.mender.io/api/devices/v1/inventory/device/attributes',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.patch('https://hosted.mender.io/api/devices/v1/inventory/device/attributes', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PATCH','https://hosted.mender.io/api/devices/v1/inventory/device/attributes', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/devices/v1/inventory/device/attributes");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PATCH");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PATCH", "https://hosted.mender.io/api/devices/v1/inventory/device/attributes", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PATCH /device/attributes

Assign a set of attributes for a device

Saves the provided attribute set for the authenticated device. The device ID is retrieved from the authorization header.

This method has upsert semantics:

Body parameter

[
  {
    "name": "ip_addr",
    "value": "1.2.3.4",
    "description": "IP address"
  },
  {
    "name": "mac_addr",
    "value": "00.01:02:03:04:05",
    "description": "MAC address"
  }
]

Parameters

Name In Type Required Description
body body Attribute true A list of attribute descriptors.

Example responses

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Attributes were uploaded successfully. None
400 Bad Request Missing/malformed request parameters or body. Error
401 Unauthorized The device is not authenticated. None
500 Internal Server Error Internal server error. Error

Schemas

Attribute

{
  "name": "ip_addr_eth",
  "description": "Device IP address on ethernet interface",
  "value": "127.0.0.1"
}

Attribute descriptor.

Properties

Name Type Required Description
name string true A human readable, unique attribute ID, e.g. 'device_type', 'ip_addr', 'cpu_load', etc.
description string false Attribute description.
value string true The current value of the attribute.

Attribute type is implicit, inferred from the JSON type.

Supported types: number, string, array of numbers, array of strings.
Mixed type arrays are not allowed.

Error

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID (same as in X-MEN-RequestID header).

Deployments

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for device firmware deployments. Intended for use by devices.

Devices can get new updates and send information about current deployment status.

Base URLs:

Check Update

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next?artifact_name=string&device_type=string \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next?artifact_name=string&device_type=string HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next?artifact_name=string&device_type=string',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next',
  params: {
  'artifact_name' => 'string',
'device_type' => 'string'
}, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next', params={
  'artifact_name': 'string',  'device_type': 'string'
}, headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next?artifact_name=string&device_type=string");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /device/deployments/next

Get next update

On success, either an empty response or a DeploymentInstructions object is returned depending on whether there are any pending updates.

Parameters

Name In Type Required Description
artifact_name query string true currently installed artifact
device_type query string true Device type of device

Example responses

Successful response.

{
  "id": "w81s4fae-7dec-11d0-a765-00a0c91e6bf6",
  "artifact": {
    "artifact_name": "my-app-0.1",
    "source": {
      "uri": "https://aws.my_update_bucket.com/image_123",
      "expire": "2016-03-11T13:03:17.063493443Z"
    },
    "device_types_compatible": [
      "rspi",
      "rspi2",
      "rspi0"
    ]
  }
}

400 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response. DeploymentInstructions
204 No Content No updates for device. None
400 Bad Request Invalid Request. Error
404 Not Found Not Found. Error
500 Internal Server Error Internal Server Error. Error

Check Update Depends

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "device_type": "rspi",
  "artifact_name": "prototype-v1.0.0",
  "rootfs_image_checksum": "4d480539cdb23a4aee6330ff80673a5af92b7793eb1c57c4694532f96383b619"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/devices/v1/deployments/device/deployments/next", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /device/deployments/next

Get a next update satisfying dependencies

Returns the next update to be installed on the device. Next update will be chosen based on parameters provided in the request body. Request body should contain artifact_provides object.

Body parameter

{
  "device_type": "rspi",
  "artifact_name": "prototype-v1.0.0",
  "rootfs_image_checksum": "4d480539cdb23a4aee6330ff80673a5af92b7793eb1c57c4694532f96383b619"
}

Parameters

Name In Type Required Description
body body object true Key-value map of strings which describes the artifact(s) installed on the device and the
» additionalProperties body string false
» device_type body string true Device type of the device.
» artifact_name body string true Name of the currently installed artifact.

Detailed descriptions

body: Key-value map of strings which describes the artifact(s) installed on the device and the device itself. It is used to determine the next deployment. The keys device_type and artifact_name are mandatory, additional free-form key-value pairs can be specified.

Example responses

Successful response.

{
  "id": "w81s4fae-7dec-11d0-a765-00a0c91e6bf6",
  "artifact": {
    "artifact_name": "my-app-0.1",
    "source": {
      "uri": "https://aws.my_update_bucket.com/image_123",
      "expire": "2016-03-11T13:03:17.063493443Z"
    },
    "device_types_compatible": [
      "rspi",
      "rspi2",
      "rspi0"
    ]
  }
}

400 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response. DeploymentInstructions
204 No Content No updates for device. None
400 Bad Request Invalid Request. Error
404 Not Found Not Found. Error
500 Internal Server Error Internal Server Error. Error

Update Deployment Status

Code samples

# You can also use wget
curl -X PUT https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/status \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

PUT https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/status HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "status": "success"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/status',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.put 'https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/status',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.put('https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/status', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/status', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/status");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/status", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /device/deployments/{id}/status

Update the device deployment status

Updates the status of a deployment on a particular device. Final status of the deployment is required to be set to indicate the success or failure of the installation process. The status can not be changed when deployment status is set to aborted. Reporting of intermediate steps such as installing, downloading, rebooting is optional.

Body parameter

{
  "status": "success"
}

Parameters

Name In Type Required Description
id path string true Deployment identifier.
body body DeploymentStatus true Deployment status.

Example responses

400 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Status updated successfully. None
400 Bad Request Invalid Request. Error
404 Not Found Not Found. Error
409 Conflict Status already set to aborted. None
500 Internal Server Error Internal Server Error. Error

Report Deployment Log

Code samples

# You can also use wget
curl -X PUT https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/log \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

PUT https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/log HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "messages": [
    {
      "timestamp": "2016-03-11T13:03:17.063493443Z",
      "level": "INFO",
      "message": "OK"
    },
    {
      "timestamp": "2016-03-11T13:03:18.023765782Z",
      "level": "DEBUG",
      "message": "successfully updated."
    }
  ]
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/log',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.put 'https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/log',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.put('https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/log', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/log', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/log");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "https://hosted.mender.io/api/devices/v1/deployments/device/deployments/{id}/log", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /device/deployments/{id}/log

Upload the device deployment log

Set the log of a selected deployment. Messages are split by line in the payload.

Body parameter

{
  "messages": [
    {
      "timestamp": "2016-03-11T13:03:17.063493443Z",
      "level": "INFO",
      "message": "OK"
    },
    {
      "timestamp": "2016-03-11T13:03:18.023765782Z",
      "level": "DEBUG",
      "message": "successfully updated."
    }
  ]
}

Parameters

Name In Type Required Description
id path string true Deployment identifier.
body body DeploymentLog true Deployment log

Example responses

400 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content The deployment log uploaded successfully. None
400 Bad Request Invalid Request. Error
404 Not Found Not Found. Error
500 Internal Server Error Internal Server Error. Error

Schemas

Error

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID (same as in X-MEN-RequestID header).

DeploymentStatus

{
  "status": "success"
}

Properties

Name Type Required Description
status string true
substate string false Additional state information

Enumerated Values

Property Value
status installing
status downloading
status rebooting
status success
status failure
status already-installed

DeploymentInstructions

{
  "id": "w81s4fae-7dec-11d0-a765-00a0c91e6bf6",
  "artifact": {
    "artifact_name": "my-app-0.1",
    "source": {
      "uri": "https://aws.my_update_bucket.com/image_123",
      "expire": "2016-03-11T13:03:17.063493443Z"
    },
    "device_types_compatible": [
      "rspi",
      "rspi2",
      "rspi0"
    ]
  }
}

Properties

Name Type Required Description
id string true Deployment ID (device unique)
artifact object true
» source object true
»» uri string(url) false URL to fetch the artifact from
»» expire string(date-time) false URL expiration time
» device_types_compatible [string] true Compatible device types
» artifact_name string true

DeploymentLog

{
  "messages": [
    {
      "timestamp": "2016-03-11T13:03:17.063493443Z",
      "level": "INFO",
      "message": "OK"
    },
    {
      "timestamp": "2016-03-11T13:03:18.023765782Z",
      "level": "DEBUG",
      "message": "successfully updated."
    }
  ]
}

Properties

Name Type Required Description
messages [object] true
» timestamp string(date-time) true
» level string true
» message string true

Management APIs

Device authentication

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for device authentication handling.

Base URLs:

List Devices

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v2/devauth/devices \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v2/devauth/devices HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/devauth/devices',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v2/devauth/devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v2/devauth/devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v2/devauth/devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/devauth/devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v2/devauth/devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /devices

List devices sorted by age and optionally filter on device status.

Parameters

Name In Type Required Description
status query string false Device status filter. If not specified, all devices are listed.
id query string false Device ID filter. Can be repeated to query a set of devices.
page query integer false Results page number
per_page query integer false Maximum number of results per page.

Detailed descriptions

status: Device status filter. If not specified, all devices are listed.

id: Device ID filter. Can be repeated to query a set of devices.

Enumerated Values

Parameter Value
status pending
status accepted
status rejected
status preauthorized
status noauth

Example responses

200 Response

[
  {
    "id": "string",
    "identity_data": {
      "mac": "00:01:02:03:04:05",
      "sku": "My Device 1",
      "sn": "SN1234567890"
    },
    "status": "pending",
    "created_ts": "2019-08-24T14:15:22Z",
    "updated_ts": "2019-08-24T14:15:22Z",
    "auth_sets": [
      {
        "id": "string",
        "pubkey": "string",
        "identity_data": {
          "mac": "00:01:02:03:04:05",
          "sku": "My Device 1",
          "sn": "SN1234567890"
        },
        "status": "pending",
        "ts": "2019-08-24T14:15:22Z"
      }
    ],
    "decommissioning": true
  }
]

Responses

Status Meaning Description Schema
200 OK An array of devices. Inline
400 Bad Request Missing/malformed request params. Error
500 Internal Server Error Unexpected error Error

Response Schema

Status Code 200

Name Type Required Restrictions Description
anonymous [Device] false
» id string false Mender assigned Device ID.
» identity_data IdentityData false Device identity attributes, in the form of a JSON structure.

The attributes are completely vendor-specific, the provided ones are just an example.
In reference implementation structure contains vendor-selected fields,
such as MACs, serial numbers, etc.
»» mac string false MAC address.
»» sku string false Stock keeping unit.
»» sn string false Serial number.
» status string false
» created_ts string(date-time) false Created timestamp
» updated_ts string(date-time) false Updated timestamp
» auth_sets [AuthSet] false [Authentication data set]
»» id string false Authentication data set ID.
»» pubkey string false The device's public key (PEM encoding), generated by the device or pre-provisioned by the vendor. Currently supported public algorithms are: RSA, ED25519 and ECDSA.
»» identity_data IdentityData false Device identity attributes, in the form of a JSON structure.

The attributes are completely vendor-specific, the provided ones are just an example.
In reference implementation structure contains vendor-selected fields,
such as MACs, serial numbers, etc.
»» status string false
»» ts string(date-time) false Created timestamp
» decommissioning boolean false Devices that are part of ongoing decomissioning process will return True

Enumerated Values

Property Value
status pending
status accepted
status rejected
status preauthorized
status noauth
status pending
status accepted
status rejected
status preauthorized
status noauth

Response Headers

Status Header Type Format Description
200 Link string Standard header, we support 'first', 'next', and 'prev'.

Preauthorize

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v2/devauth/devices \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v2/devauth/devices HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "identity_data": {
    "mac": "00:01:02:03:04:05",
    "sku": "My Device 1",
    "sn": "SN1234567890"
  },
  "pubkey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzogVU7RGDilbsoUt/DdH\nVJvcepl0A5+xzGQ50cq1VE/Dyyy8Zp0jzRXCnnu9nu395mAFSZGotZVr+sWEpO3c\nyC3VmXdBZmXmQdZqbdD/GuixJOYfqta2ytbIUPRXFN7/I7sgzxnXWBYXYmObYvdP\nokP0mQanY+WKxp7Q16pt1RoqoAd0kmV39g13rFl35muSHbSBoAW3GBF3gO+mF5Ty\n1ddp/XcgLOsmvNNjY+2HOD5F/RX0fs07mWnbD7x+xz7KEKjF+H7ZpkqCwmwCXaf0\niyYyh1852rti3Afw4mDxuVSD7sd9ggvYMc0QHIpQNkD4YWOhNiE1AB0zH57VbUYG\nUwIDAQAB\n-----END PUBLIC KEY-----\n"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/devauth/devices',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v2/devauth/devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v2/devauth/devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v2/devauth/devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/devauth/devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v2/devauth/devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /devices

Submit a preauthorized device.

Authorize a device identity with the server backend. On success the device identity is marked as 'preauthorized', and once the device connects and sends it's first authentication request the device automatically become 'accepted' without explicit user intervention.

Body parameter

{
  "identity_data": {
    "mac": "00:01:02:03:04:05",
    "sku": "My Device 1",
    "sn": "SN1234567890"
  },
  "pubkey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzogVU7RGDilbsoUt/DdH\nVJvcepl0A5+xzGQ50cq1VE/Dyyy8Zp0jzRXCnnu9nu395mAFSZGotZVr+sWEpO3c\nyC3VmXdBZmXmQdZqbdD/GuixJOYfqta2ytbIUPRXFN7/I7sgzxnXWBYXYmObYvdP\nokP0mQanY+WKxp7Q16pt1RoqoAd0kmV39g13rFl35muSHbSBoAW3GBF3gO+mF5Ty\n1ddp/XcgLOsmvNNjY+2HOD5F/RX0fs07mWnbD7x+xz7KEKjF+H7ZpkqCwmwCXaf0\niyYyh1852rti3Afw4mDxuVSD7sd9ggvYMc0QHIpQNkD4YWOhNiE1AB0zH57VbUYG\nUwIDAQAB\n-----END PUBLIC KEY-----\n"
}

Parameters

Name In Type Required Description
body body PreAuthSet true Preauthentication request.

Example responses

400 Response

{
  "error": "string"
}

Responses

Status Meaning Description Schema
201 Created Device submitted. None
400 Bad Request Missing/malformed request params. Error
409 Conflict Device already exists. Response contains conflicting device. Device
500 Internal Server Error Unexpected error Error

Response Headers

Status Header Type Format Description
201 Location string URL of the newly created user-ID.

Get Device

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v2/devauth/devices/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v2/devauth/devices/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/devauth/devices/{id}',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v2/devauth/devices/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v2/devauth/devices/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v2/devauth/devices/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/devauth/devices/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v2/devauth/devices/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /devices/{id}

Get a particular device.

Parameters

Name In Type Required Description
id path string true Device identifier

Example responses

200 Response

{
  "id": "string",
  "identity_data": {
    "mac": "00:01:02:03:04:05",
    "sku": "My Device 1",
    "sn": "SN1234567890"
  },
  "status": "pending",
  "created_ts": "2019-08-24T14:15:22Z",
  "updated_ts": "2019-08-24T14:15:22Z",
  "auth_sets": [
    {
      "id": "string",
      "pubkey": "string",
      "identity_data": {
        "mac": "00:01:02:03:04:05",
        "sku": "My Device 1",
        "sn": "SN1234567890"
      },
      "status": "pending",
      "ts": "2019-08-24T14:15:22Z"
    }
  ],
  "decommissioning": true
}

Responses

Status Meaning Description Schema
200 OK Device found. Device
404 Not Found Device not found. Error
500 Internal Server Error Unexpected error Error

Decommission device

Code samples

# You can also use wget
curl -X DELETE https://hosted.mender.io/api/management/v2/devauth/devices/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

DELETE https://hosted.mender.io/api/management/v2/devauth/devices/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/devauth/devices/{id}',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.delete 'https://hosted.mender.io/api/management/v2/devauth/devices/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.delete('https://hosted.mender.io/api/management/v2/devauth/devices/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://hosted.mender.io/api/management/v2/devauth/devices/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/devauth/devices/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://hosted.mender.io/api/management/v2/devauth/devices/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /devices/{id}

Remove device and associated authentication set

Parameters

Name In Type Required Description
id path string true Device identifier.

Example responses

404 Response

{
  "error": "string"
}

Responses

Status Meaning Description Schema
204 No Content Device decommissioned. None
404 Not Found Device not found Error
500 Internal Server Error Internal server error. Error

Reject authentication

Code samples

# You can also use wget
curl -X DELETE https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

DELETE https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.delete 'https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.delete('https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /devices/{id}/auth/{aid}

Remove the device authentication set

Removes the device authentication set. Removing 'accepted' authentication set is equivalent to rejecting device and removing authentication set. If there is only one authentication set for the device and the device is 'preauthorized' then the device will also be deleted.

Parameters

Name In Type Required Description
id path string true Device identifier.
aid path string true Authentication data set identifier.

Example responses

404 Response

{
  "error": "string"
}

Responses

Status Meaning Description Schema
204 No Content Device authentication set deleted. None
404 Not Found Device authentication set not found Error
500 Internal Server Error Internal server error. Error

Set Authentication Status

Code samples

# You can also use wget
curl -X PUT https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

PUT https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "status": "accepted"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.put 'https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.put('https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /devices/{id}/auth/{aid}/status

Update the device authentication set status

Sets the status of a authentication data set of selected value. Valid state transitions:

Body parameter

{
  "status": "accepted"
}

Parameters

Name In Type Required Description
id path string true Device identifier.
aid path string true Authentication data set identifier.
body body Status true New status.

Example responses

400 Response

{
  "error": "string"
}

Responses

Status Meaning Description Schema
204 No Content The device authentication data set status was successfully updated. None
400 Bad Request Bad request. Error
404 Not Found The device was not found. Error
422 Unprocessable Entity Request cannot be fulfilled e.g. due to exceeded limit on maximum accepted devices (see error message). Error
500 Internal Server Error Internal server error. Error

Get Authentication Status

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v2/devauth/devices/{id}/auth/{aid}/status", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /devices/{id}/auth/{aid}/status

Get the device authentication set status

Parameters

Name In Type Required Description
id path string true Device identifier.
aid path string true Authentication data set identifier.

Example responses

successful response - the device's authentication set status is returned.

{
  "status": "accepted"
}

404 Response

{
  "error": "string"
}

Responses

Status Meaning Description Schema
200 OK successful response - the device's authentication set status is returned. Status
404 Not Found The device was not found. Error
500 Internal Server Error Internal server error. Error

Count Devices

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v2/devauth/devices/count \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v2/devauth/devices/count HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/devauth/devices/count',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v2/devauth/devices/count',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v2/devauth/devices/count', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v2/devauth/devices/count', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/devauth/devices/count");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v2/devauth/devices/count", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /devices/count

Count number of devices, optionally filtered by status.

Parameters

Name In Type Required Description
status query string false Device status filter, one of 'pending', 'accepted', 'rejected', 'noauth'. Default is 'all devices'.

Detailed descriptions

status: Device status filter, one of 'pending', 'accepted', 'rejected', 'noauth'. Default is 'all devices'.

Example responses

200 Response

{
  "count": 42
}

Responses

Status Meaning Description Schema
200 OK Device count. Count
400 Bad Request Missing/malformed request params. Error
500 Internal Server Error Unexpected error Error

Revoke API Token

Code samples

# You can also use wget
curl -X DELETE https://hosted.mender.io/api/management/v2/devauth/tokens/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

DELETE https://hosted.mender.io/api/management/v2/devauth/tokens/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/devauth/tokens/{id}',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.delete 'https://hosted.mender.io/api/management/v2/devauth/tokens/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.delete('https://hosted.mender.io/api/management/v2/devauth/tokens/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://hosted.mender.io/api/management/v2/devauth/tokens/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/devauth/tokens/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://hosted.mender.io/api/management/v2/devauth/tokens/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /tokens/{id}

Revoke JWT with given id

Deletes the token, effectively revoking it. The device must apply for a new one with a new authentication request. The token 'id' corresponds to the standard 'jti' claim.

Parameters

Name In Type Required Description
id path string true Unique token identifier('jti').

Example responses

404 Response

{
  "error": "string"
}

Responses

Status Meaning Description Schema
204 No Content The token was successfully deleted. None
404 Not Found The token was not found. Error
500 Internal Server Error Internal server error. Error

Get Device Limit

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v2/devauth/limits/max_devices \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v2/devauth/limits/max_devices HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/devauth/limits/max_devices',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v2/devauth/limits/max_devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v2/devauth/limits/max_devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v2/devauth/limits/max_devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/devauth/limits/max_devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v2/devauth/limits/max_devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /limits/max_devices

Obtain limit of accepted devices.

Example responses

200 Response

{
  "limit": 123
}

Responses

Status Meaning Description Schema
200 OK Usage statistics and limits. Limit
500 Internal Server Error Internal server error. Error

Schemas

Status

{
  "status": "accepted"
}

Admission status of the device.

Properties

Name Type Required Description
status string true

Enumerated Values

Property Value
status pending
status accepted
status rejected
status preauthorized

Limit

{
  "limit": 123
}

Limit definition

Properties

Name Type Required Description
limit integer true

Device

{
  "id": "string",
  "identity_data": {
    "mac": "00:01:02:03:04:05",
    "sku": "My Device 1",
    "sn": "SN1234567890"
  },
  "status": "pending",
  "created_ts": "2019-08-24T14:15:22Z",
  "updated_ts": "2019-08-24T14:15:22Z",
  "auth_sets": [
    {
      "id": "string",
      "pubkey": "string",
      "identity_data": {
        "mac": "00:01:02:03:04:05",
        "sku": "My Device 1",
        "sn": "SN1234567890"
      },
      "status": "pending",
      "ts": "2019-08-24T14:15:22Z"
    }
  ],
  "decommissioning": true
}

Properties

Name Type Required Description
id string false Mender assigned Device ID.
identity_data IdentityData false Device identity attributes, in the form of a JSON structure.

The attributes are completely vendor-specific, the provided ones are just an example.
In reference implementation structure contains vendor-selected fields,
such as MACs, serial numbers, etc.
status string false
created_ts string(date-time) false Created timestamp
updated_ts string(date-time) false Updated timestamp
auth_sets [AuthSet] false [Authentication data set]
decommissioning boolean false Devices that are part of ongoing decomissioning process will return True

Enumerated Values

Property Value
status pending
status accepted
status rejected
status preauthorized
status noauth

AuthSet

{
  "id": "string",
  "pubkey": "string",
  "identity_data": {
    "mac": "00:01:02:03:04:05",
    "sku": "My Device 1",
    "sn": "SN1234567890"
  },
  "status": "pending",
  "ts": "2019-08-24T14:15:22Z"
}

Authentication data set

Properties

Name Type Required Description
id string false Authentication data set ID.
pubkey string false The device's public key (PEM encoding), generated by the device or pre-provisioned by the vendor. Currently supported public algorithms are: RSA, ED25519 and ECDSA.
identity_data IdentityData false Device identity attributes, in the form of a JSON structure.

The attributes are completely vendor-specific, the provided ones are just an example.
In reference implementation structure contains vendor-selected fields,
such as MACs, serial numbers, etc.
status string false
ts string(date-time) false Created timestamp

Enumerated Values

Property Value
status pending
status accepted
status rejected
status preauthorized
status noauth

Count

{
  "count": 42
}

Counter type

Properties

Name Type Required Description
count integer false The count of requested items.

Error

{
  "error": "string"
}

Error descriptor

Properties

Name Type Required Description
error string false Description of the error

PreAuthSet

{
  "identity_data": {
    "mac": "00:01:02:03:04:05",
    "sku": "My Device 1",
    "sn": "SN1234567890"
  },
  "pubkey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzogVU7RGDilbsoUt/DdH\nVJvcepl0A5+xzGQ50cq1VE/Dyyy8Zp0jzRXCnnu9nu395mAFSZGotZVr+sWEpO3c\nyC3VmXdBZmXmQdZqbdD/GuixJOYfqta2ytbIUPRXFN7/I7sgzxnXWBYXYmObYvdP\nokP0mQanY+WKxp7Q16pt1RoqoAd0kmV39g13rFl35muSHbSBoAW3GBF3gO+mF5Ty\n1ddp/XcgLOsmvNNjY+2HOD5F/RX0fs07mWnbD7x+xz7KEKjF+H7ZpkqCwmwCXaf0\niyYyh1852rti3Afw4mDxuVSD7sd9ggvYMc0QHIpQNkD4YWOhNiE1AB0zH57VbUYG\nUwIDAQAB\n-----END PUBLIC KEY-----\n"
}

Properties

Name Type Required Description
identity_data IdentityData true Device identity attributes, in the form of a JSON structure.

The attributes are completely vendor-specific, the provided ones are just an example.
In reference implementation structure contains vendor-selected fields,
such as MACs, serial numbers, etc.
pubkey string true The device's public key (PEM encoding), generated by the device or pre-provisioned by the vendor. Currently supported public algorithms are: RSA, ED25519 and ECDSA.

IdentityData

{
  "mac": "00:01:02:03:04:05",
  "sku": "My Device 1",
  "sn": "SN1234567890"
}

Device identity attributes, in the form of a JSON structure.

The attributes are completely vendor-specific, the provided ones are just an example. In reference implementation structure contains vendor-selected fields, such as MACs, serial numbers, etc.

Properties

Name Type Required Description
mac string false MAC address.
sku string false Stock keeping unit.
sn string false Serial number.

Device inventory

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for device attribute management and device grouping. Intended for use by the web GUI.

Devices can upload vendor-specific attributes (software/hardware info, health checks, metrics, etc.) of various data types to the backend.

This API enables the user to:

Base URLs:

List Device Inventories

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/inventory/devices \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/inventory/devices HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/inventory/devices',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/inventory/devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/inventory/devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/inventory/devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/inventory/devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/inventory/devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /devices

List devices inventories

Returns a paged collection of devices and their attributes. Accepts optional search and sort parameters.

Searching Searching by attributes values is accomplished by appending attribute name/value pairs to the query string, e.g.: GET /devices?attr_name_1=foo&attr_name_2=100

Parameters

Name In Type Required Description
page query number(integer) false Starting page.
per_page query number(integer) false Maximum number of results per page.
sort query string(attr[:ord][,attr[:ord]...]) false Sort devices by attribute.
has_group query boolean false Limit result to devices assigned to a group.
group query string false Limits result to devices in the given group.

Detailed descriptions

sort: Sort devices by attribute. The parameter is formatted as a comma-separated list of attribute names and sort order.

The order direction (ord) must be either asc or desc for ascending and descending respectively. Defaults to desc if not specified.

For example: ?sort=attr1:asc,attr2:desc will sort by 'attr1' ascending, and then by 'attr2' descending.

Example responses

Successful response.

[
  {
    "id": "291ae0e5956c69c2267489213df4459d19ed48a806603def19d417d004a4b67e",
    "attributes": [
      {
        "name": "ip_addr",
        "scope": "inventory",
        "value": "1.2.3.4",
        "description": "IP address"
      },
      {
        "name": "mac_addr",
        "scope": "inventory",
        "value": "00.01:02:03:04:05",
        "description": "MAC address"
      }
    ],
    "updated_ts": "2016-10-03T16:58:51.639Z"
  },
  {
    "id": "76f40e5956c699e327489213df4459d1923e1a806603def19d417d004a4a3ef",
    "attributes": [
      {
        "name": "mac",
        "scope": "inventory",
        "value": "00:01:02:03:04:05",
        "description": "MAC address"
      }
    ],
    "updated_ts": "2016-10-04T18:24:21.432Z"
  }
]

400 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
400 Bad Request Missing or malformed request parameters. Error
500 Internal Server Error Internal error. Error

Response Schema

Status Code 200

ListOfDevices

Name Type Required Restrictions Description
ListOfDevices [DeviceInventory] false
» id string false Mender-assigned unique device ID.
» updated_ts string false Timestamp of the most recent attribute update.
» attributes [Attribute] false A list of attribute descriptors.
»» name string true A human readable, unique attribute ID, e.g. 'device_type', 'ip_addr', 'cpu_load', etc.
»» description string false Attribute description.
»» value string true The current value of the attribute.

Attribute type is implicit, inferred from the JSON type.

Supported types: number, string, array of numbers, array of strings.
Mixed type arrays are not allowed.

Response Headers

Status Header Type Format Description
200 Link string Standard page navigation header, supported relations: 'first', 'next', and 'prev'.
200 X-Total-Count string Total number of devices found

Get Device Inventory

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/inventory/devices/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/inventory/devices/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/inventory/devices/{id}',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/inventory/devices/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/inventory/devices/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/inventory/devices/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/inventory/devices/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/inventory/devices/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /devices/{id}

Get a selected device's inventory

Parameters

Name In Type Required Description
id path string true Device identifier.

Example responses

Successful response - the device was found.

{
  "id": "291ae0e5956c69c2267489213df4459d19ed48a806603def19d417d004a4b67e",
  "attributes": [
    {
      "name": "ip_addr",
      "scope": "inventory",
      "value": "1.2.3.4",
      "description": "IP address"
    },
    {
      "name": "mac_addr",
      "scope": "inventory",
      "value": "00.01:02:03:04:05",
      "description": "MAC address"
    }
  ],
  "updated_ts": "2016-10-03T16:58:51.639Z"
}

404 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response - the device was found. DeviceInventory
404 Not Found The device was not found. Error
500 Internal Server Error Internal server error. Error

Delete Device Inventory

Code samples

# You can also use wget
curl -X DELETE https://hosted.mender.io/api/management/v1/inventory/devices/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

DELETE https://hosted.mender.io/api/management/v1/inventory/devices/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/inventory/devices/{id}',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.delete 'https://hosted.mender.io/api/management/v1/inventory/devices/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.delete('https://hosted.mender.io/api/management/v1/inventory/devices/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://hosted.mender.io/api/management/v1/inventory/devices/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/inventory/devices/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://hosted.mender.io/api/management/v1/inventory/devices/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /devices/{id}

Remove selected device's inventory

Parameters

Name In Type Required Description
id path string true Device identifier.

Example responses

500 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Device removed None
500 Internal Server Error Internal server error. Error

Get Device Group

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /devices/{id}/group

Get a selected device's group

Parameters

Name In Type Required Description
id path string true Device identifier.

Example responses

200 Response

{
  "group": "staging"
}

Responses

Status Meaning Description Schema
200 OK Successful response. If the device is not assigned to any group, the 'group' field will be set to 'null'. Group
400 Bad Request Missing or malformed request params or body. See the error message for details. None
404 Not Found The device was not found. Error
500 Internal Server Error Internal server error. Error

Assign Group

Code samples

# You can also use wget
curl -X PUT https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

PUT https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "group": "staging"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.put 'https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.put('https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /devices/{id}/group

Add a device to a group

Adds a device to a group.

Note that a given device can belong to at most one group. If a device already belongs to some group, it will be moved to the selected one.

Body parameter

{
  "group": "staging"
}

Parameters

Name In Type Required Description
id path string true Device identifier.
body body Group true Group descriptor.

Example responses

404 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Success - the device was added to the group. None
400 Bad Request Missing or malformed request params or body. See the error message for details. None
404 Not Found The device was not found. Error
500 Internal Server Error Internal server error. Error

Clear Group

Code samples

# You can also use wget
curl -X DELETE https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group/{name} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

DELETE https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group/{name} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group/{name}',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.delete 'https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group/{name}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.delete('https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group/{name}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group/{name}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group/{name}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://hosted.mender.io/api/management/v1/inventory/devices/{id}/group/{name}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /devices/{id}/group/{name}

Remove a device from a group

Removes the device with identifier 'id' from the group 'group'.

Parameters

Name In Type Required Description
id path string true Device identifier.
name path string true Group name.

Example responses

404 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content The device was successfully removed from the group. None
404 Not Found The device was not found or doesn't belong to the group. Error
500 Internal Server Error Internal error. Error

List Groups

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/inventory/groups \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/inventory/groups HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/inventory/groups',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/inventory/groups',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/inventory/groups', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/inventory/groups', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/inventory/groups");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/inventory/groups", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /groups

List all groups existing device groups

Parameters

Name In Type Required Description
status query string false Show groups for devices with the given auth set status.

Example responses

Successful response.

[
  "staging",
  "testing",
  "production"
]

500 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
500 Internal Server Error Internal server error. Error

Response Schema

Status Code 200

Name Type Required Restrictions Description
» ListOfGroupNames string false Group name

Get Devices in Group

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /groups/{name}/devices

List the devices belonging to a given group

Parameters

Name In Type Required Description
page query integer false Starting page.
per_page query integer false Maximum number of results per page.
name path string true Group name.

Example responses

200 Response

[
  "string"
]

Responses

Status Meaning Description Schema
200 OK Successful response Inline
400 Bad Request Invalid request parameters. Error
404 Not Found The group was not found. Error
500 Internal Server Error Internal server error. Error

Response Schema

Status Code 200

ListOfIDs

Name Type Required Restrictions Description
ListOfIDs [string] false

Response Headers

Status Header Type Format Description
200 Link string Standard header, we support 'first', 'next', and 'prev'.
200 X-Total-Count string Custom header indicating the total number of devices in the given group

Add Devices to Group

Code samples

# You can also use wget
curl -X PATCH https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

PATCH https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '[
  "string"
]';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices',
{
  method: 'PATCH',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.patch 'https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.patch('https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PATCH','https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PATCH");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PATCH", "https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PATCH /groups/{name}/devices

Add devices to group

Appends the list of devices in the request body to the given group. For devices already present in the group the operation has no effect.

Body parameter

[
  "string"
]

Parameters

Name In Type Required Description
name path string true Group name.
body body array[string] true JSON list of device IDs to append to the group.

Example responses

Successful response

{
  "updated_count": 2,
  "matched_count": 3
}

400 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response Inline
400 Bad Request Invalid request schema. Error
404 Not Found The group was not found. Error
500 Internal Server Error Internal server error. Error

Response Schema

Status Code 200

*JSON object listing how many devices were updated. *

Name Type Required Restrictions Description
» updated_count number true Number of devices listed that changed group.
» matched_count number true Number of devices listed that matched a valid device id internally.

Remove Devices from Group

Code samples

# You can also use wget
curl -X DELETE https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

DELETE https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '[
  "string"
]';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices',
{
  method: 'DELETE',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.delete 'https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.delete('https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://hosted.mender.io/api/management/v1/inventory/groups/{name}/devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /groups/{name}/devices

Clear devices' group

Removes a list of devices from their respective groups. This API provides a bulk alternative to DELETE /devices/{id}/group/{name} for managing device groups.

Body parameter

[
  "string"
]

Parameters

Name In Type Required Description
name path string true Group name.
body body array[string] true JSON list of device IDs to append to the group.

Example responses

Successful response

{
  "updated_count": 2
}

400 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response Inline
400 Bad Request Invalid request schema. Error
404 Not Found The group was not found. Error
500 Internal Server Error Internal server error. Error

Response Schema

Status Code 200

*JSON object listing how many devices were updated. *

Name Type Required Restrictions Description
» updated_count number true Number of devices for which the group was cleared sucessfully.

Schemas

Attribute

{
  "name": "ip_addr_eth",
  "description": "Device IP address on ethernet interface",
  "value": "127.0.0.1"
}

Attribute descriptor.

Properties

Name Type Required Description
name string true A human readable, unique attribute ID, e.g. 'device_type', 'ip_addr', 'cpu_load', etc.
description string false Attribute description.
value string true The current value of the attribute.

Attribute type is implicit, inferred from the JSON type.

Supported types: number, string, array of numbers, array of strings.
Mixed type arrays are not allowed.

DeviceInventory

{
  "id": "291ae0e5956c69c2267489213df4459d19ed48a806603def19d417d004a4b67e",
  "attributes": [
    {
      "name": "ip_addr",
      "value": "1.2.3.4",
      "description": "IP address"
    },
    {
      "name": "mac_addr",
      "value": "00.01:02:03:04:05",
      "description": "MAC address"
    }
  ],
  "updated_ts": "2016-10-03T16:58:51.639Z"
}

Properties

Name Type Required Description
id string false Mender-assigned unique device ID.
updated_ts string false Timestamp of the most recent attribute update.
attributes [Attribute] false A list of attribute descriptors.

Group

{
  "group": "staging"
}

Properties

Name Type Required Description
group string true Device group.

Error

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID (same as in X-MEN-RequestID header).

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for inventory-based filters management and device search. It is intended for use by the web GUI.

Devices can upload vendor-specific attributes (software/hardware info, health checks, metrics, etc.) of various data types to the backend as scoped attributes.

This API enables the user to:

Base URLs:

Search Device Inventories

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v2/inventory/filters/search \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v2/inventory/filters/search HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "page": 1,
  "per_page": 20,
  "filters": [
    {
      "type": "$eq",
      "attribute": "serial_no",
      "scope": "inventory",
      "value": "123456789"
    }
  ],
  "sort": [
    {
      "attribute": "serial_no",
      "scope": "inventory",
      "order": "asc"
    }
  ]
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/inventory/filters/search',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v2/inventory/filters/search',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v2/inventory/filters/search', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v2/inventory/filters/search', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/inventory/filters/search");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v2/inventory/filters/search", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /filters/search

Search devices based on inventory attributes

Returns a paged collection of devices and their attributes.

If multiple filter predicates are specified, the filters are combined using boolean and operator.

This operation is only available in our commercial offering and requires you to be on the following plans:

Body parameter

{
  "page": 1,
  "per_page": 20,
  "filters": [
    {
      "type": "$eq",
      "attribute": "serial_no",
      "scope": "inventory",
      "value": "123456789"
    }
  ],
  "sort": [
    {
      "attribute": "serial_no",
      "scope": "inventory",
      "order": "asc"
    }
  ]
}

Parameters

Name In Type Required Description
body body object false The search and sort parameters of the filter
» page body number(integer) false Starting page.
» per_page body number(integer) false Maximum number of results per page.
» filters body [FilterPredicate] false List of filter predicates.
»» scope body string true Attribute scope.
»» attribute body string true Attribute name.
»» type body string true Type or operator of the filter predicate.
»» value body string true The value of the attribute to be used in filtering.
» sort body [SortCriteria] false List of ordered sort criteria
»» scope body string true Attribute scope.
»» attribute body string true Attribute name.
»» order body string true Order direction, ascending ("asc") or descending ("desc").

Detailed descriptions

»» type: Type or operator of the filter predicate.

Operator Name Argument type
$eq Equal (==) any
$ne Not equal (!=) any
$gt Greater than (>) any
$gte Greater than or equal (>=) any
$lt Less than (<) any
$lte Less than or equal (<=) any
$exists Attribute exists bool
$in Is an element of array
$nin Is not an element of array
$regex Regex filter string

»» value: The value of the attribute to be used in filtering. Attribute type is implicit, inferred from the JSON type.

The $exists operator expects a boolean value: true means the specified attribute exists, false means the specified attribute doesn't exist.

The $regex operator expects a string as a Perl compatible regular expression (PCRE), automatically anchored by ^. If the regular expression is not valid, the filter will produce no results. If you need to specify options and flags, you can provide the full regex in the format of /regex/flags, for example /[a-z]+/i.

Enumerated Values

Parameter Value
»» type $eq
»» type $gt
»» type $gte
»» type $in
»» type $lt
»» type $lte
»» type $ne
»» type $nin
»» type $exists
»» type $regex
»» order asc
»» order desc

Example responses

Successful response.

[
  {
    "id": "291ae0e5956c69c2267489213df4459d19ed48a806603def19d417d004a4b67e",
    "attributes": [
      {
        "name": "ip_addr",
        "scope": "inventory",
        "value": "1.2.3.4",
        "description": "IP address"
      },
      {
        "name": "mac_addr",
        "scope": "inventory",
        "value": "00.01:02:03:04:05",
        "description": "MAC address"
      }
    ],
    "updated_ts": "2016-10-03T16:58:51.639Z"
  },
  {
    "id": "76f40e5956c699e327489213df4459d1923e1a806603def19d417d004a4a3ef",
    "attributes": [
      {
        "name": "mac",
        "scope": "identity",
        "value": "00:01:02:03:04:05",
        "description": "MAC address"
      }
    ],
    "updated_ts": "2016-10-04T18:24:21.432Z"
  }
]

400 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
400 Bad Request Missing or malformed request parameters. See error for details. Error
500 Internal Server Error Internal error. Error

Response Schema

Status Code 200

ListOfDevices

Name Type Required Restrictions Description
ListOfDevices [DeviceInventory] false
» id string false Mender-assigned unique ID.
» updated_ts string false Timestamp of the most recent attribute update.
» attributes [Attribute] false A list of attribute descriptors.
»» name string true A human readable, unique attribute ID, e.g. 'device_type', 'ip_addr', 'cpu_load', etc.
»» scope string true The scope of the attribute.

Scope is a string and acts as namespace for the attribute name.
»» description string false Attribute description.
»» value string true The current value of the attribute.

Attribute type is implicit, inferred from the JSON type.

Supported types: number, string, array of numbers, array of strings.
Mixed arrays are not allowed.

Response Headers

Status Header Type Format Description
200 X-Total-Count string Custom header indicating the total number of devices for the given query parameters

List Filters

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v2/inventory/filters \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v2/inventory/filters HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/inventory/filters',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v2/inventory/filters',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v2/inventory/filters', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v2/inventory/filters', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/inventory/filters");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v2/inventory/filters", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /filters

List all the saved filters

This operation is only available in our commercial offering and requires you to be on the following plans:

Parameters

Name In Type Required Description
page query number(integer) false Starting page.
per_page query number(integer) false Number of results per page.

Example responses

200 Response

[
  {
    "id": "myfilter",
    "name": "My Filter",
    "terms": [
      {
        "scope": "inventory",
        "attribute": "serial_no",
        "type": "$eq",
        "value": "123456789"
      }
    ]
  }
]

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
400 Bad Request Missing or malformed request parameters. See error for details. Error
500 Internal Server Error Internal error. Error

Response Schema

Status Code 200

ListOfFilters

Name Type Required Restrictions Description
ListOfFilters [Filter] false [Filter definition]
» id string true Unique identifier of the saved filter.
» name string true Name of the saved filter.
» terms [FilterPredicate] false [Attribute filter predicate]
»» scope string true Attribute scope.
»» attribute string true Attribute name.
»» type string true Type or operator of the filter predicate.

»» value string true The value of the attribute to be used in filtering.
Attribute type is implicit, inferred from the JSON type.

The $exists operator expects a boolean value: true means the specified
attribute exists, false means the specified attribute doesn't exist.

The $regex operator expects a string as a Perl compatible regular expression
(PCRE), automatically anchored by ^. If the regular expression is not valid,
the filter will produce no results. If you need to specify options and flags,
you can provide the full regex in the format of /regex/flags, for example
/[a-z]+/i.

Enumerated Values

Property Value
type $eq
type $gt
type $gte
type $in
type $lt
type $lte
type $ne
type $nin
type $exists
type $regex

Response Headers

Status Header Type Format Description
200 Link string Standard header, used for page navigation.

Supported relation types are 'first', 'next' and 'prev'. | |200|X-Total-Count|string||Custom header indicating the total number of saved filters for the given query parameters|

Create Filter

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v2/inventory/filters \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v2/inventory/filters HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "name": "string",
  "terms": [
    {
      "type": "$eq",
      "attribute": "serial_no",
      "scope": "inventory",
      "value": "123456789"
    }
  ]
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/inventory/filters',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v2/inventory/filters',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v2/inventory/filters', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v2/inventory/filters', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/inventory/filters");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v2/inventory/filters", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /filters

Create a new saved filter from a filter definition

This operation is only available in our commercial offering and requires you to be on the following plans:

Body parameter

{
  "name": "string",
  "terms": [
    {
      "type": "$eq",
      "attribute": "serial_no",
      "scope": "inventory",
      "value": "123456789"
    }
  ]
}

Parameters

Name In Type Required Description
body body object false The definition of the filter
» name body string false Name of the filter, must be unique.
» terms body [FilterPredicate] false List of filter predicates, chained with boolean AND operators to build the search condition definition.
»» scope body string true Attribute scope.
»» attribute body string true Attribute name.
»» type body string true Type or operator of the filter predicate.
»» value body string true The value of the attribute to be used in filtering.

Detailed descriptions

»» type: Type or operator of the filter predicate.

Operator Name Argument type
$eq Equal (==) any
$ne Not equal (!=) any
$gt Greater than (>) any
$gte Greater than or equal (>=) any
$lt Less than (<) any
$lte Less than or equal (<=) any
$exists Attribute exists bool
$in Is an element of array
$nin Is not an element of array
$regex Regex filter string

»» value: The value of the attribute to be used in filtering. Attribute type is implicit, inferred from the JSON type.

The $exists operator expects a boolean value: true means the specified attribute exists, false means the specified attribute doesn't exist.

The $regex operator expects a string as a Perl compatible regular expression (PCRE), automatically anchored by ^. If the regular expression is not valid, the filter will produce no results. If you need to specify options and flags, you can provide the full regex in the format of /regex/flags, for example /[a-z]+/i.

Enumerated Values

Parameter Value
»» type $eq
»» type $gt
»» type $gte
»» type $in
»» type $lt
»» type $lte
»» type $ne
»» type $nin
»» type $exists
»» type $regex

Example responses

400 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
201 Created The filter was successfully created. None
400 Bad Request Missing or malformed request parameters. See error for details. Error
409 Conflict A filter with the same name already exists. Error
500 Internal Server Error Internal error. Error

Response Headers

Status Header Type Format Description
201 Location string URL of the newly created filter.

Show Filter

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v2/inventory/filters/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v2/inventory/filters/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/inventory/filters/{id}',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v2/inventory/filters/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v2/inventory/filters/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v2/inventory/filters/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/inventory/filters/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v2/inventory/filters/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /filters/{id}

Get the definition of a saved filter

This operation is only available in our commercial offering and requires you to be on the following plans:

Parameters

Name In Type Required Description
id path string true Filter identifier.

Example responses

200 Response

{
  "id": "myfilter",
  "name": "My Filter",
  "terms": [
    {
      "scope": "inventory",
      "attribute": "serial_no",
      "type": "$eq",
      "value": "123456789"
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK Successful response. Filter
404 Not Found The filter was not found. ErrorNotFound
500 Internal Server Error Internal error. Error

Delete Filter

Code samples

# You can also use wget
curl -X DELETE https://hosted.mender.io/api/management/v2/inventory/filters/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

DELETE https://hosted.mender.io/api/management/v2/inventory/filters/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/inventory/filters/{id}',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.delete 'https://hosted.mender.io/api/management/v2/inventory/filters/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.delete('https://hosted.mender.io/api/management/v2/inventory/filters/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://hosted.mender.io/api/management/v2/inventory/filters/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/inventory/filters/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://hosted.mender.io/api/management/v2/inventory/filters/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /filters/{id}

Delete a saved filter

This operation is only available in our commercial offering and requires you to be on the following plans:

Parameters

Name In Type Required Description
id path string true Filter identifier.

Example responses

400 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content The filter was successfully deleted. None
400 Bad Request Missing or malformed request parameters. See error for details. Error
500 Internal Server Error Internal error. Error

Execute Filter

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v2/inventory/filters/{id}/search \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v2/inventory/filters/{id}/search HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/inventory/filters/{id}/search',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v2/inventory/filters/{id}/search',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v2/inventory/filters/{id}/search', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v2/inventory/filters/{id}/search', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/inventory/filters/{id}/search");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v2/inventory/filters/{id}/search", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /filters/{id}/search

Search devices using saved filter

This operation is only available in our commercial offering and requires you to be on the following plans:

Parameters

Name In Type Required Description
id path string true Filter identifier.
page query number(integer) false Starting page.
per_page query number(integer) false Number of results per page.

Example responses

Successful response.

[
  {
    "id": "291ae0e5956c69c2267489213df4459d19ed48a806603def19d417d004a4b67e",
    "attributes": [
      {
        "name": "ip_addr",
        "scope": "inventory",
        "value": "1.2.3.4",
        "description": "IP address"
      },
      {
        "name": "mac_addr",
        "scope": "inventory",
        "value": "00.01:02:03:04:05",
        "description": "MAC address"
      }
    ],
    "updated_ts": "2016-10-03T16:58:51.639Z"
  },
  {
    "id": "76f40e5956c699e327489213df4459d1923e1a806603def19d417d004a4a3ef",
    "attributes": [
      {
        "name": "mac",
        "scope": "inventory",
        "value": "00:01:02:03:04:05",
        "description": "MAC address"
      }
    ],
    "updated_ts": "2016-10-04T18:24:21.432Z"
  }
]

400 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
400 Bad Request Missing or malformed request parameters. Error
404 Not Found The filter was not found. ErrorNotFound
500 Internal Server Error Internal error. Error

Response Schema

Status Code 200

ListOfDevices

Name Type Required Restrictions Description
ListOfDevices [DeviceInventory] false
» id string false Mender-assigned unique ID.
» updated_ts string false Timestamp of the most recent attribute update.
» attributes [Attribute] false A list of attribute descriptors.
»» name string true A human readable, unique attribute ID, e.g. 'device_type', 'ip_addr', 'cpu_load', etc.
»» scope string true The scope of the attribute.

Scope is a string and acts as namespace for the attribute name.
»» description string false Attribute description.
»» value string true The current value of the attribute.

Attribute type is implicit, inferred from the JSON type.

Supported types: number, string, array of numbers, array of strings.
Mixed arrays are not allowed.

Response Headers

Status Header Type Format Description
200 Link string Standard header used for page navigation, page relations: 'first', 'next' and 'prev'.
200 X-Total-Count string Total number of devices matched query.

Schemas

Attribute

{
  "name": "serial_no",
  "scope": "inventory",
  "description": "Serial number",
  "value": "123456789"
}

Attribute descriptor.

Properties

Name Type Required Description
name string true A human readable, unique attribute ID, e.g. 'device_type', 'ip_addr', 'cpu_load', etc.
scope string true The scope of the attribute.

Scope is a string and acts as namespace for the attribute name.
description string false Attribute description.
value string true The current value of the attribute.

Attribute type is implicit, inferred from the JSON type.

Supported types: number, string, array of numbers, array of strings.
Mixed arrays are not allowed.

DeviceInventory

{
  "id": "291ae0e5956c69c2267489213df4459d19ed48a806603def19d417d004a4b67e",
  "attributes": [
    {
      "name": "ip_addr",
      "scope": "inventory",
      "value": "1.2.3.4",
      "description": "IP address"
    },
    {
      "name": "mac_addr",
      "scope": "inventory",
      "value": "00.01:02:03:04:05",
      "description": "MAC address"
    }
  ],
  "updated_ts": "2016-10-03T16:58:51.639Z"
}

Properties

Name Type Required Description
id string false Mender-assigned unique ID.
updated_ts string false Timestamp of the most recent attribute update.
attributes [Attribute] false A list of attribute descriptors.

Error

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID (same as in X-MEN-RequestID header).

ErrorNotFound

{
  "error": "filter not found",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID (same as in X-MEN-RequestID header).

Filter

{
  "id": "myfilter",
  "name": "My Filter",
  "terms": [
    {
      "scope": "inventory",
      "attribute": "serial_no",
      "type": "$eq",
      "value": "123456789"
    }
  ]
}

Filter definition

Properties

Name Type Required Description
id string true Unique identifier of the saved filter.
name string true Name of the saved filter.
terms [FilterPredicate] false [Attribute filter predicate]

FilterPredicate

{
  "type": "$eq",
  "attribute": "serial_no",
  "scope": "inventory",
  "value": "123456789"
}

Attribute filter predicate

Properties

Name Type Required Description
scope string true Attribute scope.
attribute string true Attribute name.
type string true Type or operator of the filter predicate.

value string true The value of the attribute to be used in filtering.
Attribute type is implicit, inferred from the JSON type.

The $exists operator expects a boolean value: true means the specified
attribute exists, false means the specified attribute doesn't exist.

The $regex operator expects a string as a Perl compatible regular expression
(PCRE), automatically anchored by ^. If the regular expression is not valid,
the filter will produce no results. If you need to specify options and flags,
you can provide the full regex in the format of /regex/flags, for example
/[a-z]+/i.

Enumerated Values

Property Value
type $eq
type $gt
type $gte
type $in
type $lt
type $lte
type $ne
type $nin
type $exists
type $regex

SortCriteria

{
  "attribute": "serial_no",
  "scope": "inventory",
  "order": "asc"
}

Sort criteria definition

Properties

Name Type Required Description
scope string true Attribute scope.
attribute string true Attribute name.
order string true Order direction, ascending ("asc") or descending ("desc").

Enumerated Values

Property Value
order asc
order desc

Deployments

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for deployments and artifacts management. Intended for use by the web GUI.

Base URLs:

List Deployments

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/deployments/deployments \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/deployments/deployments HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/deployments',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/deployments/deployments',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/deployments/deployments', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deployments/deployments', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/deployments");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/deployments/deployments", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /deployments

Find all deployments

Returns a filtered collection of deployments in the system, including active and historical. If both 'status' and 'query' are not specified, all devices are listed.

Parameters

Name In Type Required Description
status query string false Deployment status filter.
search query string false Deployment name or description filter.
page query number(integer) false Results page number
per_page query number(integer) false Maximum number of results per page.
created_before query number(integer) false List only deployments created before and equal to Unix timestamp (UTC)
created_after query number(integer) false List only deployments created after and equal to Unix timestamp (UTC)

Enumerated Values

Parameter Value
status inprogress
status finished
status pending
status scheduled

Example responses

Successful response.

[
  {
    "created": "2016-02-11T13:03:17.063493443Z",
    "status": "finished",
    "name": "production",
    "artifact_name": "Application 0.0.1",
    "id": "00a0c91e6-7dec-11d0-a765-f81d4faebf6",
    "finished": "2016-03-11T13:03:17.063493443Z",
    "device_count": 10,
    "retries": 0
  }
]

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
400 Bad Request Invalid Request. Error
500 Internal Server Error Internal Server Error. Error

Response Schema

Status Code 200

Name Type Required Restrictions Description
anonymous [Deployment] false
» created string(date-time) true
» name string true
» artifact_name string true
» id string true
» finished string(date-time) false
» status string true
» device_count integer true
» artifacts [string] false
» phases [DeploymentPhase] false
»» id string false Phase identifier.
»» batch_size integer false Percentage of devices to update in the phase.
»» start_ts string(date-time) false Start date of a phase.
May be undefined for the first phase of a deployment.
»» device_count integer false Number of devices which already requested an update within this phase.
» retries integer false The number of times a device can retry the deployment in case of failure, defaults to 0
» max_devices integer false max_devices denotes a limit on a number of completed deployments (failed or successful) above which the dynamic deployment will be finished.
» initial_device_count integer false In case of dynamic deployments this is a number of devices targeted initially (maching the filter at the moment of deployment creation).
» dynamic boolean false Flag indicating if the deployment is dynamic or not.
» filter Filter false Inventory filter assigned to the deployment
»» id string true Unique identifier of the saved filter.
»» name string true Name of the saved filter.
»» terms [FilterPredicate] false [Attribute filter predicate]
»»» scope string true The scope of the attribute.

Scope is a string and acts as namespace for the attribute name.
»»» attribute string true Name of the attribute to be queried for filtering.
»»» type string true Type or operator of the filter predicate.
»»» value string true The value of the attribute to be used in filtering.

Attribute type is implicit, inferred from the JSON type.

Supported types: number, string, array of numbers, array of strings.
Mixed arrays are not allowed.

Enumerated Values

Property Value
status scheduled
status pending
status inprogress
status finished
type $eq
type $gt
type $gte
type $in
type $lt
type $lte
type $ne
type $nin
type $exists

Response Headers

Status Header Type Format Description
200 Link string Standard header, we support 'first', 'next', and 'prev'.

Create Deployment

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v1/deployments/deployments \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v1/deployments/deployments HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "name": "production",
  "artifact_name": "Application 0.0.1",
  "devices": [
    "00a0c91e6-7dec-11d0-a765-f81d4faebf6"
  ],
  "phases": [
    {
      "batch_size": 5,
      "start_ts": "2020-07-06T15:04:49.114046203+02:00"
    },
    {
      "batch_size": 15,
      "start_ts": "2020-07-06T16:04:49.114046203+02:00"
    },
    {
      "start_ts": "2020-07-06T17:04:49.114046203+02:00"
    }
  ],
  "retries": 3
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/deployments',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v1/deployments/deployments',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v1/deployments/deployments', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v1/deployments/deployments', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/deployments");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v1/deployments/deployments", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /deployments

Create a deployment

Deploy software to specified devices. Artifact is auto assigned to the device from all available artifacts based on artifact name and device type. Devices for which there are no compatible artifacts to be installed are considered finished successfully as well as receive status of noartifact. If there is no artifacts for the deployment, deployment will not be created and the 422 Unprocessable Entity status code will be returned.

Body parameter

{
  "name": "production",
  "artifact_name": "Application 0.0.1",
  "devices": [
    "00a0c91e6-7dec-11d0-a765-f81d4faebf6"
  ],
  "phases": [
    {
      "batch_size": 5,
      "start_ts": "2020-07-06T15:04:49.114046203+02:00"
    },
    {
      "batch_size": 15,
      "start_ts": "2020-07-06T16:04:49.114046203+02:00"
    },
    {
      "start_ts": "2020-07-06T17:04:49.114046203+02:00"
    }
  ],
  "retries": 3
}

Parameters

Name In Type Required Description
body body NewDeployment true New deployment that needs to be created.

Example responses

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
201 Created New deployment created. None
400 Bad Request Invalid Request. Error
403 Forbidden Feature not available in your Plan. Error
422 Unprocessable Entity Unprocessable Entity. Error
500 Internal Server Error Internal Server Error. Error

Response Headers

Status Header Type Format Description
201 Location string URL of the newly created deployment.

Show Deployment

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/deployments/deployments/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/deployments/deployments/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/deployments/{id}',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/deployments/deployments/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/deployments/deployments/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deployments/deployments/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/deployments/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/deployments/deployments/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /deployments/{id}

Get the details of a selected deployment

Returns the details of a particular deployment.

Parameters

Name In Type Required Description
id path string true Deployment identifier.

Example responses

200 Response

{
  "created": "2016-02-11T13:03:17.063493443Z",
  "status": "finished",
  "name": "production",
  "artifact_name": "Application 0.0.1",
  "id": "00a0c91e6-7dec-11d0-a765-f81d4faebf6",
  "finished": "2016-03-11T13:03:17.063493443Z",
  "phases": [
    {
      "batch_size": 5
    },
    {
      "start_ts": "2020-07-06T17:04:49.114046203+02:00",
      "device_count": 25
    },
    {
      "batch_size": 15
    },
    {
      "start_ts": "2020-07-06T18:04:49.114046203+02:00",
      "device_count": 10
    },
    {
      "start_ts": "2020-07-06T19:04:49.114046203+02:00",
      "device_count": 0
    }
  ],
  "device_count": 500,
  "retries": 3
}

Responses

Status Meaning Description Schema
200 OK Successful response. Deployment
404 Not Found Not Found. Error
500 Internal Server Error Internal Server Error. Error

Abort Deployment

Code samples

# You can also use wget
curl -X PUT https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/status \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

PUT https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/status HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "status": "aborted"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/status',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.put 'https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/status',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.put('https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/status', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/status', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/status");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/status", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /deployments/{deployment_id}/status

Abort the deployment

Abort an ongoing deployment. For devices included in this deployment it means that:

Body parameter

{
  "status": "aborted"
}

Parameters

Name In Type Required Description
deployment_id path string true Deployment identifier.
body body object true Deployment status.
» status body string true

Enumerated Values

Parameter Value
» status aborted

Example responses

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Status updated successfully. None
400 Bad Request Invalid Request. Error
404 Not Found Not Found. Error
422 Unprocessable Entity Unprocessable Entity. Error
500 Internal Server Error Internal Server Error. Error

Deployment Status Statistics

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/statistics \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/statistics HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/statistics',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/statistics',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/statistics', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/statistics', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/statistics");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/statistics", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /deployments/{deployment_id}/statistics

*Get status count for all devices in a deployment. *

Parameters

Name In Type Required Description
deployment_id path string true Deployment identifier

Example responses

OK

{
  "success": 3,
  "pending": 1,
  "failure": 0,
  "downloading": 1,
  "installing": 2,
  "rebooting": 3,
  "noartifact": 0,
  "already-installed": 0,
  "aborted": 0
}

404 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK OK DeploymentStatistics
404 Not Found Not Found. Error
500 Internal Server Error Internal Server Error. Error

List Devices in Deployment

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /deployments/{deployment_id}/devices

*Get list of all devices and their respective status for the deployment with the given ID. *

Parameters

Name In Type Required Description
deployment_id path string true Deployment identifier.

Example responses

200 Response

[
  {
    "id": "00a0c91e6-7dec-11d0-a765-f81d4faebf6",
    "finished": "2016-03-11T13:03:17.063493443Z",
    "status": "installing",
    "created": "2016-02-11T13:03:17.063493443Z",
    "device_type": "Raspberry Pi 3",
    "log": false,
    "state": "installing",
    "substate": "installing.enter;script:foo-bar"
  }
]

Responses

Status Meaning Description Schema
200 OK OK Inline
404 Not Found Not Found. Error
500 Internal Server Error Internal Server Error. Error

Response Schema

Status Code 200

Name Type Required Restrictions Description
anonymous [Device] false
» id string true Device identifier.
» finished string(date-time) false
» status string true
» created string(date-time) false
» device_type string false
» log boolean true Availability of the device's deployment log.
» state string false State reported by device
» substate string false Additional state information

Enumerated Values

Property Value
status downloading
status installing
status rebooting
status pending
status success
status failure
status noartifact
status already-installed
status aborted
status decommissioned

List Device IDs in Deployment

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/deployments/deployments/{id}/device_list \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/deployments/deployments/{id}/device_list HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/deployments/{id}/device_list',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/deployments/deployments/{id}/device_list',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/deployments/deployments/{id}/device_list', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deployments/deployments/{id}/device_list', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/deployments/{id}/device_list");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/deployments/deployments/{id}/device_list", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /deployments/{id}/device_list

Get the list of device IDs being part of the deployment.

Parameters

Name In Type Required Description
id path string true Deployment identifier.

Example responses

Successful response.

[
  "00a0c91e6-7dec-11d0-a765-f81d4faebf6",
  "00a0c91e6-7dec-11d0-a765-f81d4faebf8",
  "00a0c91e6-7dec-11d0-a765-f81d4faebf7"
]

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
400 Bad Request Invalid Request. Error
404 Not Found Not Found. Error
500 Internal Server Error Internal Server Error. Error

Response Schema

Get Deployment Log for Device

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices/{device_id}/log \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices/{device_id}/log HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices/{device_id}/log',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices/{device_id}/log',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices/{device_id}/log', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices/{device_id}/log', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices/{device_id}/log");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/deployments/deployments/{deployment_id}/devices/{device_id}/log", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /deployments/{deployment_id}/devices/{device_id}/log

Get the log of a selected device's deployment

Parameters

Name In Type Required Description
deployment_id path string true Deployment identifier.
device_id path string true Device identifier.

Example responses

404 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response. None
404 Not Found Not Found. Error
500 Internal Server Error Internal Server Error. Error

Remove Device from Deployments

Code samples

# You can also use wget
curl -X DELETE https://hosted.mender.io/api/management/v1/deployments/deployments/devices/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

DELETE https://hosted.mender.io/api/management/v1/deployments/deployments/devices/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/deployments/devices/{id}',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.delete 'https://hosted.mender.io/api/management/v1/deployments/deployments/devices/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.delete('https://hosted.mender.io/api/management/v1/deployments/deployments/devices/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://hosted.mender.io/api/management/v1/deployments/deployments/devices/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/deployments/devices/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://hosted.mender.io/api/management/v1/deployments/deployments/devices/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /deployments/devices/{id}

Remove device from all deployments

Set 'decommissioned' status to all pending device deployments for a given device

Parameters

Name In Type Required Description
id path string true System wide device identifier

Example responses

500 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Device was removed None
500 Internal Server Error Internal server error. Error

List Releases

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/deployments/deployments/releases \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/deployments/deployments/releases HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/deployments/releases',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/deployments/deployments/releases',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/deployments/deployments/releases', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deployments/deployments/releases', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/deployments/releases");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/deployments/deployments/releases", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /deployments/releases

List releases

Returns a collection of releases, allows filtering by release name.

Parameters

Name In Type Required Description
name query string false Release name filter.

Example responses

Successful response.

[
  {
    "name": "my-app-v1.0.1",
    "artifacts": [
      {
        "id": "0c13a0e6-6b63-475d-8260-ee42a590e8ff",
        "name": "Application 1.0.0",
        "description": "Johns Monday test build",
        "device_types_compatible": [
          "Beagle Bone"
        ],
        "info": {
          "type_info": {
            "type": "rootfs"
          }
        },
        "signed": false,
        "updates": {
          "type_info": "rootfs-image",
          "files": [
            {
              "name": "rootfs-image-1",
              "checksum": "cc436f982bc60a8255fe1926a450db5f195a19ad",
              "size": 123,
              "date": "2016-03-11T13:03:17.063+0000"
            }
          ],
          "meta_data": {}
        },
        "artifact_provides": {
          "artifact_name": "test",
          "rootfs-image.checksum": "32714818ad6f98ee0185a52e23a475d89122e3efd2b2c26c733781c28e798c99",
          "rootfs-image.version": "test"
        },
        "artifact_depends": {
          "device_type": [
            "test"
          ]
        },
        "size": 36891648,
        "modified": "2016-03-11T13:03:17.063493443Z"
      },
      {
        "id": "0c13a0e6-6b63-475d-8260-ee42a590e8ff",
        "name": "Application 1.0.0",
        "description": "Johns Monday test build",
        "device_types_compatible": [
          "Raspberry Pi"
        ],
        "info": {
          "type_info": {
            "type": "rootfs"
          }
        },
        "signed": false,
        "updates": {
          "type_info": "rootfs-image",
          "files": [
            {
              "name": "rootfs-image-1",
              "checksum": "cc436f982bc60a8255fe1926a450db5f195a19ad",
              "size": 123,
              "date": "2016-03-11T13:03:17.063+0000"
            }
          ],
          "meta_data": {}
        },
        "artifact_provides": {
          "artifact_name": "test",
          "rootfs-image.checksum": "32714818ad6f98ee0185a52e23a475d89122e3efd2b2c26c733781c28e798c99",
          "rootfs-image.version": "test"
        },
        "artifact_depends": {
          "device_type": [
            "test"
          ]
        },
        "size": 36891648,
        "modified": "2016-03-11T13:03:17.063493443Z"
      }
    ]
  },
  {
    "name": "my-app-v2.0.0",
    "artifacts": [
      {
        "id": "0c13a0e6-6b63-475d-8260-ee42a590e8ff",
        "name": "Application 2.0.0",
        "description": "Johns Monday test build",
        "device_types_compatible": [
          "Beagle Bone"
        ],
        "info": {
          "type_info": {
            "type": "rootfs"
          }
        },
        "signed": false,
        "updates": {
          "type_info": "rootfs-image",
          "files": [
            {
              "name": "rootfs-image-1",
              "checksum": "cc436f982bc60a8255fe1926a450db5f195a19ad",
              "size": 123,
              "date": "2016-03-11T13:03:17.063+0000"
            }
          ],
          "meta_data": {}
        },
        "artifact_provides": {
          "artifact_name": "test",
          "rootfs-image.checksum": "32714818ad6f98ee0185a52e23a475d89122e3efd2b2c26c733781c28e798c99",
          "rootfs-image.version": "test"
        },
        "artifact_depends": {
          "device_type": [
            "test"
          ]
        },
        "size": 36891648,
        "modified": "2016-03-11T13:03:17.063493443Z"
      }
    ]
  }
]

500 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response. Releases
500 Internal Server Error Internal Server Error. Error

List Artifacts

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/deployments/artifacts \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/deployments/artifacts HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/artifacts',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/deployments/artifacts',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/deployments/artifacts', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deployments/artifacts', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/artifacts");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/deployments/artifacts", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /artifacts

List known artifacts

Returns a collection of all artifacts.

Example responses

200 Response

[
  {
    "id": "0c13a0e6-6b63-475d-8260-ee42a590e8ff",
    "name": "Application 1.0.0",
    "description": "Johns Monday test build",
    "device_types_compatible": [
      "Beagle Bone"
    ],
    "info": {
      "type_info": {
        "type": "rootfs"
      }
    },
    "signed": false,
    "updates": {
      "type_info": "rootfs-image",
      "files": [
        {
          "name": "rootfs-image-1",
          "checksum": "cc436f982bc60a8255fe1926a450db5f195a19ad",
          "size": 123,
          "date": "2016-03-11T13:03:17.063+0000"
        }
      ],
      "meta_data": {}
    },
    "artifact_provides": {
      "artifact_name": "test",
      "rootfs-image.checksum": "32714818ad6f98ee0185a52e23a475d89122e3efd2b2c26c733781c28e798c99",
      "rootfs-image.version": "test"
    },
    "artifact_depends": {
      "device_type": [
        "test"
      ]
    },
    "size": 36891648,
    "modified": "2016-03-11T13:03:17.063493443Z"
  }
]

Responses

Status Meaning Description Schema
200 OK OK Inline
500 Internal Server Error Internal Server Error. Error

Response Schema

Status Code 200

Name Type Required Restrictions Description
anonymous [Artifact] false [Detailed artifact.]
» id string true
» name string true
» description string true
» device_types_compatible [string] true
» info ArtifactInfo false Information about artifact format and version.
»» format string false
»» version integer false
» signed boolean false Idicates if artifact is signed or not.
» updates [Update] false [Single updated to be applied.
]
»» type_info ArtifactTypeInfo false Information about update type.
»»» type string false
»» files [UpdateFile] false [Information about particular update file.
]
»»» name string false
»»» checksum string false
»»» size integer false
»»» date string(date-time) false
»» meta_data object false meta_data is an object of unknown structure as this is dependent of update type (also custom defined by user)
» artifact_provides object false List of Artifact provides.

Map of key/value pairs, where both keys and values are strings.
»» additionalProperties string false
» artifact_depends object false List of Artifact depends.

Map of key/value pairs, where keys are strings and values are lists of strings.
»» additionalProperties [string] false
» size number(integer) false Artifact total size in bytes - the size of the actual file that will be transferred to the device (compressed).
» modified string(date-time) true Represents creation / last edition of any of the artifact properties.

Upload Artifact

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v1/deployments/artifacts \
  -H 'Content-Type: multipart/form-data' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v1/deployments/artifacts HTTP/1.1
Host: hosted.mender.io
Content-Type: multipart/form-data
Accept: application/json

const inputBody = '{
  "size": 0,
  "description": "string",
  "artifact": "string"
}';
const headers = {
  'Content-Type':'multipart/form-data',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/artifacts',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'multipart/form-data',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v1/deployments/artifacts',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'multipart/form-data',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v1/deployments/artifacts', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'multipart/form-data',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v1/deployments/artifacts', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/artifacts");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"multipart/form-data"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v1/deployments/artifacts", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /artifacts

Upload mender artifact

Upload mender artifact. Multipart request with meta and artifact. Supports artifact versions v1, v2, v3.

Body parameter

size: 0
description: string
artifact: string

Parameters

Name In Type Required Description
body body object false
» size body integer(long) false Size of the artifact file in bytes.
» description body string false
» artifact body string(binary) true Artifact. It has to be the last part of request.

Detailed descriptions

» size: Size of the artifact file in bytes. DEPRECATED: Size is determined from uploaded content.

Example responses

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
201 Created Artifact uploaded. None
400 Bad Request Invalid Request. Error
500 Internal Server Error Internal Server Error. Error

Response Headers

Status Header Type Format Description
201 Location string URL of the newly uploaded artifact.

Generate Artifact

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v1/deployments/artifacts/generate \
  -H 'Content-Type: multipart/form-data' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v1/deployments/artifacts/generate HTTP/1.1
Host: hosted.mender.io
Content-Type: multipart/form-data
Accept: application/json

const inputBody = '{
  "name": "string",
  "description": "string",
  "device_types_compatible": [
    "string"
  ],
  "type": "single_file",
  "args": "string",
  "file": "string"
}';
const headers = {
  'Content-Type':'multipart/form-data',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/artifacts/generate',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'multipart/form-data',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v1/deployments/artifacts/generate',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'multipart/form-data',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v1/deployments/artifacts/generate', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'multipart/form-data',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v1/deployments/artifacts/generate', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/artifacts/generate");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"multipart/form-data"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v1/deployments/artifacts/generate", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /artifacts/generate

Upload raw data to generate a new artifact

Generate a new Mender artifact from raw data and meta data. Multipart request with meta and raw file. Supports generating single-file updates only, using the Single File Update Module (https://hub.mender.io/t/single-file).

Body parameter

name: string
description: string
device_types_compatible:
  - string
type: single_file
args: string
file: string

Parameters

Name In Type Required Description
body body object true
» name body string true Name of the artifact to generate.
» description body string false Description of the artifact to generate.
» device_types_compatible body [string] true An array of compatible device types.
» type body string true Update module used to generate the artifact.
» args body string false Type-specific arguments used to generate the artifact.
» file body string(binary) true Raw file to be used to generate the artifact. It has to be the last part of request.

Enumerated Values

Parameter Value
» type single_file

Example responses

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
201 Created Artifact generation request accepted and queued for processing. None
400 Bad Request Invalid Request. Error
500 Internal Server Error Internal Server Error. Error

Response Headers

Status Header Type Format Description
201 Location string URL of the artifact going to be generated.

Show Artifact

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/deployments/artifacts/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/deployments/artifacts/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /artifacts/{id}

Get the details of a selected artifact

Returns the details of a selected artifact.

Parameters

Name In Type Required Description
id path string true Artifact identifier.

Example responses

Successful response.

{
  "id": "0c13a0e6-6b63-475d-8260-ee42a590e8ff",
  "name": "Application 1.0.0",
  "description": "Johns Monday test build",
  "device_types_compatible": [
    "Beagle Bone"
  ],
  "info": {
    "type_info": {
      "type": "rootfs"
    }
  },
  "signed": false,
  "updates": {
    "type_info": "rootfs-image",
    "files": [
      {
        "name": "rootfs-image-1",
        "checksum": "cc436f982bc60a8255fe1926a450db5f195a19ad",
        "size": 123,
        "date": "2016-03-11T13:03:17.063+0000"
      }
    ],
    "meta_data": {}
  },
  "artifact_provides": {
    "artifact_name": "test",
    "rootfs-image.checksum": "32714818ad6f98ee0185a52e23a475d89122e3efd2b2c26c733781c28e798c99",
    "rootfs-image.version": "test"
  },
  "artifact_depends": {
    "device_type": [
      "test"
    ]
  },
  "size": 36891648,
  "modified": "2016-03-11T13:03:17.063493443Z"
}

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response. Artifact
400 Bad Request Invalid Request. Error
404 Not Found Not Found. Error
500 Internal Server Error Internal Server Error. Error

Update Artifact Info

Code samples

# You can also use wget
curl -X PUT https://hosted.mender.io/api/management/v1/deployments/artifacts/{id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

PUT https://hosted.mender.io/api/management/v1/deployments/artifacts/{id} HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "description": "Some description"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.put 'https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.put('https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /artifacts/{id}

Update description of a selected artifact

Edit description. Artifact is not allowed to be edited if it was used in any deployment.

Body parameter

{
  "description": "Some description"
}

Parameters

Name In Type Required Description
id path string true Artifact identifier.
body body ArtifactUpdate false

Example responses

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content The artifact metadata updated successfully. None
400 Bad Request Invalid Request. Error
404 Not Found Not Found. Error
422 Unprocessable Entity Unprocessable Entity. Error
500 Internal Server Error Internal Server Error. Error

Delete Artifact

Code samples

# You can also use wget
curl -X DELETE https://hosted.mender.io/api/management/v1/deployments/artifacts/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

DELETE https://hosted.mender.io/api/management/v1/deployments/artifacts/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.delete 'https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.delete('https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /artifacts/{id}

Delete the artifact

Deletes the artifact from file and artifacts storage. Artifacts used by deployments in progress can not be deleted until deployment finishes.

Parameters

Name In Type Required Description
id path string true Artifact identifier.

Example responses

404 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content The artifact deleted successfully. None
404 Not Found Not Found. Error
409 Conflict Artifact used by active deployment. Error
500 Internal Server Error Internal Server Error. Error

Download Artifact

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}/download \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}/download HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}/download',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}/download',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}/download', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}/download', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}/download");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/deployments/artifacts/{id}/download", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /artifacts/{id}/download

Get the download link of a selected artifact

Generates signed URL for downloading artifact file. URI can be used only with GET HTTP method. Link supports such HTTP headers: 'Range', 'If-Modified-Since', 'If-Unmodified-Since' It is valid for specified period of time.

Parameters

Name In Type Required Description
id path string true Artifact identifier.

Example responses

200 Response

{
  "uri": "http://mender.io/artifact.tar.gz.mender",
  "expire": "2016-10-29T10:45:34Z"
}

Responses

Status Meaning Description Schema
200 OK Successful response. ArtifactLink
400 Bad Request Invalid Request. Error
404 Not Found Not Found. Error
500 Internal Server Error Internal Server Error. Error

Get Storage Usage

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/deployments/limits/storage \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/deployments/limits/storage HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/deployments/limits/storage',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/deployments/limits/storage',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/deployments/limits/storage', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deployments/limits/storage', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/deployments/limits/storage");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/deployments/limits/storage", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /limits/storage

Get storage limit and current storage usage

Get storage limit and current storage usage for currently logged in user. If the limit value is 0 it means there is no limit for storage for logged in user.

Example responses

200 Response

{
  "limit": 1073741824,
  "usage": 536870912
}

Responses

Status Meaning Description Schema
200 OK Successful response. StorageLimit
500 Internal Server Error Internal Server Error. Error

Schemas

Error

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID (same as in X-MEN-RequestID header).

NewDeployment

{
  "name": "production",
  "artifact_name": "Application 0.0.1",
  "devices": [
    "00a0c91e6-7dec-11d0-a765-f81d4faebf6"
  ],
  "phases": [
    {
      "batch_size": 5,
      "start_ts": "2020-07-06T15:04:49.114046203+02:00"
    },
    {
      "batch_size": 15,
      "start_ts": "2020-07-06T16:04:49.114046203+02:00"
    },
    {
      "start_ts": "2020-07-06T17:04:49.114046203+02:00"
    }
  ],
  "retries": 3
}

Properties

Name Type Required Description Plans
name string true
artifact_name string true
devices [string] true
phases [NewDeploymentPhase] false professional, enterprise
retries integer false The number of times a device can retry the deployment in case of failure, defaults to 0

Deployment

{
  "created": "2016-02-11T13:03:17.063493443Z",
  "status": "finished",
  "name": "production",
  "artifact_name": "Application 0.0.1",
  "id": "00a0c91e6-7dec-11d0-a765-f81d4faebf6",
  "finished": "2016-03-11T13:03:17.063493443Z",
  "phases": [
    {
      "batch_size": 5
    },
    {
      "start_ts": "2020-07-06T17:04:49.114046203+02:00",
      "device_count": 25
    },
    {
      "batch_size": 15
    },
    {
      "start_ts": "2020-07-06T18:04:49.114046203+02:00",
      "device_count": 10
    },
    {
      "start_ts": "2020-07-06T19:04:49.114046203+02:00",
      "device_count": 0
    }
  ],
  "device_count": 500,
  "retries": 3
}

Properties

Name Type Required Description
created string(date-time) true
name string true
artifact_name string true
id string true
finished string(date-time) false
status string true
device_count integer true
artifacts [string] false
phases [DeploymentPhase] false
retries integer false The number of times a device can retry the deployment in case of failure, defaults to 0
max_devices integer false max_devices denotes a limit on a number of completed deployments (failed or successful) above which the dynamic deployment will be finished.
initial_device_count integer false In case of dynamic deployments this is a number of devices targeted initially (maching the filter at the moment of deployment creation).
dynamic boolean false Flag indicating if the deployment is dynamic or not.
filter Filter false Inventory filter assigned to the deployment

Enumerated Values

Property Value
status scheduled
status pending
status inprogress
status finished

NewDeploymentPhase

{
  "start_ts": "2019-07-07T21:10:17.063493443Z",
  "batch_size": 5
}

Properties

Name Type Required Description
batch_size integer false Percentage of devices to update in the phase.
This field is optional for the last phase.
The last phase will contain the rest of the devices.
Note that if the percentage of devices entered does not
add up to a whole number of devices it is rounded down,
and in the case it is rounded down to zero, a 400 error
will be returned. This is mostly a concern when the deployment
consists of a low number of devices, like say 5 percent of 11
devices will round to zero, and an error is returned by the server.
start_ts string(date-time) false Start date of a phase.
Can be skipped for the first phase of a new deployment definition ('start immediately').

DeploymentPhase

{
  "application/json": {
    "id": "foo",
    "start_ts": "2020-07-06T15:04:49.114046203+02:00",
    "batch_size": 5,
    "device_count": 42
  }
}

Properties

Name Type Required Description
id string false Phase identifier.
batch_size integer false Percentage of devices to update in the phase.
start_ts string(date-time) false Start date of a phase.
May be undefined for the first phase of a deployment.
device_count integer false Number of devices which already requested an update within this phase.

DeploymentStatistics

{
  "success": 3,
  "pending": 1,
  "failure": 0,
  "downloading": 1,
  "installing": 2,
  "rebooting": 3,
  "noartifact": 0,
  "already-installed": 0,
  "aborted": 0
}

Properties

Name Type Required Description
success integer true Number of successful deployments.
pending integer true Number of pending deployments.
downloading integer true Number of deployments being downloaded.
rebooting integer true Number of deployments devices are rebooting into.
installing integer true Number of deployments devices being installed.
failure integer true Number of failed deployments.
noartifact integer true Do not have appropriate artifact for device type.
already-installed integer true Number of devices unaffected by upgrade, since they are already running the specified software version.
aborted integer true Number of deployments aborted by user.

Device

{
  "id": "00a0c91e6-7dec-11d0-a765-f81d4faebf6",
  "finished": "2016-03-11T13:03:17.063493443Z",
  "status": "installing",
  "created": "2016-02-11T13:03:17.063493443Z",
  "device_type": "Raspberry Pi 3",
  "log": false,
  "state": "installing",
  "substate": "installing.enter;script:foo-bar"
}

Properties

Name Type Required Description
id string true Device identifier.
finished string(date-time) false
status string true
created string(date-time) false
device_type string false
log boolean true Availability of the device's deployment log.
state string false State reported by device
substate string false Additional state information

Enumerated Values

Property Value
status downloading
status installing
status rebooting
status pending
status success
status failure
status noartifact
status already-installed
status aborted
status decommissioned

ArtifactUpdate

{
  "description": "Some description"
}

Artifact information update.

Properties

Name Type Required Description
description string false

ArtifactTypeInfo

{
  "type": "string"
}

Information about update type.

Properties

Name Type Required Description
type string false

UpdateFile

{
  "name": "string",
  "checksum": "string",
  "size": 0,
  "date": "2019-08-24T14:15:22Z"
}

Information about particular update file.

Properties

Name Type Required Description
name string false
checksum string false
size integer false
date string(date-time) false

Update

{
  "type_info": {
    "type": "string"
  },
  "files": [
    {
      "name": "string",
      "checksum": "string",
      "size": 0,
      "date": "2019-08-24T14:15:22Z"
    }
  ],
  "meta_data": {}
}

Single updated to be applied.

Properties

Name Type Required Description
type_info ArtifactTypeInfo false Information about update type.
files [UpdateFile] false [Information about particular update file.
]
meta_data object false meta_data is an object of unknown structure as this is dependent of update type (also custom defined by user)

ArtifactInfo

{
  "format": "string",
  "version": 0
}

Information about artifact format and version.

Properties

Name Type Required Description
format string false
version integer false

Artifact

{
  "id": "0c13a0e6-6b63-475d-8260-ee42a590e8ff",
  "name": "Application 1.0.0",
  "description": "Johns Monday test build",
  "device_types_compatible": [
    "Beagle Bone"
  ],
  "info": {
    "type_info": {
      "type": "rootfs"
    }
  },
  "signed": false,
  "updates": {
    "type_info": "rootfs-image",
    "files": [
      {
        "name": "rootfs-image-1",
        "checksum": "cc436f982bc60a8255fe1926a450db5f195a19ad",
        "size": 123,
        "date": "2016-03-11T13:03:17.063+0000"
      }
    ],
    "meta_data": {}
  },
  "artifact_provides": {
    "artifact_name": "test",
    "rootfs-image.checksum": "32714818ad6f98ee0185a52e23a475d89122e3efd2b2c26c733781c28e798c99",
    "rootfs-image.version": "test"
  },
  "artifact_depends": {
    "device_type": [
      "test"
    ]
  },
  "size": 36891648,
  "modified": "2016-03-11T13:03:17.063493443Z"
}

Detailed artifact.

Properties

Name Type Required Description
id string true
name string true
description string true
device_types_compatible [string] true
info ArtifactInfo false Information about artifact format and version.
signed boolean false Idicates if artifact is signed or not.
updates [Update] false [Single updated to be applied.
]
artifact_provides object false List of Artifact provides.

Map of key/value pairs, where both keys and values are strings.
» additionalProperties string false
artifact_depends object false List of Artifact depends.

Map of key/value pairs, where keys are strings and values are lists of strings.
» additionalProperties [string] false
size number(integer) false Artifact total size in bytes - the size of the actual file that will be transferred to the device (compressed).
modified string(date-time) true Represents creation / last edition of any of the artifact properties.
{
  "uri": "http://mender.io/artifact.tar.gz.mender",
  "expire": "2016-10-29T10:45:34Z"
}

URL for artifact file download.

Name Type Required Description
uri string true
expire string(date-time) true

StorageLimit

{
  "limit": 1073741824,
  "usage": 536870912
}

Tenant account storage limit and storage usage.

Properties

Name Type Required Description
limit integer true Storage limit in bytes. If set to 0 - there is no limit for storage.
usage integer true Current storage usage in bytes.

Releases

[
  {
    "name": "my-app-v1.0.1",
    "artifacts": [
      {
        "id": "0c13a0e6-6b63-475d-8260-ee42a590e8ff",
        "name": "Application 1.0.0",
        "description": "Johns Monday test build",
        "device_types_compatible": [
          "Beagle Bone"
        ],
        "info": {
          "type_info": {
            "type": "rootfs"
          }
        },
        "signed": false,
        "updates": {
          "type_info": "rootfs-image",
          "files": [
            {
              "name": "rootfs-image-1",
              "checksum": "cc436f982bc60a8255fe1926a450db5f195a19ad",
              "size": 123,
              "date": "2016-03-11T13:03:17.063+0000"
            }
          ],
          "meta_data": {}
        },
        "artifact_provides": {
          "artifact_name": "test",
          "rootfs-image.checksum": "32714818ad6f98ee0185a52e23a475d89122e3efd2b2c26c733781c28e798c99",
          "rootfs-image.version": "test"
        },
        "artifact_depends": {
          "device_type": [
            "test"
          ]
        },
        "size": 36891648,
        "modified": "2016-03-11T13:03:17.063493443Z"
      },
      {
        "id": "0c13a0e6-6b63-475d-8260-ee42a590e8ff",
        "name": "Application 1.0.0",
        "description": "Johns Monday test build",
        "device_types_compatible": [
          "Raspberry Pi"
        ],
        "info": {
          "type_info": {
            "type": "rootfs"
          }
        },
        "signed": false,
        "updates": {
          "type_info": "rootfs-image",
          "files": [
            {
              "name": "rootfs-image-1",
              "checksum": "cc436f982bc60a8255fe1926a450db5f195a19ad",
              "size": 123,
              "date": "2016-03-11T13:03:17.063+0000"
            }
          ],
          "meta_data": {}
        },
        "artifact_provides": {
          "artifact_name": "test",
          "rootfs-image.checksum": "32714818ad6f98ee0185a52e23a475d89122e3efd2b2c26c733781c28e798c99",
          "rootfs-image.version": "test"
        },
        "artifact_depends": {
          "device_type": [
            "test"
          ]
        },
        "size": 36891648,
        "modified": "2016-03-11T13:03:17.063493443Z"
      }
    ]
  }
]

List of releases

Properties

Name Type Required Description
anonymous [Release] false List of releases

Release

{
  "name": "my-app-v1.0.1",
  "artifacts": [
    {
      "id": "0c13a0e6-6b63-475d-8260-ee42a590e8ff",
      "name": "Application 1.0.0",
      "description": "Johns Monday test build",
      "device_types_compatible": [
        "Beagle Bone"
      ],
      "info": {
        "type_info": {
          "type": "rootfs"
        }
      },
      "signed": false,
      "updates": {
        "type_info": "rootfs-image",
        "files": [
          {
            "name": "rootfs-image-1",
            "checksum": "cc436f982bc60a8255fe1926a450db5f195a19ad",
            "size": 123,
            "date": "2016-03-11T13:03:17.063+0000"
          }
        ],
        "meta_data": {}
      },
      "artifact_provides": {
        "artifact_name": "test",
        "rootfs-image.checksum": "32714818ad6f98ee0185a52e23a475d89122e3efd2b2c26c733781c28e798c99",
        "rootfs-image.version": "test"
      },
      "artifact_depends": {
        "device_type": [
          "test"
        ]
      },
      "size": 36891648,
      "modified": "2016-03-11T13:03:17.063493443Z"
    },
    {
      "id": "0c13a0e6-6b63-475d-8260-ee42a590e8ff",
      "name": "Application 1.0.0",
      "description": "Johns Monday test build",
      "device_types_compatible": [
        "Raspberry Pi"
      ],
      "info": {
        "type_info": {
          "type": "rootfs"
        }
      },
      "signed": false,
      "updates": {
        "type_info": "rootfs-image",
        "files": [
          {
            "name": "rootfs-image-1",
            "checksum": "cc436f982bc60a8255fe1926a450db5f195a19ad",
            "size": 123,
            "date": "2016-03-11T13:03:17.063+0000"
          }
        ],
        "meta_data": {}
      },
      "artifact_provides": {
        "artifact_name": "test",
        "rootfs-image.checksum": "32714818ad6f98ee0185a52e23a475d89122e3efd2b2c26c733781c28e798c99",
        "rootfs-image.version": "test"
      },
      "artifact_depends": {
        "device_type": [
          "test"
        ]
      },
      "size": 36891648,
      "modified": "2016-03-11T13:03:17.063493443Z"
    }
  ]
}

Groups artifacts with the same release name into a single resource.

Properties

Name Type Required Description
name string false release name.
artifacts [Artifact] false list of artifacts for this release.

FilterPredicate

{
  "type": "$eq",
  "attribute": "serial_no",
  "scope": "inventory",
  "value": "123456789"
}

Attribute filter predicate

Properties

Name Type Required Description
scope string true The scope of the attribute.

Scope is a string and acts as namespace for the attribute name.
attribute string true Name of the attribute to be queried for filtering.
type string true Type or operator of the filter predicate.
value string true The value of the attribute to be used in filtering.

Attribute type is implicit, inferred from the JSON type.

Supported types: number, string, array of numbers, array of strings.
Mixed arrays are not allowed.

Enumerated Values

Property Value
type $eq
type $gt
type $gte
type $in
type $lt
type $lte
type $ne
type $nin
type $exists

Filter

{
  "id": "myfilter",
  "name": "My Filter",
  "terms": [
    {
      "scope": "inventory",
      "attribute": "serial_no",
      "type": "$eq",
      "value": "123456789"
    }
  ]
}

Inventory filter assigned to the deployment

Properties

Name Type Required Description
id string true Unique identifier of the saved filter.
name string true Name of the saved filter.
terms [FilterPredicate] false [Attribute filter predicate]

Deployments v2

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

Version 2 of the API for deployments management. Intended for use by the web GUI.

Base URLs:

Create Deployment

Code samples

# You can also use wget
curl -X POST https://docker.mender.io/api/management/v2/deployments/deployments \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://docker.mender.io/api/management/v2/deployments/deployments HTTP/1.1
Host: docker.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "name": "production",
  "artifact_name": "Application 0.0.1",
  "filter_id": "00a0c91e6-7dec-11d0-a765-f81d4faebf6",
  "phases": [
    {
      "batch_size": 5,
      "start_ts": "2020-07-06T17:04:49.114046203+02:00"
    },
    {
      "batch_size": 15,
      "start_ts": "2020-07-06T18:04:49.114046203+02:00"
    },
    {
      "start_ts": "2020-07-06T19:04:49.114046203+02:00"
    }
  ],
  "retries": 3
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://docker.mender.io/api/management/v2/deployments/deployments',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://docker.mender.io/api/management/v2/deployments/deployments',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://docker.mender.io/api/management/v2/deployments/deployments', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://docker.mender.io/api/management/v2/deployments/deployments', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://docker.mender.io/api/management/v2/deployments/deployments");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://docker.mender.io/api/management/v2/deployments/deployments", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /deployments

Create a deployment

Deploy software to devices matching the given filter. The artifact is auto assigned to the device from all available artifacts based on artifact name and device type. Devices for which there are no compatible artifacts to be installed are considered finished successfully as well as receive the status of noartifact. If there are no artifacts for the deployment, the deployment will not be created and the 422 Unprocessable Entity status code will be returned. Dynamic deployments feature is available only to Enterprise users.

This operation is only available in our commercial offering and requires you to be on the following plans:

Body parameter

{
  "name": "production",
  "artifact_name": "Application 0.0.1",
  "filter_id": "00a0c91e6-7dec-11d0-a765-f81d4faebf6",
  "phases": [
    {
      "batch_size": 5,
      "start_ts": "2020-07-06T17:04:49.114046203+02:00"
    },
    {
      "batch_size": 15,
      "start_ts": "2020-07-06T18:04:49.114046203+02:00"
    },
    {
      "start_ts": "2020-07-06T19:04:49.114046203+02:00"
    }
  ],
  "retries": 3
}

Parameters

Name In Type Required Description
body body NewDeployment true New deployment that needs to be created.

Example responses

400 Response

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
201 Created New deployment created. None
400 Bad Request Bad request, see error message for details. Error
403 Forbidden Feature not available in your Plan. Error
422 Unprocessable Entity Unprocessable Entity. Error
500 Internal Server Error Internal Server Error. Error

Response Headers

Status Header Type Format Description
201 Location string URL of the newly created deployment.

Schemas

Error

{
  "error": "failed to decode device group data: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID (same as in X-MEN-RequestID header).

NewDeployment

{
  "name": "production",
  "artifact_name": "Application 0.0.1",
  "filter_id": "00a0c91e6-7dec-11d0-a765-f81d4faebf6",
  "phases": [
    {
      "batch_size": 5,
      "start_ts": "2020-07-06T17:04:49.114046203+02:00"
    },
    {
      "batch_size": 15,
      "start_ts": "2020-07-06T18:04:49.114046203+02:00"
    },
    {
      "start_ts": "2020-07-06T19:04:49.114046203+02:00"
    }
  ],
  "retries": 3
}

Properties

Name Type Required Description
name string true
artifact_name string true
filter_id string true ID of a filter from inventory service.
phases [NewDeploymentPhase] false
retries integer false The number of times a device can retry the deployment in case of failure, defaults to 0
max_devices integer false max_devices denotes a limit on a number of completed deployments (failed or successful) above which the dynamic deployment will be finished

NewDeploymentPhase

{
  "start_ts": "2019-07-07T21:10:17.063493443Z",
  "batch_size": 5
}

Properties

Name Type Required Description
batch_size integer false Percentage of devices to update in the phase.
This field is optional for the last phase.
The last phase will contain the rest of the devices.
Note that if the percentage of devices entered does not add up to a whole number of devices it is rounded down, and in the case it is rounded down to zero, a 400 error will be returned.
This is mostly a concern when the deployment consists of a low number of devices, like say 5 percent of 11 devices will round to zero, and an error is returned by the server.
In the case of dynamic deployment, the number of devices for each phase is being calculated based on the initial number of devices matching the filter.
start_ts string(date-time) false Start date of a phase.
Can be skipped for the first phase of a new deployment definition ('start immediately').

User administration and authentication

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for user administration and user authentication handling. Intended for use by the web GUI. All responses from the API will contain 'X-MEN-RequestID' header with server-side generated request ID.

Base URLs:

Login

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v1/useradm/auth/login \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/jwt'

POST https://hosted.mender.io/api/management/v1/useradm/auth/login HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/jwt

const inputBody = '{
  "token2fa": "012234"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/jwt'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/auth/login',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/jwt'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v1/useradm/auth/login',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/jwt'
}

r = requests.post('https://hosted.mender.io/api/management/v1/useradm/auth/login', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/jwt',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v1/useradm/auth/login', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/auth/login");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/jwt"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v1/useradm/auth/login", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /auth/login

Log in to Mender

Accepts user credentials via standard Basic Auth, and returns a JWT token to be used for authentication in subsequent requests.

Body parameter

{
  "token2fa": "012234"
}

Parameters

Name In Type Required Description
body body Twofactor false Two factor authentication token, required if two factor authentication is

Detailed descriptions

body: Two factor authentication token, required if two factor authentication is enabled and tenant's plan is Professional or Enterprise.

Example responses

200 Response

"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NzYxMTkxMzYsImlzcyI6Ik1lbmRlciIsInN1YiI6Ijg1NGIzMTA5LTQ4NjItNGEyNS1hMWZiLWYxMTE2MWNlN2E4NCIsInNjcCI6WyJtZW5kZXIuKiJdfQ.X7Ief4PhPLlR6mA2wh3G3K0Z2tud0rK1QJesxu52NfICSeARmlujczs-_1YZxMwI0s-HgpXHbXIjaSVK80BjxjAM1rqpRGvgqSqG-dU5KmglDpAaTr4VaJci3VFPlVUVTRpI7bfqNMnKZtjmOUAGwjvroDUwX1RwayEmms-efGI"

Responses

Status Meaning Description Schema
200 OK Authentication successful - a new JWT is issued and returned.

The JWT is signed with the API's private key ('RS256' signing algorithm), and contains the following standard claims:

Initiate Password Reset Request

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/start \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

POST https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/start HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "email": "user@mender.io"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/start',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/start',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.post('https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/start', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/start', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/start");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/start", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /auth/password-reset/start

Initiate a Password Reset request based on the provided email address

Starts a Password Reset request, sending an email to the user containing a unique, time-based hash which can be used to reset the password of the user.

Body parameter

{
  "email": "user@mender.io"
}

Parameters

Name In Type Required Description
body body PasswordResetRequest false Password Reset request, it includes the email address of the user.

Detailed descriptions

body: Password Reset request, it includes the email address of the user.

Example responses

400 Response

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
202 Accepted The request has been accepted. None
400 Bad Request The request body is malformed. Error
500 Internal Server Error Internal server error. Error

Complete Password Reset Request

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/complete \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

POST https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/complete HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "secret": "16fd2706-8baf-433b-82eb-8c7fada847da",
  "password": "new password"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/complete',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/complete',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.post('https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/complete', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/complete', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/complete");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v1/useradm/auth/password-reset/complete", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /auth/password-reset/complete

Complete a Password Reset request

Complete a Password Reset request initiated by the /auth/password-reset/start end-point. Caller provides the secret hash received by email, and the new password of the user.

Body parameter

{
  "secret": "16fd2706-8baf-433b-82eb-8c7fada847da",
  "password": "new password"
}

Parameters

Name In Type Required Description
body body PasswordResetCompletion false Password Reset request, it includes the secret hash received by email, as well as the new password of the user.

Detailed descriptions

body: Password Reset request, it includes the secret hash received by email, as well as the new password of the user.

Example responses

400 Response

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
202 Accepted The request has been accepted. None
400 Bad Request The request body is malformed. Error
500 Internal Server Error Internal server error. Error

List Users

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/useradm/users \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/useradm/users HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/users',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/useradm/users',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/useradm/users', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/useradm/users', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/users");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/useradm/users", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /users

*List all users registered under the tenant owning the JWT. *

Example responses

200 Response

[
  {
    "email": "user@acme.com",
    "id": "806603def19d417d004a4b67e",
    "created_ts": "2020-07-06T15:04:49.114046203+02:00",
    "updated_ts": "2020-07-07T01:04:49.114046203+02:00"
  }
]

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
401 Unauthorized The user cannot be granted authentication. Error
500 Internal Server Error Internal server error. Error

Response Schema

Status Code 200

ListOfUsers

Name Type Required Restrictions Description
ListOfUsers [User] false [User descriptor.]
» email string true A unique email address.
» id string true User Id.
» created_ts string(date-time) false Server-side timestamp of the user creation.
» updated_ts string(date-time) false Server-side timestamp of the last user information update.

Create User

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v1/useradm/users \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v1/useradm/users HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "email": "user@acme.com",
  "password": "mypass1234",
  "login": {
    "google": "bob@gmail.com"
  }
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/users',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v1/useradm/users',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v1/useradm/users', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v1/useradm/users', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/users");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v1/useradm/users", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /users

*Create a new user under the tenant owning the JWT. *

Body parameter

{
  "email": "user@acme.com",
  "password": "mypass1234",
  "login": {
    "google": "bob@gmail.com"
  }
}

Parameters

Name In Type Required Description
body body UserNew true New user data.

Example responses

400 Response

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
201 Created The user was successfully created. None
400 Bad Request The request body is malformed. Error
401 Unauthorized The user cannot be granted authentication. Error
422 Unprocessable Entity The email address is duplicated or password is too short. Error
500 Internal Server Error Internal server error. Error

Response Headers

Status Header Type Format Description
201 Location string URI for the newly created 'User' resource.

Show User

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/useradm/users/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/useradm/users/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/users/{id}',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/useradm/users/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/useradm/users/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/useradm/users/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/users/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/useradm/users/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /users/{id}

Get user information

Parameters

Name In Type Required Description
id path string true User id.

Example responses

200 Response

{
  "email": "user@acme.com",
  "id": "806603def19d417d004a4b67e",
  "created_ts": "2020-07-06T15:04:49.114046203+02:00",
  "updated_ts": "2020-07-07T01:04:49.114046203+02:00"
}

Responses

Status Meaning Description Schema
200 OK Successful response - a user information is returned. User
401 Unauthorized The user cannot be granted authentication. Error
404 Not Found The user was not found. Error
500 Internal Server Error Internal server error. Error

Update User

Code samples

# You can also use wget
curl -X PUT https://hosted.mender.io/api/management/v1/useradm/users/{id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

PUT https://hosted.mender.io/api/management/v1/useradm/users/{id} HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "email": "new_email@acme.com",
  "roles": [
    "RBAC_ROLE_DEPLOY_GROUP_TESTING_DEVICES",
    "RBAC_ROLE_READ_ONLY"
  ]
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/users/{id}',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.put 'https://hosted.mender.io/api/management/v1/useradm/users/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.put('https://hosted.mender.io/api/management/v1/useradm/users/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','https://hosted.mender.io/api/management/v1/useradm/users/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/users/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "https://hosted.mender.io/api/management/v1/useradm/users/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /users/{id}

Update user information

Body parameter

{
  "email": "new_email@acme.com",
  "roles": [
    "RBAC_ROLE_DEPLOY_GROUP_TESTING_DEVICES",
    "RBAC_ROLE_READ_ONLY"
  ]
}

Parameters

Name In Type Required Description
id path string true User id.
body body UserUpdate true Updated user data.

Example responses

400 Response

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content User information updated. None
400 Bad Request The request body is malformed. Error
401 Unauthorized The user cannot be granted authentication. Error
404 Not Found The user does not exist. Error
422 Unprocessable Entity The email address is duplicated or password is too short. Error
500 Internal Server Error Internal server error. Error

Remove User

Code samples

# You can also use wget
curl -X DELETE https://hosted.mender.io/api/management/v1/useradm/users/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

DELETE https://hosted.mender.io/api/management/v1/useradm/users/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/users/{id}',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.delete 'https://hosted.mender.io/api/management/v1/useradm/users/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.delete('https://hosted.mender.io/api/management/v1/useradm/users/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://hosted.mender.io/api/management/v1/useradm/users/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/users/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://hosted.mender.io/api/management/v1/useradm/users/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /users/{id}

Remove user from the system

Parameters

Name In Type Required Description
id path string true User id.

Example responses

401 Response

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content User removed. None
401 Unauthorized The user cannot be granted authentication. Error
500 Internal Server Error Internal server error. Error

List Roles

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/useradm/roles \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/useradm/roles HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/roles',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/useradm/roles',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/useradm/roles', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/useradm/roles', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/roles");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/useradm/roles", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /roles

List existing roles

This operation is only available in our commercial offering and requires you to be on the following plans:

Example responses

200 Response

[
  {
    "name": "RBAC_ROLE_NAME",
    "description": "Description of the role",
    "permissions": [
      {
        "action": "http",
        "object": {
          "type": "GET",
          "value": "/api/v1/endpoint"
        }
      },
      {
        "action": "http",
        "object": {
          "type": "POST",
          "value": "/api/v1/endpoint"
        }
      }
    ]
  }
]

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
401 Unauthorized The user cannot be granted authentication. Error
500 Internal Server Error Internal server error. Error

Response Schema

Status Code 200

ListOfRoles

Name Type Required Restrictions Description
ListOfRoles [Role] false [Role descriptor.]
» name string true A unique name.
» description string false Description of the role, as shown in the UI.
» permissions [RolePermission] false [Role permission]
»» action string true Action
»» object RolePermissionObject true Role permission object
»»» type string true Type
»»» value string true Value

Enumerated Values

Property Value
action any
action http
action CREATE_DEPLOYMENT

Create Role

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v1/useradm/roles \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v1/useradm/roles HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "name": "RBAC_ROLE_NAME",
  "description": "Description of the role",
  "permissions": [
    {
      "action": "http",
      "object": {
        "type": "GET",
        "value": "/api/v1/endpoint"
      }
    },
    {
      "action": "http",
      "object": {
        "type": "POST",
        "value": "/api/v1/endpoint"
      }
    }
  ]
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/roles',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v1/useradm/roles',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v1/useradm/roles', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v1/useradm/roles', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/roles");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v1/useradm/roles", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /roles

Create role

This operation is only available in our commercial offering and requires you to be on the following plans:

Body parameter

{
  "name": "RBAC_ROLE_NAME",
  "description": "Description of the role",
  "permissions": [
    {
      "action": "http",
      "object": {
        "type": "GET",
        "value": "/api/v1/endpoint"
      }
    },
    {
      "action": "http",
      "object": {
        "type": "POST",
        "value": "/api/v1/endpoint"
      }
    }
  ]
}

Parameters

Name In Type Required Description
body body Role true New role data.

Example responses

400 Response

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
201 Created The role was successfully created. None
400 Bad Request The request body is malformed. Error
401 Unauthorized The user cannot be granted authentication. Error
500 Internal Server Error Internal server error. Error

Response Headers

Status Header Type Format Description
201 Location string URI for the newly created 'Role' resource.

Show Role

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/useradm/roles/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/useradm/roles/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/roles/{id}',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/useradm/roles/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/useradm/roles/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/useradm/roles/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/roles/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/useradm/roles/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /roles/{id}

Get role information

Returns role information.

This operation is only available in our commercial offering and requires you to be on the following plans:

Parameters

Name In Type Required Description
id path string true Role id.

Example responses

200 Response

{
  "name": "RBAC_ROLE_NAME",
  "description": "Description of the role",
  "permissions": [
    {
      "action": "http",
      "object": {
        "type": "GET",
        "value": "/api/v1/endpoint"
      }
    },
    {
      "action": "http",
      "object": {
        "type": "POST",
        "value": "/api/v1/endpoint"
      }
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK Successful response - a role information is returned. Role
401 Unauthorized The user cannot be granted authentication. Error
404 Not Found The role was not found. Error
500 Internal Server Error Internal server error. Error

Update Role

Code samples

# You can also use wget
curl -X PUT https://hosted.mender.io/api/management/v1/useradm/roles/{id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

PUT https://hosted.mender.io/api/management/v1/useradm/roles/{id} HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "name": "RBAC_ROLE_NAME",
  "description": "Description of the role",
  "permissions": [
    {
      "action": "http",
      "object": {
        "type": "GET",
        "value": "/api/v1/endpoint"
      }
    },
    {
      "action": "http",
      "object": {
        "type": "POST",
        "value": "/api/v1/endpoint"
      }
    }
  ]
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/roles/{id}',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.put 'https://hosted.mender.io/api/management/v1/useradm/roles/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.put('https://hosted.mender.io/api/management/v1/useradm/roles/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','https://hosted.mender.io/api/management/v1/useradm/roles/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/roles/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "https://hosted.mender.io/api/management/v1/useradm/roles/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /roles/{id}

Update role description and list of permissions.

This operation is only available in our commercial offering and requires you to be on the following plans:

Body parameter

{
  "name": "RBAC_ROLE_NAME",
  "description": "Description of the role",
  "permissions": [
    {
      "action": "http",
      "object": {
        "type": "GET",
        "value": "/api/v1/endpoint"
      }
    },
    {
      "action": "http",
      "object": {
        "type": "POST",
        "value": "/api/v1/endpoint"
      }
    }
  ]
}

Parameters

Name In Type Required Description
id path string true Role id.
body body Role true Updated role data.

Example responses

400 Response

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
202 Accepted Role information updated. None
400 Bad Request The request body is malformed. Error
401 Unauthorized The user cannot be granted authentication. Error
404 Not Found The role does not exist. Error
500 Internal Server Error Internal server error. Error

Delete Role

Code samples

# You can also use wget
curl -X DELETE https://hosted.mender.io/api/management/v1/useradm/roles/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

DELETE https://hosted.mender.io/api/management/v1/useradm/roles/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/roles/{id}',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.delete 'https://hosted.mender.io/api/management/v1/useradm/roles/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.delete('https://hosted.mender.io/api/management/v1/useradm/roles/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://hosted.mender.io/api/management/v1/useradm/roles/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/roles/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://hosted.mender.io/api/management/v1/useradm/roles/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /roles/{id}

Remove role from the system

This operation is only available in our commercial offering and requires you to be on the following plans:

Parameters

Name In Type Required Description
id path string true Role id.

Example responses

401 Response

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Role removed. None
401 Unauthorized The user cannot be granted authentication. Error
500 Internal Server Error Internal server error. Error

Show User Settings

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/useradm/settings \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/useradm/settings HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/settings',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/useradm/settings',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.get('https://hosted.mender.io/api/management/v1/useradm/settings', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/useradm/settings', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/settings");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/useradm/settings", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /settings

Get user settings

Example responses

200 Response

{
  "2fa": "enabled"
}

Responses

Status Meaning Description Schema
200 OK Successful response - a user information is returned. Settings
401 Unauthorized The user cannot be granted authentication. Error
500 Internal Server Error Internal server error. Error

Update User Settings

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v1/useradm/settings \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v1/useradm/settings HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "2fa": "enabled"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/settings',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v1/useradm/settings',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v1/useradm/settings', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v1/useradm/settings', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/useradm/settings");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v1/useradm/settings", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /settings

Create new or update existing user settings

Body parameter

{
  "2fa": "enabled"
}

Parameters

Name In Type Required Description
body body Settings true New user settings.

Example responses

400 Response

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
201 Created User settings set. None
400 Bad Request The request body is malformed. Error
401 Unauthorized The user cannot be granted authentication. Error
500 Internal Server Error Internal server error. Error

Schemas

UserNew

{
  "email": "user@acme.com",
  "password": "mypass1234",
  "login": {
    "google": "bob@gmail.com"
  }
}

New user descriptor.

Properties

Name Type Required Description
email string true A unique email address. Non-ascii characters are invalid.
password string false Password.
login object false Alternative login schemes

UserUpdate

{
  "email": "new_email@acme.com",
  "roles": [
    "RBAC_ROLE_DEPLOY_GROUP_TESTING_DEVICES",
    "RBAC_ROLE_READ_ONLY"
  ]
}

Update user information.

Properties

Name Type Required Description
email string false A unique email address.
password string false Password.
roles [string] false List of roles for the user. If not provided existing roles are kept.
» ListOfRoles string false Role name

User

{
  "email": "user@acme.com",
  "id": "806603def19d417d004a4b67e",
  "created_ts": "2020-07-06T15:04:49.114046203+02:00",
  "updated_ts": "2020-07-07T01:04:49.114046203+02:00"
}

User descriptor.

Properties

Name Type Required Description
email string true A unique email address.
id string true User Id.
created_ts string(date-time) false Server-side timestamp of the user creation.
updated_ts string(date-time) false Server-side timestamp of the last user information update.

Role

{
  "name": "RBAC_ROLE_NAME",
  "description": "Description of the role",
  "permissions": [
    {
      "action": "http",
      "object": {
        "type": "GET",
        "value": "/api/v1/endpoint"
      }
    },
    {
      "action": "http",
      "object": {
        "type": "POST",
        "value": "/api/v1/endpoint"
      }
    }
  ]
}

Role descriptor.

Properties

Name Type Required Description
name string true A unique name.
description string false Description of the role, as shown in the UI.
permissions [RolePermission] false [Role permission]

RolePermission

{
  "action": "http",
  "object": {
    "type": "GET",
    "value": ".*"
  }
}

Role permission

Properties

Name Type Required Description
action string true Action
object RolePermissionObject true Role permission object

Enumerated Values

Property Value
action any
action http
action CREATE_DEPLOYMENT

RolePermissionObject

{
  "type": "POST",
  "value": "/api/v1/endpoint"
}

Role permission object

Properties

Name Type Required Description
type string true Type
value string true Value

Error

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID (same as in X-MEN-RequestID header).

Settings

{
  "2fa": "enabled"
}

User settings.

Properties

|2fa|string|false|Enable/disable two-factor authentication for this user.|professional, enterprise|

Enumerated Values

Property Value
2fa enabled
2fa disabled

Twofactor

{
  "token2fa": "012234"
}

Two factor authentication token

Properties

Name Type Required Description
token2fa string true Two factor authentication token

PasswordResetRequest

{
  "email": "user@mender.io"
}

Password reset request

Properties

Name Type Required Description
email string true User's email address

PasswordResetCompletion

{
  "secret": "16fd2706-8baf-433b-82eb-8c7fada847da",
  "password": "new password"
}

Password reset completion

Properties

Name Type Required Description
secret string true Secret hash received by email by the user
password string true New password of the user

Tenants

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An user-facing API to tenant administration service

Base URLs:

Tenant Info

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/tenantadm/user/tenant \
  -H 'Accept: */*' \
  -H 'Authorization: string'

GET https://hosted.mender.io/api/management/v1/tenantadm/user/tenant HTTP/1.1
Host: hosted.mender.io
Accept: */*
Authorization: string


const headers = {
  'Accept':'*/*',
  'Authorization':'string'
};

fetch('https://hosted.mender.io/api/management/v1/tenantadm/user/tenant',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => '*/*',
  'Authorization' => 'string'
}

result = RestClient.get 'https://hosted.mender.io/api/management/v1/tenantadm/user/tenant',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': '*/*',
  'Authorization': 'string'
}

r = requests.get('https://hosted.mender.io/api/management/v1/tenantadm/user/tenant', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => '*/*',
    'Authorization' => 'string',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/tenantadm/user/tenant', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/tenantadm/user/tenant");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"*/*"},
        "Authorization": []string{"string"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://hosted.mender.io/api/management/v1/tenantadm/user/tenant", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /user/tenant

Obtain information about current tenant

The returned tenant resolves to the owner of the subject claim (user unique ID) in the JWT token.

Parameters

Name In Type Required Description
Authorization header string(Bearer [token]) true The user token in base64-encoded form.

Example responses

200 Response

Responses

Status Meaning Description Schema
200 OK A tenant descriptor is returned. Tenant
401 Unauthorized Verification failed. None
404 Not Found User is not a part of any tenant organization. Error
500 Internal Server Error Unexpected error. Error

Create Account

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v1/tenantadm/tenants \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Accept: */*'

POST https://hosted.mender.io/api/management/v1/tenantadm/tenants HTTP/1.1
Host: hosted.mender.io
Content-Type: application/x-www-form-urlencoded
Accept: */*

const inputBody = '{
  "organization": "string",
  "email": "user@example.com",
  "password": "string",
  "g-recaptcha-response": "string",
  "name": "string",
  "token": "string",
  "plan": "os"
}';
const headers = {
  'Content-Type':'application/x-www-form-urlencoded',
  'Accept':'*/*'
};

fetch('https://hosted.mender.io/api/management/v1/tenantadm/tenants',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/x-www-form-urlencoded',
  'Accept' => '*/*'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v1/tenantadm/tenants',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Accept': '*/*'
}

r = requests.post('https://hosted.mender.io/api/management/v1/tenantadm/tenants', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/x-www-form-urlencoded',
    'Accept' => '*/*',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v1/tenantadm/tenants', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v1/tenantadm/tenants");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/x-www-form-urlencoded"},
        "Accept": []string{"*/*"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v1/tenantadm/tenants", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants

Create tenant organization

Body parameter

organization: string
email: user@example.com
password: string
g-recaptcha-response: string
name: string
token: string
plan: os

Parameters

Name In Type Required Description
body body object true
» organization body string true Organization name (non-ascii characters are not allowed)
» email body string(email) true Email address (non-ascii characters are not allowed)
» password body string true Password
» g-recaptcha-response body string true reCAPTCHA response
» name body string false customer name
» token body string false Stripe CC token. This field is required when payment is enabled.
» plan body string false customer plan

Enumerated Values

Parameter Value
» plan os
» plan professional
» plan enterprise

Example responses

400 Response

Responses

Status Meaning Description Schema
202 Accepted Request to create organization was accepted None
400 Bad Request The request body is malformed. Error
401 Unauthorized Recaptcha verififaction failed. Error
402 Payment Required Payment is enabled but the provided card is invalid or cannot be charged. Error
409 Conflict Email is duplicated. Error
500 Internal Server Error Internal server error. Error

Schemas

Tenant

{
  "id": "507f191e810c19729de860ea",
  "name": "Acme",
  "tenant_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0ODcwNTU3MzUsImp0aSI6IjM5MTJiZDNmLWVjMTEtNDgwNy05MmE4LTBkOTVjMWFmYjU1NCIsImlzcyI6Ik1lbmRlciIsInN1YiI6ImQ0NTljOTFmZDkzMWFkOGM0ZDk4ZGIyZjdlZjU3NjYxNDI3NDJiZDMyMzM0ZjIyNjYyZTNiNjE5YmRiZTJhNTYifQ.iY2XuyuDOHW9ilPPeeHuwmz9A-6asDqdfy3mCjXuODns1SshbuH_XXFPa7s2PpXCMkhEHB82nLEjwcSO7gTIz1uqzjyGufVbXlOiZqPrCXUm4DKvhSgANiVKfkw_JvD1w-V0jyctBcrUifIhqhRlhXNAJh3c5XAMzxe2kwt9t3JW5bXiXroc64gXdv0gnX-o7YgdrFfau3rAaMFinKqHzACmeE5YhEVF9eQPJQ99U0PO6tVCcG39O-vtt51ClWh3BVeeQrHcr5eWQZWFMHThdeoRitLwvsN8wzrEKUoL9q9SlFnu4uGJkfOfTuiafgF1pJ-UBDYdBdV4sV9626PdHQ",
  "status": "active"
}

Tenant descriptor.

Properties

Name Type Required Description
id string true Tenant ID.
name string true Name of the tenant's organization.
tenant_token string true Currently used tenant token.
status string false Status of the tenant account.
api_limits TenantApiLimits false API usage quota and burst limit definitions for a tenant - per API type.

Enumerated Values

Property Value
status active
status suspended

ApiBurst

{
  "action": "PATCH",
  "uri": "/api/devices/v1/inventory/device/attributes",
  "min_interval_sec": 10
}

API burst limit definition.

Properties

Name Type Required Description
action string false HTTP verb.
uri string false URI of the resource subject to the limit.
min_interval_sec integer false Minimum allowed interval, in seconds, between subsequent calls to 'action' on 'uri' (10 = one call every 10 seconds, etc.)

ApiQuota

{
  "max_calls": 100,
  "interval_sec": 3600
}

API usage quota definition.

Properties

Name Type Required Description
max_calls integer false Maximum allowed number of calls within 'interval'.
interval_sec integer false Interval definition, in seconds (60 = 1 minute, 3600 = 1 hour, etc.).

ApiLimits

{
  "bursts": [
    {
      "action": "PATCH",
      "uri": "/api/devices/v1/inventory/device/attributes",
      "min_interval_sec": 10
    },
    {
      "action": "POST",
      "uri": "/api/devices/v1/deployments/device/deployments/next",
      "min_interval_sec": 60
    }
  ],
  "quota": {
    "max_calls": 100,
    "interval_sec": 60
  }
}

Usage quota and burst limit definitions for an API type.

Properties

Name Type Required Description
bursts [ApiBurst] false Collection of api burst limit definitions over specified API resources.
quota ApiQuota false API usage quota definition.

TenantApiLimits

{
  "management": {
    "quota": {
      "max_calls": 100,
      "interval_sec": 60
    }
  },
  "devices": {
    "quota": {
      "max_calls": 1000,
      "interval_sec": 60
    },
    "bursts": [
      {
        "action": "PATCH",
        "uri": "/api/devices/v1/inventory/device/attributes",
        "min_interval_sec": 10
      },
      {
        "action": "POST",
        "uri": "/api/devices/v1/deployments/device/deployments/next",
        "min_interval_sec": 60
      }
    ]
  }
}

API usage quota and burst limit definitions for a tenant - per API type.

Properties

Name Type Required Description
management ApiLimits false Usage quota and burst limit definitions for an API type.
devices ApiLimits false Usage quota and burst limit definitions for an API type.

Error

{
  "error": "tenant_token is invalid",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.

Tenants v2

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

Version 2 of the user-facing API to tenant administration service

Base URLs:

Create Account

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v2/tenantadm/tenants \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Accept: application/json'

POST https://hosted.mender.io/api/management/v2/tenantadm/tenants HTTP/1.1
Host: hosted.mender.io
Content-Type: application/x-www-form-urlencoded
Accept: application/json

const inputBody = '{
  "organization": "string",
  "email": "user@example.com",
  "password": "string",
  "g-recaptcha-response": "string",
  "name": "string",
  "plan": "os"
}';
const headers = {
  'Content-Type':'application/x-www-form-urlencoded',
  'Accept':'application/json'
};

fetch('https://hosted.mender.io/api/management/v2/tenantadm/tenants',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/x-www-form-urlencoded',
  'Accept' => 'application/json'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v2/tenantadm/tenants',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Accept': 'application/json'
}

r = requests.post('https://hosted.mender.io/api/management/v2/tenantadm/tenants', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/x-www-form-urlencoded',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v2/tenantadm/tenants', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/tenantadm/tenants");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/x-www-form-urlencoded"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v2/tenantadm/tenants", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants

Create tenant organization

Body parameter

organization: string
email: user@example.com
password: string
g-recaptcha-response: string
name: string
plan: os

Parameters

Name In Type Required Description
body body object true
» organization body string true Organization name (invalid characters are non-ascii)
» email body string(email) true Email address (invalid characters are non-ascii)
» password body string true Password
» g-recaptcha-response body string true reCAPTCHA response
» name body string false customer name
» plan body string false customer plan

Enumerated Values

Parameter Value
» plan os
» plan professional
» plan enterprise

Example responses

A short tenant descriptor is returned.

{
  "id": "507f191e810c19729de860ea",
  "secret": "TYooMQauvdEDq54NiTphI7jx"
}

400 Response

{
  "error": "error details",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK A short tenant descriptor is returned. TenantShortInfo
400 Bad Request The request body is malformed. Error
401 Unauthorized Recaptcha verififaction failed. Error
409 Conflict Email is duplicated. Error
500 Internal Server Error Internal server error. Error

Create Trial Account

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v2/tenantadm/tenants/trial \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Accept: application/json'

POST https://hosted.mender.io/api/management/v2/tenantadm/tenants/trial HTTP/1.1
Host: hosted.mender.io
Content-Type: application/x-www-form-urlencoded
Accept: application/json

const inputBody = '{
  "organization": "string",
  "email": "user@example.com",
  "password": "string",
  "g-recaptcha-response": "string",
  "name": "string",
  "plan": "enterprise"
}';
const headers = {
  'Content-Type':'application/x-www-form-urlencoded',
  'Accept':'application/json'
};

fetch('https://hosted.mender.io/api/management/v2/tenantadm/tenants/trial',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/x-www-form-urlencoded',
  'Accept' => 'application/json'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v2/tenantadm/tenants/trial',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Accept': 'application/json'
}

r = requests.post('https://hosted.mender.io/api/management/v2/tenantadm/tenants/trial', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/x-www-form-urlencoded',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v2/tenantadm/tenants/trial', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/tenantadm/tenants/trial");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/x-www-form-urlencoded"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v2/tenantadm/tenants/trial", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants/trial

Create a trial organization

Body parameter

organization: string
email: user@example.com
password: string
g-recaptcha-response: string
name: string
plan: enterprise

Parameters

Name In Type Required Description
body body object true
» organization body string true Organization name (invalid characters are non-ascii)
» email body string(email) true Email address (invalid characters are non-ascii)
» password body string true Password
» g-recaptcha-response body string true reCAPTCHA response
» name body string false customer name
» plan body string false customer plan

Enumerated Values

Parameter Value
» plan os
» plan professional
» plan enterprise

Example responses

400 Response

{
  "error": "error details",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
202 Accepted Request to create organization was accepted None
400 Bad Request The request body is malformed. Error
401 Unauthorized Recaptcha verififaction failed. Error
409 Conflict Email is duplicated. Error
500 Internal Server Error Internal server error. Error

Delete Inactive Account

Code samples

# You can also use wget
curl -X DELETE https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id} \
  -H 'Accept: application/json'

DELETE https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id} HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.delete 'https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.delete('https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /tenants/{id}

Remove inactive tenant from the system.

Remove inactive tenant information from the system.

Parameters

Name In Type Required Description
id path string true Tenant ID.

Example responses

405 Response

{
  "error": "error details",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Tenant removed. None
405 Method Not Allowed The tenant cannot be removed.
Only inactive tenant can be removed. Error
500 Internal Server Error Internal server error. Error

Activate Account

Code samples

# You can also use wget
curl -X PUT https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/status \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

PUT https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/status HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "status": "active"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/status',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.put 'https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/status',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.put('https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/status', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/status', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/status");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/status", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /tenants/{id}/status

Activate tenant's account.

Changes the given tenant's suspension status to active. The only valid statuses is 'active'.

Body parameter

{
  "status": "active"
}

Parameters

Name In Type Required Description
id path string true Tenant ID.
body body Status true Target suspension status

Example responses

400 Response

{
  "error": "error details",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
202 Accepted Request to activate tenant was accepted. None
400 Bad Request The request body is malformed. See error for details. Error
404 Not Found The tenant was not found. Error
409 Conflict The tenant was suspended. Error
500 Internal Server Error Internal server error. Error

Cancel Account

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/cancel \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/cancel HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "reason": "Reason for cancelling the tenant"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/cancel',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/cancel',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/cancel', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/cancel', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/cancel");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/cancel", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants/{id}/cancel

Request the cancellation of a tenant

Requests the cancellation of a tenant.

Body parameter

{
  "reason": "Reason for cancelling the tenant"
}

Parameters

Name In Type Required Description
id path string true Tenant ID.
body body CancelRequest true Cancellation request

Example responses

400 Response

{
  "error": "error details",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
202 Accepted Request has been successfully recorded. None
400 Bad Request The request body is malformed. See error for details. Error
404 Not Found The tenant was not found. Error
409 Conflict The tenant is not active. Error
500 Internal Server Error Internal server error. Error

Start Account Upgrade

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/start \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/start HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/start',
{
  method: 'POST',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/start',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/start', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/start', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/start");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/start", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants/{id}/upgrade/start

Start the upgrade process of a trial tenant.

Start the upgrade process of a trial tenant.

Parameters

Name In Type Required Description
id path string true Tenant ID.

Example responses

A short tenant descriptor is returned.

{
  "id": "507f191e810c19729de860ea",
  "secret": "TYooMQauvdEDq54NiTphI7jx"
}

400 Response

{
  "error": "error details",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK A short tenant descriptor is returned. TenantShortInfo
400 Bad Request The request is malformed. Error
500 Internal Server Error Internal server error. Error

Complete Account Upgrade

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/complete \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/complete HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "plan": "os"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/complete',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/complete',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/complete', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/complete', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/complete");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/complete", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants/{id}/upgrade/complete

Complete the upgrade process of a trial tenant to a specified plan.

Complete the upgrade process of a trial tenant to a specified plan.

Body parameter

{
  "plan": "os"
}

Parameters

Name In Type Required Description
id path string true Tenant ID.
body body UpgradeCompleteRequest true Upgrade completion request

Example responses

400 Response

{
  "error": "error details",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
202 Accepted Request to complete the tenant upgrade was successfully processed None
400 Bad Request The request is malformed. Error
500 Internal Server Error Internal server error. Error

Cancel Account Upgrade

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/cancel \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/cancel HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/cancel',
{
  method: 'POST',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/cancel',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/cancel', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/cancel', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/cancel");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v2/tenantadm/tenants/{id}/upgrade/cancel", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants/{id}/upgrade/cancel

Cancel the upgrade process of a trial tenant.

Cancel the upgrade process of a trial tenant.

Parameters

Name In Type Required Description
id path string true Tenant ID.

Example responses

400 Response

{
  "error": "error details",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
202 Accepted Request to cancel the tenant upgrade was accepted None
400 Bad Request The request is malformed. Error
500 Internal Server Error Internal server error. Error

Get stripe secret

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v2/tenantadm/secret \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v2/tenantadm/secret HTTP/1.1
Host: hosted.mender.io
Accept: application/json


const headers = {
  'Accept':'application/json',
  'Authorization':'API_KEY'
};

fetch('https://hosted.mender.io/api/management/v2/tenantadm/secret',
{
  method: 'POST',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v2/tenantadm/secret',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'API_KEY'
}

r = requests.post('https://hosted.mender.io/api/management/v2/tenantadm/secret', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'API_KEY',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','https://hosted.mender.io/api/management/v2/tenantadm/secret', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://hosted.mender.io/api/management/v2/tenantadm/secret");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"API_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v2/tenantadm/secret", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /secret

Get stripe client secret, create if not exist.

Example responses

Stripe client secret is returned.

{
  "secret": "TYooMQauvdEDq54NiTphI7jx"
}

500 Response

{
  "error": "error details",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Stripe client secret is returned. CheckoutData
500 Internal Server Error Internal server error. Error

Schemas

TenantShortInfo

{
  "id": "507f191e810c19729de860ea",
  "secret": "TYooMQauvdEDq54NiTphI7jx"
}

Tenant short info.

Properties

Name Type Required Description
id string true Tenant ID.
intent_id string false Stripe Intent ID.
secret string true Stripe client secret.

CheckoutData

{
  "secret": "TYooMQauvdEDq54NiTphI7jx"
}

Checkout data.

Properties

Name Type Required Description
secret string true Stripe client secret.

Status

{
  "status": "active"
}

Status of a tenant account.

Properties

Name Type Required Description
status string true

Enumerated Values

Property Value
status active
status inactive
status suspended

CancelRequest

{
  "reason": "Reason for cancelling the tenant"
}

Cancellation request of a tenant account.

Properties

Name Type Required Description
reason string true

UpgradeCompleteRequest

{
  "plan": "os"
}

Upgrade a trial tenant to a given plan.

Properties

Name Type Required Description
plan string true customer plan

Enumerated Values

Property Value
plan os
plan professional
plan enterprise

Error

{
  "error": "error details",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.

Internal APIs

Device authentication

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for device authentication handling. Not exposed via the API Gateway, internal use only.

Base URLs:

Check Liveliness

Code samples

# You can also use wget
curl -X GET http://mender-device-auth:8080/api/internal/v1/devauth/alive \
  -H 'Accept: application/json'

GET http://mender-device-auth:8080/api/internal/v1/devauth/alive HTTP/1.1
Host: mender-device-auth:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-device-auth:8080/api/internal/v1/devauth/alive',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-device-auth:8080/api/internal/v1/devauth/alive',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-device-auth:8080/api/internal/v1/devauth/alive', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-device-auth:8080/api/internal/v1/devauth/alive', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-device-auth:8080/api/internal/v1/devauth/alive");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-device-auth:8080/api/internal/v1/devauth/alive", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /alive

*Trivial endpoint that unconditionally returns an empty 204 response whenever the API handler is running correctly. *

Example responses

500 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Service is up and running None
500 Internal Server Error Internal API error Error

Check Health

Code samples

# You can also use wget
curl -X GET http://mender-device-auth:8080/api/internal/v1/devauth/health \
  -H 'Accept: application/json'

GET http://mender-device-auth:8080/api/internal/v1/devauth/health HTTP/1.1
Host: mender-device-auth:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-device-auth:8080/api/internal/v1/devauth/health',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-device-auth:8080/api/internal/v1/devauth/health',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-device-auth:8080/api/internal/v1/devauth/health', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-device-auth:8080/api/internal/v1/devauth/health', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-device-auth:8080/api/internal/v1/devauth/health");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-device-auth:8080/api/internal/v1/devauth/health", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /health

Check the health of the service

Example responses

Unexpected internal error

{
  "error": "internal error",
  "request_id": "ffd712be-d697-4cb7-814b-88ff1e2eb5f6"
}

Service unhealthy / not ready to accept traffic. At least one dependency is not running.

{
  "error": "error reaching MongoDB: context deadline exceeded",
  "request_id": "ffd712be-d697-4cb7-814b-88ff1e2eb5f6"
}

Responses

Status Meaning Description Schema
204 No Content Service is healthy and all dependencies are up and running. None
500 Internal Server Error Unexpected internal error Error
503 Service Unavailable Service unhealthy / not ready to accept traffic. At least one dependency is not running. Error

Verify JWT

Code samples

# You can also use wget
curl -X POST http://mender-device-auth:8080/api/internal/v1/devauth/tokens/verify \
  -H 'Accept: application/json' \
  -H 'Authorization: string'

POST http://mender-device-auth:8080/api/internal/v1/devauth/tokens/verify HTTP/1.1
Host: mender-device-auth:8080
Accept: application/json
Authorization: string


const headers = {
  'Accept':'application/json',
  'Authorization':'string'
};

fetch('http://mender-device-auth:8080/api/internal/v1/devauth/tokens/verify',
{
  method: 'POST',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'string'
}

result = RestClient.post 'http://mender-device-auth:8080/api/internal/v1/devauth/tokens/verify',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'string'
}

r = requests.post('http://mender-device-auth:8080/api/internal/v1/devauth/tokens/verify', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'string',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-device-auth:8080/api/internal/v1/devauth/tokens/verify', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-device-auth:8080/api/internal/v1/devauth/tokens/verify");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"string"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-device-auth:8080/api/internal/v1/devauth/tokens/verify", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tokens/verify

Check the validity of a token

Besides the basic validity check, checks the token expiration time and user-initiated token revocation. Services which intend to use it should be correctly set up in the gateway's configuration.

Parameters

Name In Type Required Description
Authorization header string true The token in base64-encoded form.

Example responses

500 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK The token is valid. None
400 Bad Request Missing or malformed request parameters. None
401 Unauthorized Verification failed, authentication should not be granted. None
403 Forbidden Token has expired - apply for a new one. None
500 Internal Server Error Unexpected error. Error

Revoke Device Tokens

Code samples

# You can also use wget
curl -X DELETE http://mender-device-auth:8080/api/internal/v1/devauth/tokens?tenant_id=string \
  -H 'Accept: application/json'

DELETE http://mender-device-auth:8080/api/internal/v1/devauth/tokens?tenant_id=string HTTP/1.1
Host: mender-device-auth:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-device-auth:8080/api/internal/v1/devauth/tokens?tenant_id=string',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.delete 'http://mender-device-auth:8080/api/internal/v1/devauth/tokens',
  params: {
  'tenant_id' => 'string'
}, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.delete('http://mender-device-auth:8080/api/internal/v1/devauth/tokens', params={
  'tenant_id': 'string'
}, headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','http://mender-device-auth:8080/api/internal/v1/devauth/tokens', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-device-auth:8080/api/internal/v1/devauth/tokens?tenant_id=string");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "http://mender-device-auth:8080/api/internal/v1/devauth/tokens", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /tokens

Delete device tokens

This endpoint is designed to be used for device decommissionning and tenant account suspension purpose. For device decommissioning purpose both tenant_id and device_id parameters must be set. When both tenant_id and device_id parameters are set, all tokens will be deleted for device with given device_id. For tenant account suspension purpose only tenant_id parameter must be set. When device_id parameter is not set (only tenant_id parameter is set) all tokens for all tenant devices will be deleted.

Parameters

Name In Type Required Description
tenant_id query string true Tenant ID.
device_id query string false Device ID.

Example responses

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Tokens deleted. None
400 Bad Request Invalid parameters. See error message for details. Error
500 Internal Server Error Internal server error. Error

Get Device Limit

Code samples

# You can also use wget
curl -X GET http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices \
  -H 'Accept: application/json'

GET http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices HTTP/1.1
Host: mender-device-auth:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /tenant/{tenant_id}/limits/max_devices

Max device count limit

Parameters

Name In Type Required Description
tenant_id path string true Tenant ID.

Example responses

200 Response

{
  "limit": 123
}

Responses

Status Meaning Description Schema
200 OK Successful response. Limit
400 Bad Request Invalid parameters. See error message for details. Error
500 Internal Server Error Internal server error. Error

Update Device Limit

Code samples

# You can also use wget
curl -X PUT http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

PUT http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices HTTP/1.1
Host: mender-device-auth:8080
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "limit": 123
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.put 'http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.put('http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /tenant/{tenant_id}/limits/max_devices

Update max device count limit

Body parameter

{
  "limit": 123
}

Parameters

Name In Type Required Description
tenant_id path string true Tenant ID.
body body Limit true

Example responses

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Limit information updated. None
400 Bad Request The request body is malformed. Error
500 Internal Server Error Internal server error. Error

Clear Device Limit

Code samples

# You can also use wget
curl -X DELETE http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices \
  -H 'Accept: application/json'

DELETE http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices HTTP/1.1
Host: mender-device-auth:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.delete 'http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.delete('http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "http://mender-device-auth:8080/api/internal/v1/devauth/tenant/{tenant_id}/limits/max_devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /tenant/{tenant_id}/limits/max_devices

Remove max device count limit

Parameters

Name In Type Required Description
tenant_id path string true Tenant ID.

Example responses

500 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Limit information deleted. None
500 Internal Server Error Internal server error. Error

Create Tenant

Code samples

# You can also use wget
curl -X POST http://mender-device-auth:8080/api/internal/v1/devauth/tenants \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

POST http://mender-device-auth:8080/api/internal/v1/devauth/tenants HTTP/1.1
Host: mender-device-auth:8080
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "tenant_id": "58be8208dd77460001fe0d78"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('http://mender-device-auth:8080/api/internal/v1/devauth/tenants',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.post 'http://mender-device-auth:8080/api/internal/v1/devauth/tenants',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.post('http://mender-device-auth:8080/api/internal/v1/devauth/tenants', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-device-auth:8080/api/internal/v1/devauth/tenants', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-device-auth:8080/api/internal/v1/devauth/tenants");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-device-auth:8080/api/internal/v1/devauth/tenants", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants

Provision a new tenant

Sets up all tenant-related infrastructure, e.g. a migrated tenant's database.

Body parameter

{
  "tenant_id": "58be8208dd77460001fe0d78"
}

Parameters

Name In Type Required Description
body body NewTenant true New tenant descriptor.

Example responses

500 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
201 Created Tenant was successfully provisioned. None
400 Bad Request Bad request. None
500 Internal Server Error Internal server error. Error

Device Status

Code samples

# You can also use wget
curl -X GET http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices/{did}/status \
  -H 'Accept: application/json'

GET http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices/{did}/status HTTP/1.1
Host: mender-device-auth:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices/{did}/status',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices/{did}/status',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices/{did}/status', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices/{did}/status', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices/{did}/status");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices/{did}/status", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /tenants/{tid}/devices/{did}/status

Get the status of a tenant's device

Returns the overall status of the device, computed over the statuses of its various authsets.

Parameters

Name In Type Required Description
tid path string true Tenant identifier.
did path string true Device identifier.

Example responses

200 Response

{
  "status": "accepted"
}

Responses

Status Meaning Description Schema
200 OK Success. Status
400 Bad Request Invalid parameters. See error message for details. Error
404 Not Found Tenant or device not found. Error
500 Internal Server Error Internal server error. Error

List Devices

Code samples

# You can also use wget
curl -X GET http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices \
  -H 'Accept: application/json'

GET http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices HTTP/1.1
Host: mender-device-auth:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /tenants/{tid}/devices

Get a list of tenant's devices.

Provides a list of tenant's devices, sorted by creation date, with optional device status filter.

Parameters

Name In Type Required Description
tid path string true Tenant identifier.
status query string false Device status filter. If not specified, all devices are listed.
page query integer false Results page number
per_page query integer false Maximum number of results per page.

Detailed descriptions

status: Device status filter. If not specified, all devices are listed.

Enumerated Values

Parameter Value
status pending
status accepted
status rejected
status preauthorized
status noauth

Example responses

200 Response

[
  {
    "id": "string",
    "identity_data": {
      "mac": "00:01:02:03:04:05",
      "sku": "My Device 1",
      "sn": "SN1234567890"
    },
    "status": "pending",
    "created_ts": "string",
    "updated_ts": "string",
    "auth_sets": [
      {
        "id": "string",
        "pubkey": "string",
        "identity_data": {
          "mac": "00:01:02:03:04:05",
          "sku": "My Device 1",
          "sn": "SN1234567890"
        },
        "status": "pending",
        "ts": "string"
      }
    ],
    "decommissioning": true
  }
]

Responses

Status Meaning Description Schema
200 OK An array of devices. Inline
400 Bad Request Missing/malformed request params. Error
500 Internal Server Error Unexpected error Error

Response Schema

Status Code 200

Name Type Required Restrictions Description
anonymous [Device] false
» id string false Mender assigned Device ID.
» identity_data IdentityData false Device identity attributes, in the form of a JSON structure.

The attributes are completely vendor-specific, the provided ones are just an example.
In reference implementation structure contains vendor-selected fields,
such as MACs, serial numbers, etc.
»» mac string false MAC address.
»» sku string false Stock keeping unit.
»» sn string false Serial number.
» status string false
» created_ts string(datetime) false Created timestamp
» updated_ts string(datetime) false Updated timestamp
» auth_sets [AuthSet] false [Authentication data set]
»» id string false Authentication data set ID.
»» pubkey string false The device's public key (PEM encoding), generated by the device or pre-provisioned by the vendor. Currently supported public algorithms are: RSA, ED25519 and ECDSA.
»» identity_data IdentityData false Device identity attributes, in the form of a JSON structure.

The attributes are completely vendor-specific, the provided ones are just an example.
In reference implementation structure contains vendor-selected fields,
such as MACs, serial numbers, etc.
»» status string false
»» ts string(datetime) false Created timestamp
» decommissioning boolean false Devices that are part of ongoing decomissioning process will return True

Enumerated Values

Property Value
status pending
status accepted
status rejected
status preauthorized
status noauth
status pending
status accepted
status rejected
status preauthorized

Response Headers

Status Header Type Format Description
200 Link string Standard header, we support 'first', 'next', and 'prev'.

Schemas

NewTenant

{
  "tenant_id": "58be8208dd77460001fe0d78"
}

New tenant descriptor.

Properties

Name Type Required Description
tenant_id string false New tenant's ID.

Limit

{
  "limit": 123
}

Tenant account limit.

Properties

Name Type Required Description
limit integer true

Error

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID (same as in X-MEN-RequestID header).

Status

{
  "status": "accepted"
}

Admission status of the device.

Properties

Name Type Required Description
status string true

Enumerated Values

Property Value
status pending
status accepted
status rejected
status preauthorized
status noauth

Device

{
  "id": "string",
  "identity_data": {
    "mac": "00:01:02:03:04:05",
    "sku": "My Device 1",
    "sn": "SN1234567890"
  },
  "status": "pending",
  "created_ts": "string",
  "updated_ts": "string",
  "auth_sets": [
    {
      "id": "string",
      "pubkey": "string",
      "identity_data": {
        "mac": "00:01:02:03:04:05",
        "sku": "My Device 1",
        "sn": "SN1234567890"
      },
      "status": "pending",
      "ts": "string"
    }
  ],
  "decommissioning": true
}

Properties

Name Type Required Description
id string false Mender assigned Device ID.
identity_data IdentityData false Device identity attributes, in the form of a JSON structure.

The attributes are completely vendor-specific, the provided ones are just an example.
In reference implementation structure contains vendor-selected fields,
such as MACs, serial numbers, etc.
status string false
created_ts string(datetime) false Created timestamp
updated_ts string(datetime) false Updated timestamp
auth_sets [AuthSet] false [Authentication data set]
decommissioning boolean false Devices that are part of ongoing decomissioning process will return True

Enumerated Values

Property Value
status pending
status accepted
status rejected
status preauthorized
status noauth

AuthSet

{
  "id": "string",
  "pubkey": "string",
  "identity_data": {
    "mac": "00:01:02:03:04:05",
    "sku": "My Device 1",
    "sn": "SN1234567890"
  },
  "status": "pending",
  "ts": "string"
}

Authentication data set

Properties

Name Type Required Description
id string false Authentication data set ID.
pubkey string false The device's public key (PEM encoding), generated by the device or pre-provisioned by the vendor. Currently supported public algorithms are: RSA, ED25519 and ECDSA.
identity_data IdentityData false Device identity attributes, in the form of a JSON structure.

The attributes are completely vendor-specific, the provided ones are just an example.
In reference implementation structure contains vendor-selected fields,
such as MACs, serial numbers, etc.
status string false
ts string(datetime) false Created timestamp

Enumerated Values

Property Value
status pending
status accepted
status rejected
status preauthorized

IdentityData

{
  "mac": "00:01:02:03:04:05",
  "sku": "My Device 1",
  "sn": "SN1234567890"
}

Device identity attributes, in the form of a JSON structure.

The attributes are completely vendor-specific, the provided ones are just an example. In reference implementation structure contains vendor-selected fields, such as MACs, serial numbers, etc.

Properties

Name Type Required Description
mac string false MAC address.
sku string false Stock keeping unit.
sn string false Serial number.

Device inventory

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for device attribute management and device grouping. Not exposed via the API Gateway - intended for internal use only.

Base URLs:

Check Health

Code samples

# You can also use wget
curl -X GET http://mender-inventory:8080/api/internal/v1/inventory/health \
  -H 'Accept: */*'

GET http://mender-inventory:8080/api/internal/v1/inventory/health HTTP/1.1
Host: mender-inventory:8080
Accept: */*


const headers = {
  'Accept':'*/*'
};

fetch('http://mender-inventory:8080/api/internal/v1/inventory/health',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => '*/*'
}

result = RestClient.get 'http://mender-inventory:8080/api/internal/v1/inventory/health',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': '*/*'
}

r = requests.get('http://mender-inventory:8080/api/internal/v1/inventory/health', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => '*/*',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-inventory:8080/api/internal/v1/inventory/health', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-inventory:8080/api/internal/v1/inventory/health");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"*/*"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-inventory:8080/api/internal/v1/inventory/health", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /health

Check the health of the service

Example responses

500 Response

Unexpected internal error

{
  "error": "internal error",
  "request_id": "ffd712be-d697-4cb7-814b-88ff1e2eb5f6"
}

Service unhealthy / not ready to accept traffic. At least one dependency is not running.

{
  "error": "error reaching MongoDB: context deadline exceeded",
  "request_id": "ffd712be-d697-4cb7-814b-88ff1e2eb5f6"
}

Responses

Status Meaning Description Schema
204 No Content Service is healthy and all dependencies are up and running. None
500 Internal Server Error Unexpected internal error Error
503 Service Unavailable Service unhealthy / not ready to accept traffic. At least one dependency is not running. Error

Check Liveliness

Code samples

# You can also use wget
curl -X GET http://mender-inventory:8080/api/internal/v1/inventory/alive \
  -H 'Accept: */*'

GET http://mender-inventory:8080/api/internal/v1/inventory/alive HTTP/1.1
Host: mender-inventory:8080
Accept: */*


const headers = {
  'Accept':'*/*'
};

fetch('http://mender-inventory:8080/api/internal/v1/inventory/alive',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => '*/*'
}

result = RestClient.get 'http://mender-inventory:8080/api/internal/v1/inventory/alive',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': '*/*'
}

r = requests.get('http://mender-inventory:8080/api/internal/v1/inventory/alive', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => '*/*',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-inventory:8080/api/internal/v1/inventory/alive', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-inventory:8080/api/internal/v1/inventory/alive");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"*/*"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-inventory:8080/api/internal/v1/inventory/alive", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /alive

*Trivial endpoint that unconditionally returns an empty 200 response whenever the API handler is running correctly. *

Example responses

500 Response

Responses

Status Meaning Description Schema
204 No Content Service is up and running. None
500 Internal Server Error Internal API error Error

Create Tenant

Code samples

# You can also use wget
curl -X POST http://mender-inventory:8080/api/internal/v1/inventory/tenants \
  -H 'Content-Type: application/json' \
  -H 'Accept: */*'

POST http://mender-inventory:8080/api/internal/v1/inventory/tenants HTTP/1.1
Host: mender-inventory:8080
Content-Type: application/json
Accept: */*

const inputBody = '{
  "tenant_id": "1234"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'*/*'
};

fetch('http://mender-inventory:8080/api/internal/v1/inventory/tenants',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => '*/*'
}

result = RestClient.post 'http://mender-inventory:8080/api/internal/v1/inventory/tenants',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': '*/*'
}

r = requests.post('http://mender-inventory:8080/api/internal/v1/inventory/tenants', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => '*/*',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-inventory:8080/api/internal/v1/inventory/tenants', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-inventory:8080/api/internal/v1/inventory/tenants");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"*/*"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-inventory:8080/api/internal/v1/inventory/tenants", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants

Create tenant

Create a tenant with provided configuration.

Body parameter

{
  "tenant_id": "1234"
}

Parameters

Name In Type Required Description
body body TenantNew true

Example responses

500 Response

Responses

Status Meaning Description Schema
201 Created The tenant was created successfully. None
400 Bad Request Missing or malformed request parameters. None
500 Internal Server Error Unexpected error. Error

Initialize Device

Code samples

# You can also use wget
curl -X POST http://mender-inventory:8080/api/internal/v1/inventory/devices \
  -H 'Content-Type: application/json' \
  -H 'Accept: */*'

POST http://mender-inventory:8080/api/internal/v1/inventory/devices HTTP/1.1
Host: mender-inventory:8080
Content-Type: application/json
Accept: */*

const inputBody = '{
  "id": "291ae0e5956c69c2267489213df4459d19ed48a806603def19d417d004a4b67e",
  "attributes": [
    {
      "name": "ip_addr",
      "value": "1.2.3.4",
      "description": "IP address"
    },
    {
      "name": "mac_addr",
      "value": "00.01:02:03:04:05",
      "description": "MAC address"
    }
  ]
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'*/*'
};

fetch('http://mender-inventory:8080/api/internal/v1/inventory/devices',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => '*/*'
}

result = RestClient.post 'http://mender-inventory:8080/api/internal/v1/inventory/devices',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': '*/*'
}

r = requests.post('http://mender-inventory:8080/api/internal/v1/inventory/devices', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => '*/*',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-inventory:8080/api/internal/v1/inventory/devices', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-inventory:8080/api/internal/v1/inventory/devices");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"*/*"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-inventory:8080/api/internal/v1/inventory/devices", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /devices

Create a device resource with the supplied set of attributes

Body parameter

{
  "id": "291ae0e5956c69c2267489213df4459d19ed48a806603def19d417d004a4b67e",
  "attributes": [
    {
      "name": "ip_addr",
      "value": "1.2.3.4",
      "description": "IP address"
    },
    {
      "name": "mac_addr",
      "value": "00.01:02:03:04:05",
      "description": "MAC address"
    }
  ]
}

Parameters

Name In Type Required Description
body body DeviceNew true

Example responses

400 Response

Responses

Status Meaning Description Schema
201 Created The device was successfully created. None
400 Bad Request Malformed request body. See error for details. Error
500 Internal Server Error Internal server error. Error

Response Headers

Status Header Type Format Description
201 Location string URI for the newly created 'Device' resource.

Schemas

Error

{
  "error": "missing Authorization header"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.

TenantNew

{
  "tenant_id": "1234"
}

Tenant configuration.

Properties

Name Type Required Description
tenant_id string false ID of given tenant.

DeviceNew

{
  "id": "291ae0e5956c69c2267489213df4459d19ed48a806603def19d417d004a4b67e",
  "attributes": [
    {
      "name": "ip_addr",
      "value": "1.2.3.4",
      "description": "IP address"
    },
    {
      "name": "mac_addr",
      "value": "00.01:02:03:04:05",
      "description": "MAC address"
    }
  ]
}

Properties

Name Type Required Description
id string true Mender-assigned unique ID.
updated_ts string false Timestamp of the most recent attribute update.
attributes [Attribute] false A list of attribute descriptors.

Attribute

{
  "name": "ip_addr_eth",
  "description": "Device IP address on ethernet interface",
  "value": "127.0.0.1"
}

Attribute descriptor.

Properties

Name Type Required Description
name string true A human readable, unique attribute ID, e.g. 'device_type', 'ip_addr', 'cpu_load', etc.
description string false Attribute description.
value string true The current value of the attribute.

Attribute type is implicit, inferred from the JSON type.

Supported types: number, string, array of numbers, array of strings.
Mixed type arrays are not allowed.

Deployments Internal API

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

Internal API of deployments service

Base URLs:

Get Storage Usage

Code samples

# You can also use wget
curl -X GET http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage \
  -H 'Accept: application/json'

GET http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage HTTP/1.1
Host: mender-deployments:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /tenants/{id}/limits/storage

Get storage limit and current storage usage for given tenant

Get storage limit and current storage usage for given tenant. If the limit value is 0 it means storage space is unlimited

Parameters

Name In Type Required Description
id path string true Tenant ID

Example responses

200 Response

{
  "limit": 1073741824,
  "usage": 536870912
}

Responses

Status Meaning Description Schema
200 OK Successful response. StorageUsage
500 Internal Server Error Internal Server Error. Error

Set Storage Limit

Code samples

# You can also use wget
curl -X PUT http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

PUT http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage HTTP/1.1
Host: mender-deployments:8080
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "limit": 1073741824
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.put 'http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.put('http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/limits/storage", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /tenants/{id}/limits/storage

Set storage limit for given tenant

Set storage limit for given tenant. If the limit value is 0 it means storage space is unlimited

Body parameter

{
  "limit": 1073741824
}

Parameters

Name In Type Required Description
id path string true Tenant ID
body body StorageLimit true

Example responses

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Limit information updated. None
400 Bad Request The request body is malformed. Error
500 Internal Server Error Internal server error. Error

Create Tenant

Code samples

# You can also use wget
curl -X POST http://mender-deployments:8080/api/internal/v1/deployments/tenants \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

POST http://mender-deployments:8080/api/internal/v1/deployments/tenants HTTP/1.1
Host: mender-deployments:8080
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "tenant_id": "58be8208dd77460001fe0d78"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('http://mender-deployments:8080/api/internal/v1/deployments/tenants',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.post 'http://mender-deployments:8080/api/internal/v1/deployments/tenants',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.post('http://mender-deployments:8080/api/internal/v1/deployments/tenants', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-deployments:8080/api/internal/v1/deployments/tenants', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-deployments:8080/api/internal/v1/deployments/tenants");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-deployments:8080/api/internal/v1/deployments/tenants", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants

Provision a new tenant

Sets up all tenant-related infrastructure, e.g. a migrated tenant's database.

Body parameter

{
  "tenant_id": "58be8208dd77460001fe0d78"
}

Parameters

Name In Type Required Description
body body NewTenant true New tenant descriptor.

Example responses

500 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
201 Created Tenant was successfully provisioned. None
400 Bad Request Bad request. None
500 Internal Server Error Internal server error. Error

Get Deployments

Code samples

# You can also use wget
curl -X GET http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/deployments \
  -H 'Accept: application/json'

GET http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/deployments HTTP/1.1
Host: mender-deployments:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/deployments',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/deployments',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/deployments', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/deployments', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/deployments");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/deployments", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /tenants/{id}/deployments

Get all deployments for specific tenant

Returns a filtered collection of deployments in the system, including active and historical. If both 'status' and 'query' are not specified, all devices are listed.

Parameters

Name In Type Required Description
id path string true Tenant ID
status query string false Deployment status filter.
search query string false Deployment name or description filter.
page query number(integer) false Results page number
created_before query number(integer) false List only deployments created before and equal to Unix timestamp (UTC)
created_after query number(integer) false List only deployments created after and equal to Unix timestamp (UTC)

Enumerated Values

Parameter Value
status inprogress
status finished
status pending

Example responses

Successful response.

[
  {
    "created": "2016-02-11T13:03:17.063493443Z",
    "status": "finished",
    "name": "production",
    "artifact_name": "Application 0.0.1",
    "id": "00a0c91e6-7dec-11d0-a765-f81d4faebf6",
    "finished": "2016-03-11T13:03:17.063493443Z",
    "device_count": 10
  }
]

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
400 Bad Request Invalid Request. Error

Response Schema

Status Code 200

Name Type Required Restrictions Description
anonymous [Deployment] false
» created string(date-time) true
» name string true
» artifact_name string true
» id string true
» finished string(date-time) false
» status string true
» device_count integer false
» artifacts [string] false

Enumerated Values

Property Value
status inprogress
status pending
status finished

Upload artifact

Code samples

# You can also use wget
curl -X POST http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/artifacts \
  -H 'Content-Type: multipart/form-data' \
  -H 'Accept: application/json'

POST http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/artifacts HTTP/1.1
Host: mender-deployments:8080
Content-Type: multipart/form-data
Accept: application/json

const inputBody = '{
  "artifact_id": "string",
  "size": 0,
  "description": "string",
  "artifact": "string"
}';
const headers = {
  'Content-Type':'multipart/form-data',
  'Accept':'application/json'
};

fetch('http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/artifacts',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'multipart/form-data',
  'Accept' => 'application/json'
}

result = RestClient.post 'http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/artifacts',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'multipart/form-data',
  'Accept': 'application/json'
}

r = requests.post('http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/artifacts', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'multipart/form-data',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/artifacts', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/artifacts");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"multipart/form-data"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-deployments:8080/api/internal/v1/deployments/tenants/{id}/artifacts", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants/{id}/artifacts

Upload mender artifact

Upload mender artifact to a specific tenant. Multipart request with meta and artifact. Supports artifact versions v1, v2, v3.

Body parameter

artifact_id: string
size: 0
description: string
artifact: string

Parameters

Name In Type Required Description
id path string true Tenant ID, or "default" if running in non-multitenant setup
body body object false
» artifact_id body string false Artifact ID, optional; the server generates a randome one if not provided.
» size body integer(long) false Size of the artifact file in bytes.
» description body string false
» artifact body string(binary) true Artifact. It has to be the last part of request.

Example responses

400 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
201 Created Artifact uploaded. None
400 Bad Request Invalid Request. Error
500 Internal Server Error Internal Server Error. Error

Response Headers

Status Header Type Format Description
201 Location string URL of the newly uploaded artifact.

Check Health

Code samples

# You can also use wget
curl -X GET http://mender-deployments:8080/api/internal/v1/deployments/health \
  -H 'Accept: application/json'

GET http://mender-deployments:8080/api/internal/v1/deployments/health HTTP/1.1
Host: mender-deployments:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-deployments:8080/api/internal/v1/deployments/health',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-deployments:8080/api/internal/v1/deployments/health',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-deployments:8080/api/internal/v1/deployments/health', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-deployments:8080/api/internal/v1/deployments/health', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-deployments:8080/api/internal/v1/deployments/health");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-deployments:8080/api/internal/v1/deployments/health", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /health

Check the health of the service

Example responses

Unexpected internal error

{
  "error": "internal error",
  "request_id": "ffd712be-d697-4cb7-814b-88ff1e2eb5f6"
}

Service unhealthy / not ready to accept traffic. At least one dependency is not running.

{
  "error": "error reaching MongoDB: context deadline exceeded",
  "request_id": "ffd712be-d697-4cb7-814b-88ff1e2eb5f6"
}

Responses

Status Meaning Description Schema
204 No Content Service is healthy and all dependencies are up and running. None
500 Internal Server Error Unexpected internal error Error
503 Service Unavailable Service unhealthy / not ready to accept traffic. At least one dependency is not running. Error

Check Liveliness

Code samples

# You can also use wget
curl -X GET http://mender-deployments:8080/api/internal/v1/deployments/alive \
  -H 'Accept: application/json'

GET http://mender-deployments:8080/api/internal/v1/deployments/alive HTTP/1.1
Host: mender-deployments:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-deployments:8080/api/internal/v1/deployments/alive',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-deployments:8080/api/internal/v1/deployments/alive',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-deployments:8080/api/internal/v1/deployments/alive', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-deployments:8080/api/internal/v1/deployments/alive', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-deployments:8080/api/internal/v1/deployments/alive");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-deployments:8080/api/internal/v1/deployments/alive", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /alive

*Trivial endpoint that unconditionally returns an empty 200 response whenever the API handler is running correctly. *

Example responses

500 Response

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
204 No Content Service is up and running. None
500 Internal Server Error Internal API error Error

Schemas

NewTenant

{
  "tenant_id": "58be8208dd77460001fe0d78"
}

New tenant descriptor.

Properties

Name Type Required Description
tenant_id string false New tenant's ID.

Error

{
  "error": "failed to decode request body: JSON payload is empty",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID (same as in X-MEN-RequestID header).

StorageUsage

{
  "limit": 1073741824,
  "usage": 536870912
}

Tenant account storage limit and storage usage.

Properties

Name Type Required Description
limit integer true Storage limit in bytes. If set to 0 - there is no limit for storage.
usage integer true Current storage usage in bytes.

StorageLimit

{
  "limit": 1073741824
}

Tenant account storage limit

Properties

Name Type Required Description
limit integer true Storage limit in bytes. If set to 0 - there is no limit for storage.

Deployment

{
  "created": "2016-02-11T13:03:17.063493443Z",
  "status": "finished",
  "name": "production",
  "artifact_name": "Application 0.0.1",
  "id": "00a0c91e6-7dec-11d0-a765-f81d4faebf6",
  "finished": "2016-03-11T13:03:17.063493443Z"
}

Properties

Name Type Required Description
created string(date-time) true
name string true
artifact_name string true
id string true
finished string(date-time) false
status string true
device_count integer false
artifacts [string] false

Enumerated Values

Property Value
status inprogress
status pending
status finished

User administration and authentication

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for user administration and user authentication handling. Not exposed via the API Gateway - intended for internal use only.

Base URLs:

Check Health

Code samples

# You can also use wget
curl -X GET http://mender-useradm:8080/api/internal/v1/useradm/health \
  -H 'Accept: */*'

GET http://mender-useradm:8080/api/internal/v1/useradm/health HTTP/1.1
Host: mender-useradm:8080
Accept: */*


const headers = {
  'Accept':'*/*'
};

fetch('http://mender-useradm:8080/api/internal/v1/useradm/health',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => '*/*'
}

result = RestClient.get 'http://mender-useradm:8080/api/internal/v1/useradm/health',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': '*/*'
}

r = requests.get('http://mender-useradm:8080/api/internal/v1/useradm/health', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => '*/*',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-useradm:8080/api/internal/v1/useradm/health', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-useradm:8080/api/internal/v1/useradm/health");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"*/*"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-useradm:8080/api/internal/v1/useradm/health", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /health

Check the health of the service

Example responses

500 Response

Unexpected internal error

{
  "error": "internal error",
  "request_id": "ffd712be-d697-4cb7-814b-88ff1e2eb5f6"
}

Service unhealthy / not ready to accept traffic. At least one dependency is not running.

{
  "error": "error reaching MongoDB: context deadline exceeded",
  "request_id": "ffd712be-d697-4cb7-814b-88ff1e2eb5f6"
}

Responses

Status Meaning Description Schema
204 No Content Service is healthy and all dependencies are up and running. None
500 Internal Server Error Unexpected internal error Error
503 Service Unavailable Service unhealthy / not ready to accept traffic. At least one dependency is not running. Error

Check Liveliness

Code samples

# You can also use wget
curl -X GET http://mender-useradm:8080/api/internal/v1/useradm/alive \
  -H 'Accept: */*'

GET http://mender-useradm:8080/api/internal/v1/useradm/alive HTTP/1.1
Host: mender-useradm:8080
Accept: */*


const headers = {
  'Accept':'*/*'
};

fetch('http://mender-useradm:8080/api/internal/v1/useradm/alive',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => '*/*'
}

result = RestClient.get 'http://mender-useradm:8080/api/internal/v1/useradm/alive',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': '*/*'
}

r = requests.get('http://mender-useradm:8080/api/internal/v1/useradm/alive', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => '*/*',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-useradm:8080/api/internal/v1/useradm/alive', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-useradm:8080/api/internal/v1/useradm/alive");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"*/*"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-useradm:8080/api/internal/v1/useradm/alive", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /alive

*Trivial endpoint that unconditionally returns an empty 200 response whenever the API handler is running correctly. *

Example responses

500 Response

Responses

Status Meaning Description Schema
204 No Content Service is up and running. None
500 Internal Server Error Internal API error Error

Verify JWT

Code samples

# You can also use wget
curl -X POST http://mender-useradm:8080/api/internal/v1/useradm/auth/verify \
  -H 'Accept: */*' \
  -H 'Authorization: string' \
  -H 'X-Original-URI: string' \
  -H 'X-Original-Method: GET'

POST http://mender-useradm:8080/api/internal/v1/useradm/auth/verify HTTP/1.1
Host: mender-useradm:8080
Accept: */*
Authorization: string
X-Original-URI: string
X-Original-Method: GET


const headers = {
  'Accept':'*/*',
  'Authorization':'string',
  'X-Original-URI':'string',
  'X-Original-Method':'GET'
};

fetch('http://mender-useradm:8080/api/internal/v1/useradm/auth/verify',
{
  method: 'POST',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => '*/*',
  'Authorization' => 'string',
  'X-Original-URI' => 'string',
  'X-Original-Method' => 'GET'
}

result = RestClient.post 'http://mender-useradm:8080/api/internal/v1/useradm/auth/verify',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': '*/*',
  'Authorization': 'string',
  'X-Original-URI': 'string',
  'X-Original-Method': 'GET'
}

r = requests.post('http://mender-useradm:8080/api/internal/v1/useradm/auth/verify', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => '*/*',
    'Authorization' => 'string',
    'X-Original-URI' => 'string',
    'X-Original-Method' => 'GET',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-useradm:8080/api/internal/v1/useradm/auth/verify', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-useradm:8080/api/internal/v1/useradm/auth/verify");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"*/*"},
        "Authorization": []string{"string"},
        "X-Original-URI": []string{"string"},
        "X-Original-Method": []string{"GET"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-useradm:8080/api/internal/v1/useradm/auth/verify", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /auth/verify

Check the validity of a token

Besides the basic validity check, checks the token expiration time and user-initiated token revocation.

Services which intend to use it should be correctly set up in the gateway's configuration.

Parameters

Name In Type Required Description
Authorization header string(Bearer [token]) true The token in base64-encoded form.
X-Original-URI header string(HTTP path) true URI the original request was sent to, the URI is expected to have
X-Original-Method header string true HTTP method used when accessing the original URI

Detailed descriptions

X-Original-URI: URI the original request was sent to, the URI is expected to have at least 4 components, eg. /api/management/1.0/foo/bar

Enumerated Values

Parameter Value
X-Original-Method GET
X-Original-Method PUT
X-Original-Method POST
X-Original-Method DELETE

Example responses

400 Response

Responses

Status Meaning Description Schema
200 OK The token is valid. None
400 Bad Request Missing or malformed request parameters. Error
401 Unauthorized Verification failed, authentication should not be granted. Error
403 Forbidden Token has expired - apply for a new one. Error
500 Internal Server Error Unexpected error. Error

Verify Plan

Code samples

# You can also use wget
curl -X POST http://mender-useradm:8080/api/internal/v1/useradm/plan/verify \
  -H 'Accept: */*' \
  -H 'Authorization: string' \
  -H 'X-Mender-Required-Minimal-Plan: string'

POST http://mender-useradm:8080/api/internal/v1/useradm/plan/verify HTTP/1.1
Host: mender-useradm:8080
Accept: */*
Authorization: string
X-Mender-Required-Minimal-Plan: string


const headers = {
  'Accept':'*/*',
  'Authorization':'string',
  'X-Mender-Required-Minimal-Plan':'string'
};

fetch('http://mender-useradm:8080/api/internal/v1/useradm/plan/verify',
{
  method: 'POST',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => '*/*',
  'Authorization' => 'string',
  'X-Mender-Required-Minimal-Plan' => 'string'
}

result = RestClient.post 'http://mender-useradm:8080/api/internal/v1/useradm/plan/verify',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': '*/*',
  'Authorization': 'string',
  'X-Mender-Required-Minimal-Plan': 'string'
}

r = requests.post('http://mender-useradm:8080/api/internal/v1/useradm/plan/verify', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => '*/*',
    'Authorization' => 'string',
    'X-Mender-Required-Minimal-Plan' => 'string',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-useradm:8080/api/internal/v1/useradm/plan/verify', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-useradm:8080/api/internal/v1/useradm/plan/verify");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"*/*"},
        "Authorization": []string{"string"},
        "X-Mender-Required-Minimal-Plan": []string{"string"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-useradm:8080/api/internal/v1/useradm/plan/verify", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /plan/verify

Check if the user has given pricing plan associated

Checks if user is in the given plan

Services which intend to use it should be correctly set up in the gateway's configuration.

Parameters

Name In Type Required Description
Authorization header string(Bearer [token]) true The token in base64-encoded form.
X-Mender-Required-Minimal-Plan header string true Required minimal plan to complete the request

Detailed descriptions

X-Mender-Required-Minimal-Plan: Required minimal plan to complete the request

Example responses

500 Response

Responses

Status Meaning Description Schema
200 OK The given plan and user plan match. None
401 Unauthorized The plans do not match or user is not logged in. None
500 Internal Server Error Unexpected error. Error

Create Tenant

Code samples

# You can also use wget
curl -X POST http://mender-useradm:8080/api/internal/v1/useradm/tenants \
  -H 'Content-Type: application/json' \
  -H 'Accept: */*'

POST http://mender-useradm:8080/api/internal/v1/useradm/tenants HTTP/1.1
Host: mender-useradm:8080
Content-Type: application/json
Accept: */*

const inputBody = '{
  "tenant_id": "1234"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'*/*'
};

fetch('http://mender-useradm:8080/api/internal/v1/useradm/tenants',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => '*/*'
}

result = RestClient.post 'http://mender-useradm:8080/api/internal/v1/useradm/tenants',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': '*/*'
}

r = requests.post('http://mender-useradm:8080/api/internal/v1/useradm/tenants', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => '*/*',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-useradm:8080/api/internal/v1/useradm/tenants', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-useradm:8080/api/internal/v1/useradm/tenants");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"*/*"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-useradm:8080/api/internal/v1/useradm/tenants", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants

Create a tenant with provided configuration.

Body parameter

{
  "tenant_id": "1234"
}

Parameters

Name In Type Required Description
body body TenantNew true

Example responses

500 Response

Responses

Status Meaning Description Schema
201 Created The tenant was created successfully. None
400 Bad Request Missing or malformed request parameters. None
500 Internal Server Error Unexpected error. Error

Create User

Code samples

# You can also use wget
curl -X POST http://mender-useradm:8080/api/internal/v1/useradm/tenants/{tenant_id}/users \
  -H 'Content-Type: application/json' \
  -H 'Accept: */*'

POST http://mender-useradm:8080/api/internal/v1/useradm/tenants/{tenant_id}/users HTTP/1.1
Host: mender-useradm:8080
Content-Type: application/json
Accept: */*

const inputBody = '{
  "email": "user@acme.com",
  "password": "secret",
  "propagate": false
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'*/*'
};

fetch('http://mender-useradm:8080/api/internal/v1/useradm/tenants/{tenant_id}/users',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => '*/*'
}

result = RestClient.post 'http://mender-useradm:8080/api/internal/v1/useradm/tenants/{tenant_id}/users',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': '*/*'
}

r = requests.post('http://mender-useradm:8080/api/internal/v1/useradm/tenants/{tenant_id}/users', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => '*/*',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-useradm:8080/api/internal/v1/useradm/tenants/{tenant_id}/users', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-useradm:8080/api/internal/v1/useradm/tenants/{tenant_id}/users");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"*/*"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-useradm:8080/api/internal/v1/useradm/tenants/{tenant_id}/users", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants/{tenant_id}/users

Create user

Body parameter

{
  "email": "user@acme.com",
  "password": "secret",
  "propagate": false
}

Parameters

Name In Type Required Description
tenant_id path string true Tenant ID.
body body UserNew true New user data.

Example responses

400 Response

Responses

Status Meaning Description Schema
201 Created The user was successfully created. None
400 Bad Request The request body is malformed. Error
404 Not Found Tenant with given ID does not exist. Error
422 Unprocessable Entity User name or ID is duplicated. Error
500 Internal Server Error Internal server error. Error

Revoke User Tokens

Code samples

# You can also use wget
curl -X DELETE http://mender-useradm:8080/api/internal/v1/useradm/tokens?tenant_id=string \
  -H 'Accept: */*'

DELETE http://mender-useradm:8080/api/internal/v1/useradm/tokens?tenant_id=string HTTP/1.1
Host: mender-useradm:8080
Accept: */*


const headers = {
  'Accept':'*/*'
};

fetch('http://mender-useradm:8080/api/internal/v1/useradm/tokens?tenant_id=string',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => '*/*'
}

result = RestClient.delete 'http://mender-useradm:8080/api/internal/v1/useradm/tokens',
  params: {
  'tenant_id' => 'string'
}, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': '*/*'
}

r = requests.delete('http://mender-useradm:8080/api/internal/v1/useradm/tokens', params={
  'tenant_id': 'string'
}, headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => '*/*',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','http://mender-useradm:8080/api/internal/v1/useradm/tokens', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-useradm:8080/api/internal/v1/useradm/tokens?tenant_id=string");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"*/*"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "http://mender-useradm:8080/api/internal/v1/useradm/tokens", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /tokens

Delete all user tokens

This endpoint is designed to be used for tenant account suspension purpose. When only tenant_id parameter is set, tokens for all tenant users will be removed. It is also possible to remove tokens for user with given user_id by setting optional user_id parameter.

Parameters

Name In Type Required Description
tenant_id query string true Tenant ID.
user_id query string false User ID.

Example responses

400 Response

Responses

Status Meaning Description Schema
204 No Content Tokens deleted. None
400 Bad Request Invalid parameters. Error
500 Internal Server Error Internal server error. Error

Schemas

Error

{
  "error": "missing Authorization header"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.

TenantNew

{
  "tenant_id": "1234"
}

Tenant configuration.

Properties

Name Type Required Description
tenant_id string false ID of given tenant.

UserNew

{
  "email": "user@acme.com",
  "password": "secret",
  "propagate": false
}

New user descriptor.

Properties

Name Type Required Description
email string(email) true User's email.
password string true User's password.
propagate boolean false When propagate is true, the useradm will propagate user information
to tenantadm, otherwise no request to tenantadm will be made.
Defaults to true.

Tenant administration

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for tenant administration, not exposed via the API Gateway - intended for internal use only.

Base URLs:

Check Health

Code samples

# You can also use wget
curl -X GET http://mender-tenantadm:8080/api/internal/v1/tenantadm/health \
  -H 'Accept: application/json'

GET http://mender-tenantadm:8080/api/internal/v1/tenantadm/health HTTP/1.1
Host: mender-tenantadm:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-tenantadm:8080/api/internal/v1/tenantadm/health',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-tenantadm:8080/api/internal/v1/tenantadm/health',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-tenantadm:8080/api/internal/v1/tenantadm/health', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-tenantadm:8080/api/internal/v1/tenantadm/health', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-tenantadm:8080/api/internal/v1/tenantadm/health");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-tenantadm:8080/api/internal/v1/tenantadm/health", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /health

Check the health of the service

Example responses

500 Response

{
  "error": "tenant_token is invalid"
}

Responses

Status Meaning Description Schema
204 No Content Service is healthy and all dependencies are up and running. None
500 Internal Server Error Unexpected internal error Error
503 Service Unavailable Service unhealthy / not ready to accept traffic. At least one dependency is not running. Error

Check Liveliness

Code samples

# You can also use wget
curl -X GET http://mender-tenantadm:8080/api/internal/v1/tenantadm/alive \
  -H 'Accept: application/json'

GET http://mender-tenantadm:8080/api/internal/v1/tenantadm/alive HTTP/1.1
Host: mender-tenantadm:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-tenantadm:8080/api/internal/v1/tenantadm/alive',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-tenantadm:8080/api/internal/v1/tenantadm/alive',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-tenantadm:8080/api/internal/v1/tenantadm/alive', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-tenantadm:8080/api/internal/v1/tenantadm/alive', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-tenantadm:8080/api/internal/v1/tenantadm/alive");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-tenantadm:8080/api/internal/v1/tenantadm/alive", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /alive

*Trivial endpoint that unconditionally returns an empty 200 response whenever the API handler is running correctly. *

Example responses

500 Response

{
  "error": "tenant_token is invalid"
}

Responses

Status Meaning Description Schema
204 No Content Service is up and running None
500 Internal Server Error Internal API error Error

Verify JWT

Code samples

# You can also use wget
curl -X POST http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/verify \
  -H 'Accept: application/json' \
  -H 'Authorization: string'

POST http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/verify HTTP/1.1
Host: mender-tenantadm:8080
Accept: application/json
Authorization: string


const headers = {
  'Accept':'application/json',
  'Authorization':'string'
};

fetch('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/verify',
{
  method: 'POST',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'string'
}

result = RestClient.post 'http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/verify',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'string'
}

r = requests.post('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/verify', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'string',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/verify', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/verify");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"string"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/verify", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /tenants/verify

Check the validity of a tenant token

Verifies the signature of the token and the presence of the following claims:

Parameters

Name In Type Required Description
Authorization header string(Bearer [token]) true The tenant token in base64-encoded form.

Example responses

The token is valid. A tenant descriptor is returned.

{
  "id": "507f191e810c19729de860ea",
  "name": "Acme"
}

500 Response

{
  "error": "tenant_token is invalid"
}

Responses

Status Meaning Description Schema
200 OK The token is valid. A tenant descriptor is returned. Tenant
400 Bad Request Missing or malformed request parameters. None
401 Unauthorized Verification failed. None
500 Internal Server Error Unexpected error. Error

List Tenants

Code samples

# You can also use wget
curl -X GET http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants \
  -H 'Accept: application/json'

GET http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants HTTP/1.1
Host: mender-tenantadm:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /tenants

List known tenants

Returns a paged collection of existing tenants. Supports finding tenants by an associated user's username.

Parameters

Name In Type Required Description
username query string false Username filter. Selects the tenant associated with the given user.
q query string false Tenant filter. Matches if the tenant ID is equal to this string, or tenant's name or tenant's admin username contain this string.
page query number(integer) false Starting page.
per_page query number(integer) false Maximum number of results per page.

Detailed descriptions

username: Username filter. Selects the tenant associated with the given user.

q: Tenant filter. Matches if the tenant ID is equal to this string, or tenant's name or tenant's admin username contain this string.

Example responses

Successful response.

[
  {
    "id": "507f191e810c19729de860ea",
    "name": "Acme",
    "plan": "os"
  },
  {
    "id": "507f1f77bcf86cd799439011",
    "name": "Foo Inc.",
    "plan": "professional"
  }
]

400 Response

{
  "error": "tenant_token is invalid"
}

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
400 Bad Request Invalid parameters. See error message for details. Error
500 Internal Server Error Internal server error. Error

Response Schema

Status Code 200

ListOfTenants

Name Type Required Restrictions Description
ListOfTenants [Tenant] false [Tenant descriptor.]
» id string false Autogenerated tenant ID.
» name string false Name of the tenant's organization.
» tenant_token string false Currently used tenant token.
» status string false Status of the tenant account.
» plan string false Plan assigned to the tenant account.
» api_limits TenantApiLimits false API usage quota and burst limit definitions for a tenant - per API type.
»» management ApiLimits false Usage quota and burst limit definitions for an API type.
»»» bursts [ApiBurst] false Collection of api burst limit definitions over specified API resources.
»»»» action string false HTTP verb.
»»»» uri string false URI of the resource subject to the limit.
»»»» min_interval_sec integer false Minimum allowed interval, in seconds, between subsequent calls to 'action' on 'uri' (10 = one call every 10 seconds, etc.)
»»» quota ApiQuota false API usage quota definition.
»»»» max_calls integer false Maximum allowed number of calls within 'interval'. A value of 0 means 'no limit'.
»»»» interval_sec integer false Interval definition, in seconds (60 = 1 minute, 3600 = 1 hour, etc.).
»» devices ApiLimits false Usage quota and burst limit definitions for an API type.

Enumerated Values

Property Value
status active
status suspended
plan os
plan enterprise
plan professional
plan

Response Headers

Status Header Type Format Description
200 Link string Standard header, used for page navigation.

Supported relation types are 'first', 'next' and 'prev'. |

Show Tenant

Code samples

# You can also use wget
curl -X GET http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id} \
  -H 'Accept: application/json'

GET http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id} HTTP/1.1
Host: mender-tenantadm:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /tenants/{tenant_id}

Obtain information about selected tenant

Parameters

Name In Type Required Description
tenant_id path string true Tenant ID.

Example responses

200 Response

{
  "id": "507f191e810c19729de860ea",
  "name": "Acme",
  "tenant_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0ODcwNTU3MzUsImp0aSI6IjM5MTJiZDNmLWVjMTEtNDgwNy05MmE4LTBkOTVjMWFmYjU1NCIsImlzcyI6Ik1lbmRlciIsInN1YiI6ImQ0NTljOTFmZDkzMWFkOGM0ZDk4ZGIyZjdlZjU3NjYxNDI3NDJiZDMyMzM0ZjIyNjYyZTNiNjE5YmRiZTJhNTYifQ.iY2XuyuDOHW9ilPPeeHuwmz9A-6asDqdfy3mCjXuODns1SshbuH_XXFPa7s2PpXCMkhEHB82nLEjwcSO7gTIz1uqzjyGufVbXlOiZqPrCXUm4DKvhSgANiVKfkw_JvD1w-V0jyctBcrUifIhqhRlhXNAJh3c5XAMzxe2kwt9t3JW5bXiXroc64gXdv0gnX-o7YgdrFfau3rAaMFinKqHzACmeE5YhEVF9eQPJQ99U0PO6tVCcG39O-vtt51ClWh3BVeeQrHcr5eWQZWFMHThdeoRitLwvsN8wzrEKUoL9q9SlFnu4uGJkfOfTuiafgF1pJ-UBDYdBdV4sV9626PdHQ",
  "status": "active",
  "plan": "os",
  "api_limits": {
    "management": {
      "quota": {
        "max_calls": 100,
        "interval_sec": 60
      }
    },
    "devices": {
      "quota": {
        "max_calls": 1000,
        "interval_sec": 60
      },
      "bursts": [
        {
          "action": "PATCH",
          "uri": "/api/devices/v1/inventory/device/attributes",
          "min_interval_sec": 10
        },
        {
          "action": "POST",
          "uri": "/api/devices/v1/deployments/device/deployments/next",
          "min_interval_sec": 60
        }
      ]
    }
  }
}

Responses

Status Meaning Description Schema
200 OK A tenant descriptor is returned. Tenant
404 Not Found Tenant not found. Error
500 Internal Server Error Unexpected error. Error

Update Tenant

Code samples

# You can also use wget
curl -X PUT http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

PUT http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id} HTTP/1.1
Host: mender-tenantadm:8080
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "name": "Acme",
  "plan": "os",
  "trial": true,
  "trial_expiration": "2021-01-01T00:00:00Z",
  "api_limits": {
    "management": {
      "quota": {
        "max_calls": 100,
        "interval_sec": 60
      }
    },
    "devices": {
      "quota": {
        "max_calls": 1000,
        "interval_sec": 60
      },
      "bursts": [
        {
          "action": "PATCH",
          "uri": "/api/devices/v1/inventory/device/attributes",
          "min_interval_sec": 10
        },
        {
          "action": "POST",
          "uri": "/api/devices/v1/deployments/device/deployments/next",
          "min_interval_sec": 60
        }
      ]
    }
  }
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.put 'http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.put('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /tenants/{tenant_id}

Update tenant information

Update tenant information.

Body parameter

{
  "name": "Acme",
  "plan": "os",
  "trial": true,
  "trial_expiration": "2021-01-01T00:00:00Z",
  "api_limits": {
    "management": {
      "quota": {
        "max_calls": 100,
        "interval_sec": 60
      }
    },
    "devices": {
      "quota": {
        "max_calls": 1000,
        "interval_sec": 60
      },
      "bursts": [
        {
          "action": "PATCH",
          "uri": "/api/devices/v1/inventory/device/attributes",
          "min_interval_sec": 10
        },
        {
          "action": "POST",
          "uri": "/api/devices/v1/deployments/device/deployments/next",
          "min_interval_sec": 60
        }
      ]
    }
  }
}

Parameters

Name In Type Required Description
tenant_id path string true Tenant ID.
body body TenantUpdate true Updated tenant data.

Example responses

400 Response

{
  "error": "tenant_token is invalid"
}

Responses

Status Meaning Description Schema
204 No Content Tenant information updated. None
400 Bad Request The request body is malformed. Error
404 Not Found The tenant does not exist. Error
500 Internal Server Error Internal server error. Error

Create User

Code samples

# You can also use wget
curl -X POST http://mender-tenantadm:8080/api/internal/v1/tenantadm/users \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

POST http://mender-tenantadm:8080/api/internal/v1/tenantadm/users HTTP/1.1
Host: mender-tenantadm:8080
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "name": "user@acme.com",
  "id": "8c1a4f58-7919-4c42-a656-10da91c41fe9",
  "tenant_id": "754bf88b-d1e4-402e-a9e5-b076ca7791cc"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('http://mender-tenantadm:8080/api/internal/v1/tenantadm/users',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.post 'http://mender-tenantadm:8080/api/internal/v1/tenantadm/users',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.post('http://mender-tenantadm:8080/api/internal/v1/tenantadm/users', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-tenantadm:8080/api/internal/v1/tenantadm/users', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-tenantadm:8080/api/internal/v1/tenantadm/users");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-tenantadm:8080/api/internal/v1/tenantadm/users", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /users

Create user

Body parameter

{
  "name": "user@acme.com",
  "id": "8c1a4f58-7919-4c42-a656-10da91c41fe9",
  "tenant_id": "754bf88b-d1e4-402e-a9e5-b076ca7791cc"
}

Parameters

Name In Type Required Description
body body UserNew true New user data.

Example responses

400 Response

{
  "error": "tenant_token is invalid"
}

Responses

Status Meaning Description Schema
201 Created The user was successfully created. None
400 Bad Request The request body is malformed. Error
404 Not Found Tenant with given ID does not exist. Error
422 Unprocessable Entity User name or ID is duplicated. Error
500 Internal Server Error Internal server error. Error

Response Headers

Status Header Type Format Description
201 Location string URI for the newly created 'User' resource.

List Users

Code samples

# You can also use wget
curl -X GET http://mender-tenantadm:8080/api/internal/v1/tenantadm/users \
  -H 'Accept: application/json'

GET http://mender-tenantadm:8080/api/internal/v1/tenantadm/users HTTP/1.1
Host: mender-tenantadm:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-tenantadm:8080/api/internal/v1/tenantadm/users',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-tenantadm:8080/api/internal/v1/tenantadm/users',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-tenantadm:8080/api/internal/v1/tenantadm/users', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-tenantadm:8080/api/internal/v1/tenantadm/users', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-tenantadm:8080/api/internal/v1/tenantadm/users");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-tenantadm:8080/api/internal/v1/tenantadm/users", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /users

List known users

Returns a paged collection of existing users. Supports filtering by all internal user fields.

Parameters

Name In Type Required Description
name query string false Username filter. Selects the user with the given email
tenant_id query string false Tenant id filter. Selects the user with the given tenant id.
id query string false Tenant id filter. Selects the user with the given user id.
login query string false Filter by alternative login schemes (e.g. OAuth). The parameter
page query number(integer) false Starting page.
per_page query number(integer) false Maximum number of results per page.

Detailed descriptions

name: Username filter. Selects the user with the given email

tenant_id: Tenant id filter. Selects the user with the given tenant id.

id: Tenant id filter. Selects the user with the given user id.

login: Filter by alternative login schemes (e.g. OAuth). The parameter can be provided multiple times and assumes key/value pairs on the form "key:value"

Example responses

200 Response

[
  {
    "id": "d8f0423b-2297-47d7-a6df-00bf6ce07b17",
    "tenant_id": "507f191e810c19729de860ea",
    "name": "bob@bldr.org",
    "plan": "os"
  },
  {
    "id": "d8f0423b-2297-47d7-a6df-00bf6ce07b17",
    "tenant_id": "507f191e810c19729de860ea",
    "name": "Foo Inc.",
    "plan": "professional",
    "login": {
      "github": "1234"
    }
  }
]

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
400 Bad Request Invalid parameters. See error message for details. Error
500 Internal Server Error Internal server error. Error

Response Schema

Status Code 200

ListOfUsers

Name Type Required Restrictions Description
ListOfUsers [User] false [User descriptor.]
» name string true User name (email).
» id string true User ID.
» tenant_id string true Tenant ID.
» plan string false User payment plan.
» login object false

Response Headers

Status Header Type Format Description
200 Link string Standard header, used for page navigation.

Supported relation types are 'first', 'next' and 'prev'. |

Update User

Code samples

# You can also use wget
curl -X PUT http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

PUT http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id} HTTP/1.1
Host: mender-tenantadm:8080
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "name": "new_email@acme.com"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id}',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.put 'http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.put('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /tenants/{tenant_id}/users/{user_id}

Update user information

Body parameter

{
  "name": "new_email@acme.com"
}

Parameters

Name In Type Required Description
tenant_id path string true Tenant ID.
user_id path string true User ID.
body body UserUpdate true Updated user data.

Example responses

400 Response

{
  "error": "tenant_token is invalid"
}

Responses

Status Meaning Description Schema
204 No Content User information updated. None
400 Bad Request The request body is malformed. Error
404 Not Found The user or tenant does not exist. Error
422 Unprocessable Entity The user name is duplicated. Error
500 Internal Server Error Internal server error. Error

Delete User

Code samples

# You can also use wget
curl -X DELETE http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id} \
  -H 'Accept: application/json'

DELETE http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id} HTTP/1.1
Host: mender-tenantadm:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id}',
{
  method: 'DELETE',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.delete 'http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.delete('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('DELETE','http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("DELETE");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("DELETE", "http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{tenant_id}/users/{user_id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

DELETE /tenants/{tenant_id}/users/{user_id}

Remove user from the system

Parameters

Name In Type Required Description
tenant_id path string true Tenant ID.
user_id path string true User ID.

Example responses

500 Response

{
  "error": "tenant_token is invalid"
}

Responses

Status Meaning Description Schema
204 No Content User removed. None
500 Internal Server Error Internal server error. Error

Set Account Status

Code samples

# You can also use wget
curl -X PUT http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{id}/status \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

PUT http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{id}/status HTTP/1.1
Host: mender-tenantadm:8080
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "status": "suspended"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{id}/status',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.put 'http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{id}/status',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.put('http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{id}/status', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('PUT','http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{id}/status', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{id}/status");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PUT", "http://mender-tenantadm:8080/api/internal/v1/tenantadm/tenants/{id}/status", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

PUT /tenants/{id}/status

Suspend/unsuspend tenant's account.

Changes the given tenant's suspension status. Valid statuses are:

Body parameter

{
  "status": "suspended"
}

Parameters

Name In Type Required Description
id path string true Tenant ID.
body body Status true Target suspension status

Example responses

400 Response

{
  "error": "tenant_token is invalid"
}

Responses

Status Meaning Description Schema
200 OK The tenant was successfully (un)suspended. None
400 Bad Request The request body is malformed. See error for details. Error
404 Not Found The tenant was not found. Error
500 Internal Server Error Internal server error. Error

Schemas

Tenant

{
  "id": "507f191e810c19729de860ea",
  "name": "Acme",
  "tenant_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0ODcwNTU3MzUsImp0aSI6IjM5MTJiZDNmLWVjMTEtNDgwNy05MmE4LTBkOTVjMWFmYjU1NCIsImlzcyI6Ik1lbmRlciIsInN1YiI6ImQ0NTljOTFmZDkzMWFkOGM0ZDk4ZGIyZjdlZjU3NjYxNDI3NDJiZDMyMzM0ZjIyNjYyZTNiNjE5YmRiZTJhNTYifQ.iY2XuyuDOHW9ilPPeeHuwmz9A-6asDqdfy3mCjXuODns1SshbuH_XXFPa7s2PpXCMkhEHB82nLEjwcSO7gTIz1uqzjyGufVbXlOiZqPrCXUm4DKvhSgANiVKfkw_JvD1w-V0jyctBcrUifIhqhRlhXNAJh3c5XAMzxe2kwt9t3JW5bXiXroc64gXdv0gnX-o7YgdrFfau3rAaMFinKqHzACmeE5YhEVF9eQPJQ99U0PO6tVCcG39O-vtt51ClWh3BVeeQrHcr5eWQZWFMHThdeoRitLwvsN8wzrEKUoL9q9SlFnu4uGJkfOfTuiafgF1pJ-UBDYdBdV4sV9626PdHQ",
  "status": "active",
  "plan": "os",
  "api_limits": {
    "management": {
      "quota": {
        "max_calls": 100,
        "interval_sec": 60
      }
    },
    "devices": {
      "quota": {
        "max_calls": 1000,
        "interval_sec": 60
      },
      "bursts": [
        {
          "action": "PATCH",
          "uri": "/api/devices/v1/inventory/device/attributes",
          "min_interval_sec": 10
        },
        {
          "action": "POST",
          "uri": "/api/devices/v1/deployments/device/deployments/next",
          "min_interval_sec": 60
        }
      ]
    }
  }
}

Tenant descriptor.

Properties

Name Type Required Description
id string false Autogenerated tenant ID.
name string false Name of the tenant's organization.
tenant_token string false Currently used tenant token.
status string false Status of the tenant account.
plan string false Plan assigned to the tenant account.
api_limits TenantApiLimits false API usage quota and burst limit definitions for a tenant - per API type.

Enumerated Values

Property Value
status active
status suspended
plan os
plan enterprise
plan professional
plan

User

{
  "name": "user@acme.com",
  "id": "8c1a4f58-7919-4c42-a656-10da91c41fe9",
  "tenant_id": "754bf88b-d1e4-402e-a9e5-b076ca7791cc"
}

User descriptor.

Properties

Name Type Required Description
name string true User name (email).
id string true User ID.
tenant_id string true Tenant ID.
plan string false User payment plan.
login object false

UserNew

{
  "name": "user@acme.com",
  "id": "8c1a4f58-7919-4c42-a656-10da91c41fe9",
  "tenant_id": "754bf88b-d1e4-402e-a9e5-b076ca7791cc"
}

New user descriptor.

Properties

Name Type Required Description
name string true A unique user name.
id string true User ID.
tenant_id string true Tenant ID.
login object false

UserUpdate

{
  "name": "new_email@acme.com"
}

Update user information.

Properties

Name Type Required Description
name string true A unique user name.

TenantUpdate

{
  "name": "Acme",
  "plan": "os",
  "trial": true,
  "trial_expiration": "2021-01-01T00:00:00Z",
  "api_limits": {
    "management": {
      "quota": {
        "max_calls": 100,
        "interval_sec": 60
      }
    },
    "devices": {
      "quota": {
        "max_calls": 1000,
        "interval_sec": 60
      },
      "bursts": [
        {
          "action": "PATCH",
          "uri": "/api/devices/v1/inventory/device/attributes",
          "min_interval_sec": 10
        },
        {
          "action": "POST",
          "uri": "/api/devices/v1/deployments/device/deployments/next",
          "min_interval_sec": 60
        }
      ]
    }
  }
}

Update tenant information.

Properties

Name Type Required Description
name string false Name of the tenant's organization.
plan string false Plan assigned to the tenant account.
api_limits TenantApiLimits false API usage quota and burst limit definitions for a tenant - per API type.
trial boolean false True if the tenant is in trial period.
trial_expiration string false End date and time of the trial period, in ISO8601 format.

Enumerated Values

Property Value
plan os
plan enterprise
plan professional
plan

Status

{
  "status": "suspended"
}

Suspension status of a tenant account.

Properties

Name Type Required Description
status string true

Enumerated Values

Property Value
status active
status suspended

ApiBurst

{
  "action": "PATCH",
  "uri": "/api/devices/v1/inventory/device/attributes",
  "min_interval_sec": 10
}

API burst limit definition.

Properties

Name Type Required Description
action string false HTTP verb.
uri string false URI of the resource subject to the limit.
min_interval_sec integer false Minimum allowed interval, in seconds, between subsequent calls to 'action' on 'uri' (10 = one call every 10 seconds, etc.)

ApiQuota

{
  "max_calls": 100,
  "interval_sec": 3600
}

API usage quota definition.

Properties

Name Type Required Description
max_calls integer false Maximum allowed number of calls within 'interval'. A value of 0 means 'no limit'.
interval_sec integer false Interval definition, in seconds (60 = 1 minute, 3600 = 1 hour, etc.).

ApiLimits

{
  "bursts": [
    {
      "action": "PATCH",
      "uri": "/api/devices/v1/inventory/device/attributes",
      "min_interval_sec": 10
    },
    {
      "action": "POST",
      "uri": "/api/devices/v1/deployments/device/deployments/next",
      "min_interval_sec": 60
    }
  ],
  "quota": {
    "max_calls": 100,
    "interval_sec": 60
  }
}

Usage quota and burst limit definitions for an API type.

Properties

Name Type Required Description
bursts [ApiBurst] false Collection of api burst limit definitions over specified API resources.
quota ApiQuota false API usage quota definition.

TenantApiLimits

{
  "management": {
    "quota": {
      "max_calls": 100,
      "interval_sec": 60
    }
  },
  "devices": {
    "quota": {
      "max_calls": 1000,
      "interval_sec": 60
    },
    "bursts": [
      {
        "action": "PATCH",
        "uri": "/api/devices/v1/inventory/device/attributes",
        "min_interval_sec": 10
      },
      {
        "action": "POST",
        "uri": "/api/devices/v1/deployments/device/deployments/next",
        "min_interval_sec": 60
      }
    ]
  }
}

API usage quota and burst limit definitions for a tenant - per API type.

Properties

Name Type Required Description
management ApiLimits false Usage quota and burst limit definitions for an API type.
devices ApiLimits false Usage quota and burst limit definitions for an API type.

Error

{
  "error": "tenant_token is invalid"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.

Workflows

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

An API for workflow management. Intended for use by other services.

Base URLs:

Check Liveliness

Code samples

# You can also use wget
curl -X GET http://mender-workflows-server:8080/status \
  -H 'Accept: application/json'

GET http://mender-workflows-server:8080/status HTTP/1.1
Host: mender-workflows-server:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-workflows-server:8080/status',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-workflows-server:8080/status',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-workflows-server:8080/status', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-workflows-server:8080/status', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-workflows-server:8080/status");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-workflows-server:8080/status", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /status

Check if service API is alive and serving requests

Example responses

Successful response.

{
  "status": "ok"
}

500 Response

{
  "error": "failed: JSON payload is empty"
}

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
500 Internal Server Error Internal Server Error. Error

Response Schema

Status Code 200

Name Type Required Restrictions Description
» id string false
» name string false

Check Health

Code samples

# You can also use wget
curl -X GET http://mender-workflows-server:8080/health \
  -H 'Accept: application/json'

GET http://mender-workflows-server:8080/health HTTP/1.1
Host: mender-workflows-server:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-workflows-server:8080/health',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-workflows-server:8080/health',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-workflows-server:8080/health', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-workflows-server:8080/health', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-workflows-server:8080/health");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-workflows-server:8080/health", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /health

Check if service and all operational dependencies are healthy.

Example responses

500 Response

{
  "error": "failed: JSON payload is empty"
}

Responses

Status Meaning Description Schema
204 No Content Service is healthy. None
500 Internal Server Error Internal Server Error. Error
502 Bad Gateway Service is temporarily unavailable (currently unhealthy). Error

Start Workflow

Code samples

# You can also use wget
curl -X POST http://mender-workflows-server:8080/api/v1/workflow/{name} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

POST http://mender-workflows-server:8080/api/v1/workflow/{name} HTTP/1.1
Host: mender-workflows-server:8080
Content-Type: application/json
Accept: application/json

const inputBody = '[
  {
    "name": "key",
    "value": "parameter"
  }
]';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('http://mender-workflows-server:8080/api/v1/workflow/{name}',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.post 'http://mender-workflows-server:8080/api/v1/workflow/{name}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.post('http://mender-workflows-server:8080/api/v1/workflow/{name}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-workflows-server:8080/api/v1/workflow/{name}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-workflows-server:8080/api/v1/workflow/{name}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-workflows-server:8080/api/v1/workflow/{name}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /api/v1/workflow/{name}

Start a new workflow

Starts a new workflow given by the name path-parameter.

Body parameter

[
  {
    "name": "key",
    "value": "parameter"
  }
]

Parameters

Name In Type Required Description
name path string true Workflow identifier.
body body InputParameter true Contains the definition of the job to be started.

Example responses

201 Response

{
  "id": "string",
  "name": "string"
}

Responses

Status Meaning Description Schema
201 Created Workflow created successfully Inline
400 Bad Request Invalid Request. Error
404 Not Found Not Found. Error

Response Schema

Status Code 201

Name Type Required Restrictions Description
» id string false
» name string false

Workflow Status

Code samples

# You can also use wget
curl -X GET http://mender-workflows-server:8080/api/v1/workflow/{name}/{id} \
  -H 'Accept: application/json'

GET http://mender-workflows-server:8080/api/v1/workflow/{name}/{id} HTTP/1.1
Host: mender-workflows-server:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-workflows-server:8080/api/v1/workflow/{name}/{id}',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-workflows-server:8080/api/v1/workflow/{name}/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-workflows-server:8080/api/v1/workflow/{name}/{id}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-workflows-server:8080/api/v1/workflow/{name}/{id}', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-workflows-server:8080/api/v1/workflow/{name}/{id}");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-workflows-server:8080/api/v1/workflow/{name}/{id}", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /api/v1/workflow/{name}/{id}

Gets the workflow status for the given id.

Gets the workflow status for the given workflow name and id provided by the path parameters.

Parameters

Name In Type Required Description
name path string true Workflow identifier.
id path string true Job identifier

Example responses

200 Response

{
  "id": "string",
  "workflowName": "string",
  "inputParameters": [
    {
      "name": "key",
      "value": "parameter"
    }
  ],
  "status": "string",
  "results": [
    {
      "success": true,
      "cli": {
        "command": [
          "string"
        ],
        "output": "string",
        "error": "string",
        "exitCode": 0
      },
      "request": {
        "statusCode": 0,
        "body": "string"
      },
      "response": {
        "uri": "string",
        "method": "string",
        "headers": [
          "string"
        ],
        "body": "string"
      }
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK Successful query JobStatus
404 Not Found Not Found. Error

List Workflows

Code samples

# You can also use wget
curl -X GET http://mender-workflows-server:8080/api/v1/metadata/workflows \
  -H 'Accept: application/json'

GET http://mender-workflows-server:8080/api/v1/metadata/workflows HTTP/1.1
Host: mender-workflows-server:8080
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('http://mender-workflows-server:8080/api/v1/metadata/workflows',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'http://mender-workflows-server:8080/api/v1/metadata/workflows',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('http://mender-workflows-server:8080/api/v1/metadata/workflows', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','http://mender-workflows-server:8080/api/v1/metadata/workflows', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-workflows-server:8080/api/v1/metadata/workflows");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-workflows-server:8080/api/v1/metadata/workflows", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /api/v1/metadata/workflows

Get all workflow definitions

Example responses

200 Response

[
  {
    "name": "string",
    "description": "string",
    "version": 0,
    "schemaversion": 0,
    "tasks": [
      {
        "name": "string",
        "type": "string",
        "cli": {
          "command": [
            "string"
          ],
          "executionTimeOut": 0
        },
        "http": {
          "uri": "string",
          "method": "string",
          "contentType": "string",
          "body": "string",
          "headers": {},
          "statusCodes": [
            0
          ],
          "connectionTimeOut": 0,
          "readTimeOut": 0
        }
      }
    ],
    "inputParameters": [
      "string"
    ]
  }
]

Responses

Status Meaning Description Schema
200 OK Successful response Inline

Response Schema

Status Code 200

Name Type Required Restrictions Description
anonymous [Workflow] false
» name string true
» description string false
» version integer true
» schemaversion integer false
» tasks [Task] true [Task definition]
»» name string true
»» type string true
»» cli CLIParams false CLI parameters
»»» command [string] false
»»» executionTimeOut integer false
»» http HTTPParams false HTTP parameters
»»» uri string false
»»» method string false
»»» contentType string false
»»» body string false
»»» headers object false
»»» statusCodes [integer] false
»»» connectionTimeOut integer false
»»» readTimeOut integer false
» inputParameters [string] false

Register Workflow

Code samples

# You can also use wget
curl -X POST http://mender-workflows-server:8080/api/v1/metadata/workflows \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

POST http://mender-workflows-server:8080/api/v1/metadata/workflows HTTP/1.1
Host: mender-workflows-server:8080
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "name": "string",
  "description": "string",
  "version": 0,
  "schemaversion": 0,
  "tasks": [
    {
      "name": "string",
      "type": "string",
      "cli": {
        "command": [
          "string"
        ],
        "executionTimeOut": 0
      },
      "http": {
        "uri": "string",
        "method": "string",
        "contentType": "string",
        "body": "string",
        "headers": {},
        "statusCodes": [
          0
        ],
        "connectionTimeOut": 0,
        "readTimeOut": 0
      }
    }
  ],
  "inputParameters": [
    "string"
  ]
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('http://mender-workflows-server:8080/api/v1/metadata/workflows',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}

result = RestClient.post 'http://mender-workflows-server:8080/api/v1/metadata/workflows',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

r = requests.post('http://mender-workflows-server:8080/api/v1/metadata/workflows', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('POST','http://mender-workflows-server:8080/api/v1/metadata/workflows', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("http://mender-workflows-server:8080/api/v1/metadata/workflows");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Content-Type": []string{"application/json"},
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "http://mender-workflows-server:8080/api/v1/metadata/workflows", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

POST /api/v1/metadata/workflows

Register a new workflow

Body parameter

{
  "name": "string",
  "description": "string",
  "version": 0,
  "schemaversion": 0,
  "tasks": [
    {
      "name": "string",
      "type": "string",
      "cli": {
        "command": [
          "string"
        ],
        "executionTimeOut": 0
      },
      "http": {
        "uri": "string",
        "method": "string",
        "contentType": "string",
        "body": "string",
        "headers": {},
        "statusCodes": [
          0
        ],
        "connectionTimeOut": 0,
        "readTimeOut": 0
      }
    }
  ],
  "inputParameters": [
    "string"
  ]
}

Parameters

Name In Type Required Description
body body Workflow true Workflow definition.

Example responses

400 Response

{
  "error": "failed: JSON payload is empty"
}

Responses

Status Meaning Description Schema
201 Created Successful response. None
400 Bad Request Invalid Request. Error
409 Conflict Conflict, record already exists. Error

Schemas

Error

{
  "error": "failed: JSON payload is empty"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.

CLIParams

{
  "command": [
    "string"
  ],
  "executionTimeOut": 0
}

CLI parameters

Properties

Name Type Required Description
command [string] false
executionTimeOut integer false

HTTPParams

{
  "uri": "string",
  "method": "string",
  "contentType": "string",
  "body": "string",
  "headers": {},
  "statusCodes": [
    0
  ],
  "connectionTimeOut": 0,
  "readTimeOut": 0
}

HTTP parameters

Properties

Name Type Required Description
uri string false
method string false
contentType string false
body string false
headers object false
statusCodes [integer] false
connectionTimeOut integer false
readTimeOut integer false

Task

{
  "name": "string",
  "type": "string",
  "cli": {
    "command": [
      "string"
    ],
    "executionTimeOut": 0
  },
  "http": {
    "uri": "string",
    "method": "string",
    "contentType": "string",
    "body": "string",
    "headers": {},
    "statusCodes": [
      0
    ],
    "connectionTimeOut": 0,
    "readTimeOut": 0
  }
}

Task definition

Properties

Name Type Required Description
name string true
type string true
cli CLIParams false CLI parameters
http HTTPParams false HTTP parameters

Workflow

{
  "name": "string",
  "description": "string",
  "version": 0,
  "schemaversion": 0,
  "tasks": [
    {
      "name": "string",
      "type": "string",
      "cli": {
        "command": [
          "string"
        ],
        "executionTimeOut": 0
      },
      "http": {
        "uri": "string",
        "method": "string",
        "contentType": "string",
        "body": "string",
        "headers": {},
        "statusCodes": [
          0
        ],
        "connectionTimeOut": 0,
        "readTimeOut": 0
      }
    }
  ],
  "inputParameters": [
    "string"
  ]
}

Properties

Name Type Required Description
name string true
description string false
version integer true
schemaversion integer false
tasks [Task] true [Task definition]
inputParameters [string] false

InputParameter

{
  "name": "key",
  "value": "parameter"
}

Properties

Name Type Required Description
name string true
value string true

TaskResultCLI

{
  "command": [
    "string"
  ],
  "output": "string",
  "error": "string",
  "exitCode": 0
}

Properties

Name Type Required Description
command [string] false
output string false
error string false
exitCode integer false

TaskResultHTTPRequest

{
  "statusCode": 0,
  "body": "string"
}

Properties

Name Type Required Description
statusCode integer false
body string false

TaskResultHTTPResponse

{
  "uri": "string",
  "method": "string",
  "headers": [
    "string"
  ],
  "body": "string"
}

Properties

Name Type Required Description
uri string false
method string false
headers [string] false
body string false

TaskResult

{
  "success": true,
  "cli": {
    "command": [
      "string"
    ],
    "output": "string",
    "error": "string",
    "exitCode": 0
  },
  "request": {
    "statusCode": 0,
    "body": "string"
  },
  "response": {
    "uri": "string",
    "method": "string",
    "headers": [
      "string"
    ],
    "body": "string"
  }
}

Properties

Name Type Required Description
success boolean false
cli TaskResultCLI false
request TaskResultHTTPRequest false
response TaskResultHTTPResponse false

JobStatus

{
  "id": "string",
  "workflowName": "string",
  "inputParameters": [
    {
      "name": "key",
      "value": "parameter"
    }
  ],
  "status": "string",
  "results": [
    {
      "success": true,
      "cli": {
        "command": [
          "string"
        ],
        "output": "string",
        "error": "string",
        "exitCode": 0
      },
      "request": {
        "statusCode": 0,
        "body": "string"
      },
      "response": {
        "uri": "string",
        "method": "string",
        "headers": [
          "string"
        ],
        "body": "string"
      }
    }
  ]
}

Properties

Name Type Required Description
id string false
workflowName string false
inputParameters [InputParameter] false
status string false
results [TaskResult] false