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

Replace Attributes

Code samples

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

PUT 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: '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/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.put('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('PUT','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("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/inventory/device/attributes", data)
    req.Header = headers

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

PUT /device/attributes

Replace the set of attributes for a device

Replaces the attribute set for the authenticated device with the provided one. The device ID is retrieved from the authorization header.

This method replaces all the attributes with the new set:

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 Array of log entries of a deployment
» timestamp string(date-time) true
» level string true
» message string true

Device connect

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

Device facing API for managing persistent device connections.

Base URLs:

Email: Mender Support Web: Mender Support License: Apache 2.0

Connect

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/devices/v1/deviceconnect/connect \
  -H 'Accept: application/json' \
  -H 'Connection: Upgrade' \
  -H 'Upgrade: websocket' \
  -H 'Sec-Websocket-Key: string' \
  -H 'Sec-Websocket-Version: 13' \
  -H 'Authorization: Bearer {access-token}'

GET https://hosted.mender.io/api/devices/v1/deviceconnect/connect HTTP/1.1
Host: hosted.mender.io
Accept: application/json
Connection: Upgrade
Upgrade: websocket
Sec-Websocket-Key: string
Sec-Websocket-Version: 13


const headers = {
  'Accept':'application/json',
  'Connection':'Upgrade',
  'Upgrade':'websocket',
  'Sec-Websocket-Key':'string',
  'Sec-Websocket-Version':'13',
  'Authorization':'Bearer {access-token}'
};

fetch('https://hosted.mender.io/api/devices/v1/deviceconnect/connect',
{
  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',
  'Connection' => 'Upgrade',
  'Upgrade' => 'websocket',
  'Sec-Websocket-Key' => 'string',
  'Sec-Websocket-Version' => '13',
  'Authorization' => 'Bearer {access-token}'
}

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

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Connection': 'Upgrade',
  'Upgrade': 'websocket',
  'Sec-Websocket-Key': 'string',
  'Sec-Websocket-Version': '13',
  'Authorization': 'Bearer {access-token}'
}

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

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Connection' => 'Upgrade',
    'Upgrade' => 'websocket',
    'Sec-Websocket-Key' => 'string',
    'Sec-Websocket-Version' => '13',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

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

try {
    $response = $client->request('GET','https://hosted.mender.io/api/devices/v1/deviceconnect/connect', 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/deviceconnect/connect");
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"},
        "Connection": []string{"Upgrade"},
        "Upgrade": []string{"websocket"},
        "Sec-Websocket-Key": []string{"string"},
        "Sec-Websocket-Version": []string{"13"},
        "Authorization": []string{"Bearer {access-token}"},
    }

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

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

GET /connect

Connect the device and make it available to the server.

Calling /connect will upgrade the connection to a persistent websocket connection and make the device available to the management API. The device must provide DeviceJWT identity either as Authorization (Bearer) header or as a cookie named 'JWT'.

Parameters

Name In Type Required Description
Connection header string false Standard websocket request header.
Upgrade header string(base64) false Standard websocket request header.
Sec-Websocket-Key header string(base64) false Standard websocket request header.
Sec-Websocket-Version header integer false Standard websocket request header.

Enumerated Values

Parameter Value
Connection Upgrade
Upgrade websocket
Sec-Websocket-Version 13

Example responses

400 Response

{
  "error": "bad request parameters",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

500 Response

{
  "error": "internal error",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

Responses

Status Meaning Description Schema
101 Switching Protocols Successful response - change to websocket protocol. None
400 Bad Request Invalid Request. Error
500 Internal Server Error Internal Server Error. Error

Response Headers

Status Header Type Format Description
101 Sec-Websocket-Accept string base64 Standard websocket upgrade response header.
101 Upgrade string

Schemas

Error

{
  "error": "<error description>",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID passed with the request X-MEN-RequestID header or generated by the server.

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.

Search Devices

Code samples

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

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

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

fetch('https://hosted.mender.io/api/management/v2/devauth/devices/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/devauth/devices/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/devauth/devices/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/devauth/devices/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/devauth/devices/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/devauth/devices/search", data)
    req.Header = headers

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

POST /devices/search

Query for devices. Returns a list of matching devices with AuthSets sorted by age.

Body parameter

{
  "status": "pending",
  "id": [
    "string"
  ]
}

Parameters

Name In Type Required Description
page query integer false Results page number
per_page query integer false Maximum number of results per page.
body body object true Device status filter.
» status body string false Device status filter. Can be an array for querying devices from multiple device statuses.
» id body [string] false Device ID filter. Can be a string for querying for a single device.

Detailed descriptions

body: Device status filter. All properties can be either a single string or an array of strings.

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 Successful response Inline
400 Bad Request Missing/malformed request params. Error
500 Internal Server Error Unexpected error Error

Response Schema

Status Code 200

Array of devices

Name Type Required Restrictions Description
anonymous [Device] false Array of devices
» 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 Pagination link header, we support 'first', 'next', and 'prev'.

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:

Get filterable attributes

Code samples

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

GET https://hosted.mender.io/api/management/v2/inventory/filters/attributes 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/attributes',
{
  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/attributes',
  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/attributes', 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/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/management/v2/inventory/filters/attributes");
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/attributes", data)
    req.Header = headers

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

GET /filters/attributes

Get the list of filterable inventory attributes

Returns a list of filterable inventory attributes.

The list is sorted in descending order by the count of occurrences of the attribute in the inventory database, then in ascending order by scope and name.

Example responses

200 Response

[
  {
    "attribute": "serial_no",
    "name": "inventory",
    "count": 10
  }
]

Responses

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

Response Schema

Status Code 200

List of filter attributes

Name Type Required Restrictions Description
List of filter attributes [FilterAttribute] false [Filterable attribute]
» scope string true Scope of the attribute.
» name string true Name of the attribute.
» count integer true Number of occurrences of the attribute in the database.

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).

FilterAttribute

{
  "attribute": "serial_no",
  "name": "inventory",
  "count": 10
}

Filterable attribute

Properties

Name Type Required Description
scope string true Scope of the attribute.
name string true Name of the attribute.
count integer true Number of occurrences of the attribute in the database.

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
401 Unauthorized Unauthorized. None
500 Internal Server Error Internal Server Error. Error

Response Schema

Status Code 200

Name Type Required Restrictions Description
anonymous [Deployment] false
» id string true Deployment identifier
» name string true Name of the deployment
» artifact_name string true Name of the artifact to deploy
» created string(date-time) true Deployment's creation date and time
» finished string(date-time) false Deployment's completion date and time
» status string true Status of the deployment
» device_count integer true Number of devices the deployment acted upon
» artifacts [string] false An array of artifact's identifiers.
» 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'.
200 X-Total-Count int Total number of deployments matching query.

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
401 Unauthorized Unauthorized. None
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.

Create Deployment for a Group of Devices

Code samples

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

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

const inputBody = '{
  "name": "production",
  "artifact_name": "Application 0.0.1",
  "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/group/{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',
  'Authorization' => 'API_KEY'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v1/deployments/deployments/group/{name}',
  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/group/{name}', 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/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/deployments/deployments/group/{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"},
        "Authorization": []string{"API_KEY"},
    }

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

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

POST /deployments/group/{name}

Create a deployment for a group of devices

Deploy software to devices belonging to the specified group.

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",
  "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
name path string true Device group name.
body body NewDeploymentForGroup 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
401 Unauthorized Unauthorized. None
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
401 Unauthorized Unauthorized. None
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
401 Unauthorized Unauthorized. None
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
401 Unauthorized Unauthorized. None
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
401 Unauthorized Unauthorized. None
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
401 Unauthorized Unauthorized. None
404 Not Found Not Found. Error
500 Internal Server Error Internal Server Error. Error

Response Schema

Status Code 200

List of device IDs

Name Type Required Restrictions Description

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
401 Unauthorized Unauthorized. 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
401 Unauthorized Unauthorized. 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"
          ]
        },
        "clears_artifact_provides": [
          "rootfs-image.*"
        ],
        "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"
          ]
        },
        "clears_artifact_provides": [
          "rootfs-image.*"
        ],
        "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"
          ]
        },
        "clears_artifact_provides": [
          "rootfs-image.*"
        ],
        "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
401 Unauthorized Unauthorized. None
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"
      ]
    },
    "clears_artifact_provides": [
      "rootfs-image.*"
    ],
    "size": 36891648,
    "modified": "2016-03-11T13:03:17.063493443Z"
  }
]

Responses

Status Meaning Description Schema
200 OK OK Inline
401 Unauthorized Unauthorized. None
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 An array of compatible device types.
» 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
» clears_artifact_provides [string] false List of Clear Artifact provides.
» 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
401 Unauthorized Unauthorized. None
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
401 Unauthorized Unauthorized. None
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"
    ]
  },
  "clears_artifact_provides": [
    "rootfs-image.*"
  ],
  "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
401 Unauthorized Unauthorized. None
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
401 Unauthorized Unauthorized. None
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
401 Unauthorized Unauthorized. 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
401 Unauthorized Unauthorized. None
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
401 Unauthorized Unauthorized. None
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 Name of the deployment
artifact_name string true Name of the artifact to deploy
devices [string] false An array of devices' identifiers.
all_devices boolean false When set, the deployment will be created for all
currently accepted devices.
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

NewDeploymentForGroup

{
  "name": "production",
  "artifact_name": "Application 0.0.1",
  "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
name string true Name of the deployment
artifact_name string true Name of the artifact to deploy

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
id string true Deployment identifier
name string true Name of the deployment
artifact_name string true Name of the artifact to deploy
created string(date-time) true Deployment's creation date and time
finished string(date-time) false Deployment's completion date and time
status string true Status of the deployment
device_count integer true Number of devices the deployment acted upon
artifacts [string] false An array of artifact's identifiers.
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"
    ]
  },
  "clears_artifact_provides": [
    "rootfs-image.*"
  ],
  "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 An array of compatible device types.
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
clears_artifact_provides [string] false List of Clear Artifact provides.
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"
          ]
        },
        "clears_artifact_provides": [
          "rootfs-image.*"
        ],
        "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"
          ]
        },
        "clears_artifact_provides": [
          "rootfs-image.*"
        ],
        "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"
        ]
      },
      "clears_artifact_provides": [
        "rootfs-image.*"
      ],
      "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"
        ]
      },
      "clears_artifact_provides": [
        "rootfs-image.*"
      ],
      "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:

Logout

Code samples

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

POST https://hosted.mender.io/api/management/v1/useradm/auth/logout 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/auth/logout',
{
  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/v1/useradm/auth/logout',
  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/v1/useradm/auth/logout', 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/v1/useradm/auth/logout', 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/logout");
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/v1/useradm/auth/logout", data)
    req.Header = headers

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

POST /auth/logout

Log out from Mender

Invalidates the JWT token of the current user.

Example responses

400 Response

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
202 Accepted Request has been accepted and the JWT token has been invalidated. None
400 Bad Request Bad request, see error message for details. Error
401 Unauthorized Unauthorized. Error
500 Internal Server Error Internal server error. Error

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

Verify Plan

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v1/useradm/auth/plan-verify \
  -H 'Accept: application/json' \
  -H 'X-Mender-Required-Minimal-Plan: string'

POST https://hosted.mender.io/api/management/v1/useradm/auth/plan-verify HTTP/1.1
Host: hosted.mender.io
Accept: application/json
X-Mender-Required-Minimal-Plan: string


const headers = {
  'Accept':'application/json',
  'X-Mender-Required-Minimal-Plan':'string'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/auth/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' => 'application/json',
  'X-Mender-Required-Minimal-Plan' => 'string'
}

result = RestClient.post 'https://hosted.mender.io/api/management/v1/useradm/auth/plan-verify',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'X-Mender-Required-Minimal-Plan': 'string'
}

r = requests.post('https://hosted.mender.io/api/management/v1/useradm/auth/plan-verify', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'X-Mender-Required-Minimal-Plan' => 'string',
);

$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/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("https://hosted.mender.io/api/management/v1/useradm/auth/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{"application/json"},
        "X-Mender-Required-Minimal-Plan": []string{"string"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://hosted.mender.io/api/management/v1/useradm/auth/plan-verify", data)
    req.Header = headers

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

POST /auth/plan-verify

Check if the user has given or superior pricing plan associated

Checks if user is in the given plan, or a superior one

Parameters

Name In Type Required Description
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

401 Response

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
202 Accepted The required minimal plan matches the user plan None
401 Unauthorized The user authentication failed Error
403 Forbidden The required minimal plan doesn't match the user plan Error
500 Internal Server Error Unexpected 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. *

Parameters

Name In Type Required Description
id query string false Limit result by user ID, can be repeated to include multiple users in the query.
email query string false Limit result by user email, can be repeated to include multiple users in the query.
created_after query integer false Filter users created after timestamp (UNIX timestamp).
created_before query integer false Filter users created before timestamp (UNIX timestamp).
updated_after query integer false Filter users updated after timestamp (UNIX timestamp).
updated_before query integer false Filter users updated before timestamp (UNIX timestamp).

Detailed descriptions

id: Limit result by user ID, can be repeated to include multiple users in the query.

email: Limit result by user email, can be repeated to include multiple users in the query.

created_after: Filter users created after timestamp (UNIX timestamp).

created_before: Filter users created before timestamp (UNIX timestamp).

updated_after: Filter users updated after timestamp (UNIX timestamp).

updated_before: Filter users updated before timestamp (UNIX timestamp).

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.
» login_ts string(date-time) false Timestamp of last successful login.

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. Set to "me" for the current user.

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. Set to "me" for the current user.
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

Get 2FA QR code

Code samples

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

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


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

fetch('https://hosted.mender.io/api/management/v1/useradm/2faqr',
{
  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 'https://hosted.mender.io/api/management/v1/useradm/2faqr',
  params: {
  }, headers: headers

p JSON.parse(result)

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

r = requests.get('https://hosted.mender.io/api/management/v1/useradm/2faqr', 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','https://hosted.mender.io/api/management/v1/useradm/2faqr', 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/2faqr");
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", "https://hosted.mender.io/api/management/v1/useradm/2faqr", data)
    req.Header = headers

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

GET /2faqr

Get 2FA QR code

Example responses

200 Response

{
  "qr": "string"
}

Responses

Status Meaning Description Schema
200 OK Successful response - a user information is returned. Inline
401 Unauthorized The user cannot be granted authentication. Error
500 Internal Server Error Internal server error. Error

Response Schema

Status Code 200

Name Type Required Restrictions Description
» qr string false The content of the QR code.

Verify the 2FA token

Code samples

# You can also use wget
curl -X PUT https://hosted.mender.io/api/management/v1/useradm/2faverify \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

PUT https://hosted.mender.io/api/management/v1/useradm/2faverify HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "token2fa": "string"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('https://hosted.mender.io/api/management/v1/useradm/2faverify',
{
  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/v1/useradm/2faverify',
  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/v1/useradm/2faverify', 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/v1/useradm/2faverify', 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/2faverify");
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/v1/useradm/2faverify", data)
    req.Header = headers

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

PUT /2faverify

Verify the 2FA token

Body parameter

{
  "token2fa": "string"
}

Parameters

Name In Type Required Description
body body object true The token
» token2fa body string false The 2FA token to verify.

Example responses

400 Response

{
  "error": "missing Authorization header",
  "request_id": "f7881e82-0492-49fb-b459-795654e7188a"
}

Responses

Status Meaning Description Schema
202 Accepted Successful response - the verification was successful. None
400 Bad Request The request is not valid. Error
401 Unauthorized The verification failed. 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.
login_ts string(date-time) false Timestamp of last successful login.

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' \
  -H 'Authorization: API_KEY'

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',
  'Authorization':'API_KEY'
};

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',
  'Authorization' => 'API_KEY'
}

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',
  'Authorization': 'API_KEY'
}

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',
    '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/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"},
        "Authorization": []string{"API_KEY"},
    }

    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 billing information

Code samples

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

GET https://hosted.mender.io/api/management/v2/tenantadm/billing 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/billing',
{
  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/tenantadm/billing',
  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/tenantadm/billing', 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/tenantadm/billing', 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/billing");
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/tenantadm/billing", data)
    req.Header = headers

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

GET /billing

Get billing information, such as the card stored as default payment method in stripe

Example responses

200 Response

{
  "card": {
    "brand": "Visa",
    "checks": {
      "address_line1_check": "pass",
      "address_postal_code_check": "pass",
      "cvc_check": "pass"
    },
    "country": "no",
    "description": "",
    "exp_month": 2,
    "exp_year": 2020,
    "fingerprint": "fingerprint",
    "funding": "all",
    "iin": "",
    "issuer": "",
    "last4": "1234",
    "three_d_secure_usage": {
      "supported": true
    },
    "wallet": {
      "dynamic_last4": "6789",
      "type": "visa_checkout"
    }
  },
  "subscription": {
    "id": "sub_36VrPHS2vVxJMq",
    "object": "subscription",
    "application_fee_percent": null,
    "billing_cycle_anchor": 1387222772,
    "billing_thresholds": null,
    "cancel_at": null,
    "cancel_at_period_end": false,
    "canceled_at": 1445989053,
    "collection_method": "charge_automatically",
    "created": 1386790772,
    "current_period_end": 1447702772,
    "current_period_start": 1444678772,
    "customer": "cus_36Akh5CetFGg9T",
    "days_until_due": null,
    "default_payment_method": null,
    "default_source": null,
    "default_tax_rates": [],
    "discount": null,
    "ended_at": 1445989053,
    "items": {
      "object": "list",
      "data": [
        {
          "id": "si_18SfBn2eZvKYlo2C1fwOImYF",
          "object": "subscription_item",
          "billing_thresholds": null,
          "created": 1386790772,
          "metadata": {},
          "price": {
            "id": "40",
            "object": "price",
            "active": true,
            "billing_scheme": "per_unit",
            "created": 1386694689,
            "currency": "usd",
            "livemode": false,
            "lookup_key": null,
            "metadata": {
              "charset": "utf-8",
              "content": "40"
            },
            "nickname": null,
            "product": "prod_BTcfj5EqyqxDVn",
            "recurring": {
              "aggregate_usage": null,
              "interval": "week",
              "interval_count": 5,
              "usage_type": "licensed"
            },
            "tiers_mode": null,
            "transform_quantity": null,
            "type": "recurring",
            "unit_amount": 5465,
            "unit_amount_decimal": "5465"
          },
          "quantity": 1,
          "subscription": "sub_36VrPHS2vVxJMq",
          "tax_rates": []
        }
      ],
      "has_more": false,
      "url": "/v1/subscription_items?subscription=sub_36VrPHS2vVxJMq"
    },
    "latest_invoice": null,
    "livemode": false,
    "metadata": {},
    "next_pending_invoice_item_invoice": null,
    "pause_collection": null,
    "pending_invoice_item_interval": null,
    "pending_setup_intent": null,
    "pending_update": null,
    "schedule": null,
    "start_date": 1386790772,
    "status": "canceled",
    "transfer_data": null,
    "trial_end": 1387222772,
    "trial_start": 1386790772
  }
}

Stripe stored card data is returned.

Responses

Status Meaning Description Schema
200 OK Stripe stored card data is returned. BillingInfo
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/billing/secret \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v2/tenantadm/billing/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/billing/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/billing/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/billing/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/billing/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/billing/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/billing/secret", data)
    req.Header = headers

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

POST /billing/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

Init Card Update

Code samples

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

POST https://hosted.mender.io/api/management/v2/tenantadm/billing/card 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/billing/card',
{
  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/billing/card',
  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/billing/card', 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/billing/card', 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/billing/card");
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/billing/card", data)
    req.Header = headers

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

POST /billing/card

Generate a Stripe setup intent for collecting updated CC details via the UI.

Example responses

Stripe setup intent id and secret is returned.

{
  "intent_id": "seti_1HXHVn2eZvKYlo2CT3XEEjKB",
  "secret": "TYooMQauvdEDq54NiTphI7jx"
}

401 Response

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

Responses

Status Meaning Description Schema
200 OK Stripe setup intent id and secret is returned. CardSetupData
401 Unauthorized Unauthorized. Error
409 Conflict Tenant is in invalid state; see error for details. Error
500 Internal Server Error Internal server error. Error

Confirm Card Update

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/management/v2/tenantadm/billing/card/{id}/confirm \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'

POST https://hosted.mender.io/api/management/v2/tenantadm/billing/card/{id}/confirm 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/billing/card/{id}/confirm',
{
  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/billing/card/{id}/confirm',
  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/billing/card/{id}/confirm', 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/billing/card/{id}/confirm', 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/billing/card/{id}/confirm");
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/billing/card/{id}/confirm", data)
    req.Header = headers

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

POST /billing/card/{id}/confirm

Save the credit card collected using the given intent as the default card.

Parameters

Name In Type Required Description
id path string true Setup intent ID obtained from POST /card.

Example responses

401 Response

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

Responses

Status Meaning Description Schema
204 No Content New credit card is saved as the default one. None
401 Unauthorized Unauthorized. Error
404 Not Found Intent not found. Error
409 Conflict Setup intent is in invalid state; see error for details. Error
500 Internal Server Error Internal server error. Error

Schemas

TenantShortInfo

{
  "intent_id": "seti_1HXHVn2eZvKYlo2CT3XEEjKB",
  "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.

BillingInfo

{
  "card": {
    "brand": "Visa",
    "checks": {
      "address_line1_check": "pass",
      "address_postal_code_check": "pass",
      "cvc_check": "pass"
    },
    "country": "no",
    "description": "",
    "exp_month": 2,
    "exp_year": 2020,
    "fingerprint": "fingerprint",
    "funding": "all",
    "iin": "",
    "issuer": "",
    "last4": "1234",
    "three_d_secure_usage": {
      "supported": true
    },
    "wallet": {
      "dynamic_last4": "6789",
      "type": "visa_checkout"
    }
  },
  "subscription": {
    "id": "sub_36VrPHS2vVxJMq",
    "object": "subscription",
    "application_fee_percent": null,
    "billing_cycle_anchor": 1387222772,
    "billing_thresholds": null,
    "cancel_at": null,
    "cancel_at_period_end": false,
    "canceled_at": 1445989053,
    "collection_method": "charge_automatically",
    "created": 1386790772,
    "current_period_end": 1447702772,
    "current_period_start": 1444678772,
    "customer": "cus_36Akh5CetFGg9T",
    "days_until_due": null,
    "default_payment_method": null,
    "default_source": null,
    "default_tax_rates": [],
    "discount": null,
    "ended_at": 1445989053,
    "items": {
      "object": "list",
      "data": [
        {
          "id": "si_18SfBn2eZvKYlo2C1fwOImYF",
          "object": "subscription_item",
          "billing_thresholds": null,
          "created": 1386790772,
          "metadata": {},
          "price": {
            "id": "40",
            "object": "price",
            "active": true,
            "billing_scheme": "per_unit",
            "created": 1386694689,
            "currency": "usd",
            "livemode": false,
            "lookup_key": null,
            "metadata": {
              "charset": "utf-8",
              "content": "40"
            },
            "nickname": null,
            "product": "prod_BTcfj5EqyqxDVn",
            "recurring": {
              "aggregate_usage": null,
              "interval": "week",
              "interval_count": 5,
              "usage_type": "licensed"
            },
            "tiers_mode": null,
            "transform_quantity": null,
            "type": "recurring",
            "unit_amount": 5465,
            "unit_amount_decimal": "5465"
          },
          "quantity": 1,
          "subscription": "sub_36VrPHS2vVxJMq",
          "tax_rates": []
        }
      ],
      "has_more": false,
      "url": "/v1/subscription_items?subscription=sub_36VrPHS2vVxJMq"
    },
    "latest_invoice": null,
    "livemode": false,
    "metadata": {},
    "next_pending_invoice_item_invoice": null,
    "pause_collection": null,
    "pending_invoice_item_interval": null,
    "pending_setup_intent": null,
    "pending_update": null,
    "schedule": null,
    "start_date": 1386790772,
    "status": "canceled",
    "transfer_data": null,
    "trial_end": 1387222772,
    "trial_start": 1386790772
  }
}

Billing related data, such as credit card information and next billing date

Properties

Name Type Required Description
card CardData false Card information stored in Stripe. The full type description is available at "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.yaml#/components/schemas/payment_method_card"
subscription SubscriptionData false Subscription information stored in Stripe. The full type description is available at "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.yaml#/components/schemas/subscription"

CardData

{
  "brand": "string",
  "checks": {
    "address_line1_check": "string",
    "address_postal_code_check": "string",
    "cvc_check": "string"
  },
  "country": "string",
  "exp_month": 0,
  "exp_year": 0,
  "fingerprint": "string",
  "funding": "string",
  "last4": "string",
  "three_d_secure_usage": {
    "supported": true
  },
  "wallet": {
    "dynamic_last4": "string",
    "type": "string"
  }
}

Card information stored in Stripe. The full type description is available at "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.yaml#/components/schemas/payment_method_card"

Properties

Name Type Required Description
brand string false Card brand. Can be amex, diners, discover, jcb, mastercard, unionpay, visa, or unknown.
checks object false Checks on Card address and CVC if provided.
» address_line1_check string false
» address_postal_code_check string false
» cvc_check string false
country string false Two-letter ISO code representing the country of the card. You could use this attribute to get a sense of the international breakdown of cards you've collected.
exp_month integer false Two-digit number representing the card's expiration month.
exp_year integer false Four-digit number representing the card's expiration year.
fingerprint string false Uniquely identifies this particular card number. You can use this attribute to check whether two customers who’ve signed up with you are using the same card number,for example. For payment methods that tokenize card information (Apple Pay, Google Pay), the tokenized number might be provided instead of the underlying card number.
funding string false Card funding type. Can be credit, debit, prepaid, or unknown.
last4 string false The last four digits of the card.
three_d_secure_usage object false Contains details on how this Card maybe be used for 3D Secure authentication.
» supported boolean false
wallet object false If this Card is part of a card wallet, this contains the details of the card wallet.
» dynamic_last4 string false
» type string false

SubscriptionData

{
  "id": "sub_36VrPHS2vVxJMq",
  "object": "subscription",
  "application_fee_percent": null,
  "billing_cycle_anchor": 1387222772,
  "billing_thresholds": null,
  "cancel_at": null,
  "cancel_at_period_end": false,
  "canceled_at": 1445989053,
  "collection_method": "charge_automatically",
  "created": 1386790772,
  "current_period_end": 1447702772,
  "current_period_start": 1444678772,
  "customer": "cus_36Akh5CetFGg9T",
  "days_until_due": null,
  "default_payment_method": null,
  "default_source": null,
  "default_tax_rates": [],
  "discount": null,
  "ended_at": 1445989053,
  "items": {
    "object": "list",
    "data": [
      {
        "id": "si_18SfBn2eZvKYlo2C1fwOImYF",
        "object": "subscription_item",
        "billing_thresholds": null,
        "created": 1386790772,
        "metadata": {},
        "price": {
          "id": "40",
          "object": "price",
          "active": true,
          "billing_scheme": "per_unit",
          "created": 1386694689,
          "currency": "usd",
          "livemode": false,
          "lookup_key": null,
          "metadata": {
            "charset": "utf-8",
            "content": "40"
          },
          "nickname": null,
          "product": "prod_BTcfj5EqyqxDVn",
          "recurring": {
            "aggregate_usage": null,
            "interval": "week",
            "interval_count": 5,
            "usage_type": "licensed"
          },
          "tiers_mode": null,
          "transform_quantity": null,
          "type": "recurring",
          "unit_amount": 5465,
          "unit_amount_decimal": "5465"
        },
        "quantity": 1,
        "subscription": "sub_36VrPHS2vVxJMq",
        "tax_rates": []
      }
    ],
    "has_more": false,
    "url": "/v1/subscription_items?subscription=sub_36VrPHS2vVxJMq"
  },
  "latest_invoice": null,
  "livemode": false,
  "metadata": {},
  "next_pending_invoice_item_invoice": null,
  "pause_collection": null,
  "pending_invoice_item_interval": null,
  "pending_setup_intent": null,
  "pending_update": null,
  "schedule": null,
  "start_date": 1386790772,
  "status": "canceled",
  "transfer_data": null,
  "trial_end": 1387222772,
  "trial_start": 1386790772
}

Subscription information stored in Stripe. The full type description is available at "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.yaml#/components/schemas/subscription"

Properties

None

CheckoutData

{
  "secret": "TYooMQauvdEDq54NiTphI7jx"
}

Checkout data.

Properties

Name Type Required Description
secret string true Stripe client secret.

CardSetupData

{
  "intent_id": "seti_1HXHVn2eZvKYlo2CT3XEEjKB",
  "secret": "TYooMQauvdEDq54NiTphI7jx"
}

Stripe setup intent data.

Properties

Name Type Required Description
intent_id string true Setup intent id.
secret string true Setup intent 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.

Audit Logs service

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 audit logs service.

Base URLs:

Get Audit Logs

Code samples

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

GET https://hosted.mender.io/api/management/v1/auditlogs/logs 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/auditlogs/logs',
{
  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/auditlogs/logs',
  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/auditlogs/logs', 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/auditlogs/logs', 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/auditlogs/logs");
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/auditlogs/logs", data)
    req.Header = headers

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

GET /logs

Returns a paged list of audit log objects.

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.
created_before query number(integer) false List only log entries created before and equal to Unix timestamp (UTC)
created_after query number(integer) false List only log entries created after and equal to Unix timestamp (UTC)
actor_id query string false If present, limits the results only to logs where actor has given id.
actor_type query string false If present, limits the results only to logs where actor is of a given type.
actor_email query string false If present, limits the results only to logs where actors has given email address.
object_id query string false If present, limits the results only to logs where object has given id.
object_type query string false If present, limits the results only to logs where object is of a given type.
object_deployment_name query string false If present, limits the results only to logs where object is a deploymen and has give name.
sort query string false Supports sorting the log list by creation date.

Detailed descriptions

sort: Supports sorting the log list by creation date. By default logs are sorted by creation date in descending order (newest first).

Enumerated Values

Parameter Value
actor_type user
actor_type device
object_type user
object_type deployment
sort asc
sort desc

Example responses

200 Response

[
  {
    "actor": {
      "id": "string",
      "type": "user",
      "email": "string",
      "identity_data": "string"
    },
    "time": "2019-08-24T14:15:22Z",
    "action": "create",
    "object": {
      "id": "string",
      "type": "user",
      "user": {
        "email": "user@acme.com"
      },
      "deployment": {
        "application/json": {
          "name": "production",
          "artifact_name": "Application 0.0.1"
        }
      }
    },
    "change": "string"
  }
]

Responses

Status Meaning Description Schema
200 OK Successful response. Inline
401 Unauthorized The user cannot be granted authentication. Error
429 Too Many Requests The user has sent too many requests in a given amount of time. Error
500 Internal Server Error Internal Server Error. Error

Response Schema

Status Code 200

ListOfLogs

Name Type Required Restrictions Description
ListOfLogs [AuditLog] false A list of audit logs is returned.
» actor Actor true The actor may be a user or device.
Depending on the type of the actor different information will be available.
»» id string true An unique identifier of the actor.
»» type string true The type of the actor.
»» email string false The email address of the user.
»» identity_data string false The Indentity data of the device.
» time string(date-time) true
» action string true
» object Object true Various types of objects are supported.
Depending on the type of object different information will be available.
»» id string true An unique identifier of the object.
»» type string true The type of the object.
»» user User false User descriptor.
»»» email string true Email address of the user.
»» deployment Deployment false The deployment descriptor.
»»» name string true
»»» artifact_name string true
» change string false

Enumerated Values

Property Value
type user
type device
action create
action update
action delete
type user
type deployment

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.

Export Audit Logs

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/auditlogs/logs/export \
  -H 'Accept: text/csv' \
  -H 'Authorization: API_KEY'

GET https://hosted.mender.io/api/management/v1/auditlogs/logs/export HTTP/1.1
Host: hosted.mender.io
Accept: text/csv


const headers = {
  'Accept':'text/csv',
  'Authorization':'API_KEY'
};

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

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

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'text/csv',
  'Authorization' => 'API_KEY'
}

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

p JSON.parse(result)

import requests
headers = {
  'Accept': 'text/csv',
  'Authorization': 'API_KEY'
}

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

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'text/csv',
    '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/auditlogs/logs/export', 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/auditlogs/logs/export");
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{"text/csv"},
        "Authorization": []string{"API_KEY"},
    }

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

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

GET /logs/export

Returns a paged list of audit log objects.

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

Parameters

Name In Type Required Description
limit query number(integer) false Limit number of logs returned
created_before query number(integer) false List only log entries created before and equal to Unix timestamp (UTC)
created_after query number(integer) false List only log entries created after and equal to Unix timestamp (UTC)
actor_id query string false If present, limits the results only to logs where actor has given id.
actor_type query string false If present, limits the results only to logs where actor is of a given type.
actor_email query string false If present, limits the results only to logs where actors has given email address.
object_id query string false If present, limits the results only to logs where object has given id.
object_type query string false If present, limits the results only to logs where object is of a given type.
object_deployment_name query string false If present, limits the results only to logs where object is a deploymen and has give name.
sort query string false Supports sorting the log list by creation date.
format_separator query string false Format string used to separate nested fields in the exported csv header
ignore query string false Header fields to ignore in the exported document (e.g. ignore=actor.id)

Detailed descriptions

sort: Supports sorting the log list by creation date. By default logs are sorted by creation date in descending order (newest first).

format_separator: Format string used to separate nested fields in the exported csv header

ignore: Header fields to ignore in the exported document (e.g. ignore=actor.id)

Enumerated Values

Parameter Value
actor_type user
actor_type device
object_type user
object_type deployment
sort asc
sort desc

Example responses

401 Response

Responses

Status Meaning Description Schema
200 OK Successful response.

Document follows in response body (chunked encoding).|None| |401|Unauthorized|The user cannot be granted authentication.|Error| |429|Too Many Requests|The user has sent too many requests in a given amount of time.|Error| |500|Internal Server Error|Internal Server Error.|Error|

Schemas

AuditLog

{
  "actor": {
    "id": "string",
    "type": "user",
    "email": "string",
    "identity_data": "string"
  },
  "time": "2019-08-24T14:15:22Z",
  "action": "create",
  "object": {
    "id": "string",
    "type": "user",
    "user": {
      "email": "user@acme.com"
    },
    "deployment": {
      "application/json": {
        "name": "production",
        "artifact_name": "Application 0.0.1"
      }
    }
  },
  "change": "string"
}

The audit log.

Properties

Name Type Required Description
actor Actor true The actor may be a user or device.
Depending on the type of the actor different information will be available.
time string(date-time) true
action string true
object Object true Various types of objects are supported.
Depending on the type of object different information will be available.
change string false

Enumerated Values

Property Value
action create
action update
action delete

Actor

{
  "id": "string",
  "type": "user",
  "email": "string",
  "identity_data": "string"
}

The actor may be a user or device. Depending on the type of the actor different information will be available.

Properties

Name Type Required Description
id string true An unique identifier of the actor.
type string true The type of the actor.
email string false The email address of the user.
identity_data string false The Indentity data of the device.

Enumerated Values

Property Value
type user
type device

Object

{
  "id": "string",
  "type": "user",
  "user": {
    "email": "user@acme.com"
  },
  "deployment": {
    "application/json": {
      "name": "production",
      "artifact_name": "Application 0.0.1"
    }
  }
}

Various types of objects are supported. Depending on the type of object different information will be available.

Properties

Name Type Required Description
id string true An unique identifier of the object.
type string true The type of the object.
user User false User descriptor.
deployment Deployment false The deployment descriptor.

Enumerated Values

Property Value
type user
type deployment

User

{
  "email": "user@acme.com"
}

User descriptor.

Properties

Name Type Required Description
email string true Email address of the user.

Deployment

{
  "application/json": {
    "name": "production",
    "artifact_name": "Application 0.0.1"
  }
}

The deployment descriptor.

Properties

Name Type Required Description
name string true
artifact_name string true

Error

{
  "error": "error description"
}

The error descriptor.

Properties

Name Type Required Description
error string false The description of the error.

Device connect

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

API for managing persistent device connections. Intended for use by the web GUI

Base URLs:

Email: Mender Support Web: Mender Support License: Apache 2.0

Get device

Code samples

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

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


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}'
};

fetch('https://hosted.mender.io/api/management/v1/deviceconnect/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' => 'Bearer {access-token}'
}

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

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}'
}

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

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

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

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deviceconnect/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/deviceconnect/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{"Bearer {access-token}"},
    }

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

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

GET /devices/{id}

Fetch the state of a device.

Parameters

Name In Type Required Description
id path string true ID for the target device.

Example responses

200 Response

{
  "device_id": "3bafab7b-4400-4bcf-8e6e-09f954699940",
  "status": "connected"
}

400 Response

{
  "error": "bad request parameters",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

404 Response

{
  "error": "Device not found",
  "request_id": "eed14d55-d996-42cd-8248-e806663810aa"
}

500 Response

{
  "error": "internal error",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

Responses

Status Meaning Description Schema
200 OK Successful response. DeviceState
400 Bad Request Invalid Request. Error
404 Not Found Device not found. Error
500 Internal Server Error Internal Server Error. Error

Connect

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/management/v1/deviceconnect/devices/{id}/connect \
  -H 'Accept: application/json' \
  -H 'Connection: Upgrade' \
  -H 'Upgrade: websocket' \
  -H 'Sec-Websocket-Key: string' \
  -H 'Sec-Websocket-Version: 13' \
  -H 'Authorization: Bearer {access-token}'

GET https://hosted.mender.io/api/management/v1/deviceconnect/devices/{id}/connect HTTP/1.1
Host: hosted.mender.io
Accept: application/json
Connection: Upgrade
Upgrade: websocket
Sec-Websocket-Key: string
Sec-Websocket-Version: 13


const headers = {
  'Accept':'application/json',
  'Connection':'Upgrade',
  'Upgrade':'websocket',
  'Sec-Websocket-Key':'string',
  'Sec-Websocket-Version':'13',
  'Authorization':'Bearer {access-token}'
};

fetch('https://hosted.mender.io/api/management/v1/deviceconnect/devices/{id}/connect',
{
  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',
  'Connection' => 'Upgrade',
  'Upgrade' => 'websocket',
  'Sec-Websocket-Key' => 'string',
  'Sec-Websocket-Version' => '13',
  'Authorization' => 'Bearer {access-token}'
}

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

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Connection': 'Upgrade',
  'Upgrade': 'websocket',
  'Sec-Websocket-Key': 'string',
  'Sec-Websocket-Version': '13',
  'Authorization': 'Bearer {access-token}'
}

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

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Connection' => 'Upgrade',
    'Upgrade' => 'websocket',
    'Sec-Websocket-Key' => 'string',
    'Sec-Websocket-Version' => '13',
    'Authorization' => 'Bearer {access-token}',
);

$client = new \GuzzleHttp\Client();

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

try {
    $response = $client->request('GET','https://hosted.mender.io/api/management/v1/deviceconnect/devices/{id}/connect', 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/deviceconnect/devices/{id}/connect");
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"},
        "Connection": []string{"Upgrade"},
        "Upgrade": []string{"websocket"},
        "Sec-Websocket-Key": []string{"string"},
        "Sec-Websocket-Version": []string{"13"},
        "Authorization": []string{"Bearer {access-token}"},
    }

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

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

GET /devices/{id}/connect

Establish permanent connection with device

Parameters

Name In Type Required Description
id path string true ID for the target device.
Connection header string false Standard websocket request header.
Upgrade header string(base64) false Standard websocket request header.
Sec-Websocket-Key header string(base64) false Standard websocket request header.
Sec-Websocket-Version header integer false Standard websocket request header.

Enumerated Values

Parameter Value
Connection Upgrade
Upgrade websocket
Sec-Websocket-Version 13

Example responses

400 Response

{
  "error": "bad request parameters",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

403 Response

{
  "error": "Access denied (RBAC)",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

404 Response

{
  "error": "<error description>",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

500 Response

{
  "error": "internal error",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

Responses

Status Meaning Description Schema
101 Switching Protocols Successful response - change to websocket protocol. None
400 Bad Request Invalid Request. Error
403 Forbidden The user is not permitted to access the remote terminal
for a given device. Error
404 Not Found Device not found. Error
500 Internal Server Error Internal Server Error. Error

Schemas

DeviceState

{
  "device_id": "3bafab7b-4400-4bcf-8e6e-09f954699940",
  "status": "connected"
}

Properties

Name Type Required Description
device_id string(uuid) false Device ID.
status string false Device status.

Enumerated Values

Property Value
status connected
status disconnected

Error

{
  "error": "<error description>",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID passed with the request X-MEN-RequestID header or generated by the server.

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'.

Count Devices

Code samples

# You can also use wget
curl -X GET http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices/count \
  -H 'Accept: application/json'

GET http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices/count 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/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'
}

result = RestClient.get 'http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices/count',
  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/count', 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/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("http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/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"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "http://mender-device-auth:8080/api/internal/v1/devauth/tenants/{tid}/devices/count", data)
    req.Header = headers

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

GET /tenants/{tid}/devices/count

Count number of devices, optionally filtered by status.

Parameters

Name In Type Required Description
tid path string true Tenant identifier.
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

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

Count

{
  "count": 42
}

Counter type

Properties

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

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.

Update Status of Devices

Code samples

# You can also use wget
curl -X POST http://mender-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/devices/{status} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

POST http://mender-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/devices/{status} HTTP/1.1
Host: mender-inventory:8080
Content-Type: application/json
Accept: application/json

const inputBody = '[
  {
    "id": "ff8f7099-d842-42f2-9d5b-46a9ad13f90a",
    "revision": 3
  },
  {
    "id": "80f3ad8f-40f2-429a-8931-b47cebbbe9b3",
    "revision": 5
  }
]';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('http://mender-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/devices/{status}',
{
  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-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/devices/{status}',
  params: {
  }, headers: headers

p JSON.parse(result)

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

r = requests.post('http://mender-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/devices/{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('POST','http://mender-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/devices/{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-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/devices/{status}");
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-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/devices/{status}", data)
    req.Header = headers

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

POST /tenants/{tenant_id}/devices/{status}

Update the status of a list of devices

An API end-point that allows to bulk update the status of a list of devices.

Body parameter

[
  {
    "id": "ff8f7099-d842-42f2-9d5b-46a9ad13f90a",
    "revision": 3
  },
  {
    "id": "80f3ad8f-40f2-429a-8931-b47cebbbe9b3",
    "revision": 5
  }
]

Parameters

Name In Type Required Description
tenant_id path string true ID of given tenant.
status path string true New status to set for the specified devices.
body body DeviceUpdate true List of devices.

Example responses

400 Response

{
  "error": "missing Authorization header"
}

Responses

Status Meaning Description Schema
200 OK The operation completed successfully. None
400 Bad Request Malformed request body. See error for details. Error
409 Conflict Write conflict, the request needs to be retried. Error
500 Internal Server Error Internal server error. Error

Update Inventory for a Device

Code samples

# You can also use wget
curl -X PATCH http://mender-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/device/{device_id}/attribute/scope/{scope} \
  -H 'Content-Type: application/json'

PATCH http://mender-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/device/{device_id}/attribute/scope/{scope} HTTP/1.1
Host: mender-inventory:8080
Content-Type: application/json

const inputBody = '[
  {
    "name": "ip_addr_eth",
    "description": "Device IP address on ethernet interface",
    "value": "127.0.0.1"
  }
]';
const headers = {
  'Content-Type':'application/json'
};

fetch('http://mender-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/device/{device_id}/attribute/scope/{scope}',
{
  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'
}

result = RestClient.patch 'http://mender-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/device/{device_id}/attribute/scope/{scope}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json'
}

r = requests.patch('http://mender-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/device/{device_id}/attribute/scope/{scope}', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

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

$client = new \GuzzleHttp\Client();

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

try {
    $response = $client->request('PATCH','http://mender-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/device/{device_id}/attribute/scope/{scope}', 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/{tenant_id}/device/{device_id}/attribute/scope/{scope}");
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"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("PATCH", "http://mender-inventory:8080/api/internal/v1/inventory/tenants/{tenant_id}/device/{device_id}/attribute/scope/{scope}", data)
    req.Header = headers

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

PATCH /tenants/{tenant_id}/device/{device_id}/attribute/scope/{scope}

Update multiple inventory attributes in a single scope for a device

An API end-point that allows to update the inventory attributes in a single scope for a device.

Body parameter

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

Parameters

Name In Type Required Description
tenant_id path string true ID of given tenant.
device_id path string true ID of given device.
scope path string true Scope of the inventory attributes.
body body Attribute true List of inventory attributes to set.

Responses

Status Meaning Description Schema
200 OK Device inventory successfully updated. None
400 Bad Request Error descriptor. None
500 Internal Server Error Error descriptor. None

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.

DeviceUpdate

{
  "id": "string",
  "revision": 0
}

Object containing device id and device revision of the device to update.

Properties

Name Type Required Description
id string true Device identifier.
revision number(integer) true Device object revision.

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 An array of artifact's identifiers.

Enumerated Values

Property Value
status inprogress
status pending
status finished

Response Headers

Status Header Type Format Description
200 X-Total-Count int Total number of deployments matching query.

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 An array of artifact's identifiers.

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

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

List Users

Code samples

# You can also use wget
curl -X GET http://mender-useradm:8080/api/internal/v1/useradm/tenants/{tenant_id}/users \
  -H 'Accept: */*'

GET http://mender-useradm:8080/api/internal/v1/useradm/tenants/{tenant_id}/users HTTP/1.1
Host: mender-useradm:8080
Accept: */*


const headers = {
  'Accept':'*/*'
};

fetch('http://mender-useradm:8080/api/internal/v1/useradm/tenants/{tenant_id}/users',
{
  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/tenants/{tenant_id}/users',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': '*/*'
}

r = requests.get('http://mender-useradm:8080/api/internal/v1/useradm/tenants/{tenant_id}/users', 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/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("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/tenants/{tenant_id}/users", data)
    req.Header = headers

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

GET /tenants/{tenant_id}/users

*List all users registered under the tenant owning the JWT. *

Parameters

Name In Type Required Description
tenant_id path string true Tenant ID.
id query string false Limit result by user ID, can be repeated to include multiple users in the query.
email query string false Limit result by user email, can be repeated to include multiple users in the query.
created_after query integer false Filter users created after timestamp (UNIX timestamp).
created_before query integer false Filter users created before timestamp (UNIX timestamp).
updated_after query integer false Filter users updated after timestamp (UNIX timestamp).
updated_before query integer false Filter users updated before timestamp (UNIX timestamp).

Detailed descriptions

id: Limit result by user ID, can be repeated to include multiple users in the query.

email: Limit result by user email, can be repeated to include multiple users in the query.

created_after: Filter users created after timestamp (UNIX timestamp).

created_before: Filter users created before timestamp (UNIX timestamp).

updated_after: Filter users updated after timestamp (UNIX timestamp).

updated_before: Filter users updated before timestamp (UNIX timestamp).

Example responses

200 Response

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.

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.

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.

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",
        "retries": 0,
        "retryDelaySeconds": 0,
        "requires": [
          "string"
        ],
        "cli": {
          "command": [
            "string"
          ],
          "executionTimeOut": 0
        },
        "http": {
          "uri": "string",
          "method": "string",
          "contentType": "string",
          "body": "string",
          "json": {},
          "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
»» retries integer false
»» retryDelaySeconds integer false
»» requires [string] false
»» 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
»»» json object 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",
      "retries": 0,
      "retryDelaySeconds": 0,
      "requires": [
        "string"
      ],
      "cli": {
        "command": [
          "string"
        ],
        "executionTimeOut": 0
      },
      "http": {
        "uri": "string",
        "method": "string",
        "contentType": "string",
        "body": "string",
        "json": {},
        "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",
      "retries": 0,
      "retryDelaySeconds": 0,
      "requires": [
        "string"
      ],
      "cli": {
        "command": [
          "string"
        ],
        "executionTimeOut": 0
      },
      "http": {
        "uri": "string",
        "method": "string",
        "contentType": "string",
        "body": "string",
        "json": {},
        "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",
  "json": {},
  "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
json object false
headers object false
statusCodes [integer] false
connectionTimeOut integer false
readTimeOut integer false

Task

{
  "name": "string",
  "type": "string",
  "retries": 0,
  "retryDelaySeconds": 0,
  "requires": [
    "string"
  ],
  "cli": {
    "command": [
      "string"
    ],
    "executionTimeOut": 0
  },
  "http": {
    "uri": "string",
    "method": "string",
    "contentType": "string",
    "body": "string",
    "json": {},
    "headers": {},
    "statusCodes": [
      0
    ],
    "connectionTimeOut": 0,
    "readTimeOut": 0
  }
}

Task definition

Properties

Name Type Required Description
name string true
type string true
retries integer false
retryDelaySeconds integer false
requires [string] false
cli CLIParams false CLI parameters
http HTTPParams false HTTP parameters

Workflow

{
  "name": "string",
  "description": "string",
  "version": 0,
  "schemaversion": 0,
  "tasks": [
    {
      "name": "string",
      "type": "string",
      "retries": 0,
      "retryDelaySeconds": 0,
      "requires": [
        "string"
      ],
      "cli": {
        "command": [
          "string"
        ],
        "executionTimeOut": 0
      },
      "http": {
        "uri": "string",
        "method": "string",
        "contentType": "string",
        "body": "string",
        "json": {},
        "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

Audit Logs service

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 audit logs service.

Base URLs:

Check Health

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/internal/v1/auditlogs/health/alive \
  -H 'Accept: application/json'

GET https://hosted.mender.io/api/internal/v1/auditlogs/health/alive HTTP/1.1
Host: hosted.mender.io
Accept: application/json


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

fetch('https://hosted.mender.io/api/internal/v1/auditlogs/health/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 'https://hosted.mender.io/api/internal/v1/auditlogs/health/alive',
  params: {
  }, headers: headers

p JSON.parse(result)

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

r = requests.get('https://hosted.mender.io/api/internal/v1/auditlogs/health/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','https://hosted.mender.io/api/internal/v1/auditlogs/health/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("https://hosted.mender.io/api/internal/v1/auditlogs/health/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", "https://hosted.mender.io/api/internal/v1/auditlogs/health/alive", data)
    req.Header = headers

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

GET /health/alive

Get health status of service

Returns a status of the running service.

Example responses

500 Response

{
  "error": "error description"
}

Responses

Status Meaning Description Schema
204 No Content Successful response. None
500 Internal Server Error Internal Server Error. Error

Get Audit Logs

Code samples

# You can also use wget
curl -X GET https://hosted.mender.io/api/internal/v1/auditlogs/tenants/{tenant_id}/logs \
  -H 'Accept: application/json'

GET https://hosted.mender.io/api/internal/v1/auditlogs/tenants/{tenant_id}/logs HTTP/1.1
Host: hosted.mender.io
Accept: application/json


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

fetch('https://hosted.mender.io/api/internal/v1/auditlogs/tenants/{tenant_id}/logs',
{
  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 'https://hosted.mender.io/api/internal/v1/auditlogs/tenants/{tenant_id}/logs',
  params: {
  }, headers: headers

p JSON.parse(result)

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

r = requests.get('https://hosted.mender.io/api/internal/v1/auditlogs/tenants/{tenant_id}/logs', 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','https://hosted.mender.io/api/internal/v1/auditlogs/tenants/{tenant_id}/logs', 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/internal/v1/auditlogs/tenants/{tenant_id}/logs");
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", "https://hosted.mender.io/api/internal/v1/auditlogs/tenants/{tenant_id}/logs", data)
    req.Header = headers

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

GET /tenants/{tenant_id}/logs

Returns a list of audit log objects.

Parameters

Name In Type Required Description
tenant_id path string true Tenant ID.
page query number(integer) false Starting page.
per_page query number(integer) false Number of results per page.
created_before query number(integer) false List only log entries created before and equal to Unix timestamp (UTC)
created_after query number(integer) false List only log entries created after and equal to Unix timestamp (UTC)
actor_id query string false If present, limits the results only to logs where actor has given id.
actor_type query string false If present, limits the results only to logs where actor is of a given type.
actor_email query string false If present, limits the results only to logs where actors has given email address.
object_id query string false If present, limits the results only to logs where object has given id.
object_type query string false If present, limits the results only to logs where object is of a given type.
object_deployment_name query string false If present, limits the results only to logs where object is a deployment with a given name.
sort query string false Supports sorting the log list by creation date.

Detailed descriptions

sort: Supports sorting the log list by creation date. By default logs are sorted by creation date in descending order (newest first).

Enumerated Values

Parameter Value
actor_type user
actor_type device
object_type user
object_type deployment
sort asc
sort desc

Example responses

200 Response

[
  {
    "actor": {
      "id": "string",
      "type": "user",
      "email": "string",
      "identity_data": "string"
    },
    "time": "2019-08-24T14:15:22Z",
    "action": "create",
    "object": {
      "id": "string",
      "type": "user",
      "user": {
        "email": "user@acme.com"
      },
      "deployment": {
        "application/json": {
          "name": "production",
          "artifact_name": "Application 0.0.1"
        }
      }
    },
    "change": "string"
  }
]

Responses

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

Response Schema

Status Code 200

ListOfLogs

Name Type Required Restrictions Description
ListOfLogs [AuditLog] false A list of audit logs is returned.
» actor Actor true The actor may be a user or device.
Depending on the type of the actor different information will be available.
»» id string true A unique identifier of the actor.
»» type string true The type of the actor.
»» email string false The email address of the user.
»» identity_data string false The identity data of the device.
» time string(date-time) true
» action string true
» object Object true Various types of objects are supported.
Depending on the type of object different information will be available.
»» id string true A unique identifier of the object.
»» type string true The type of the object.
»» user User false The user descriptor.
»»» email string true The email address of the user.
»» deployment Deployment false The deployment descriptor.
»»» name string true
»»» artifact_name string true
» change string false

Enumerated Values

Property Value
type user
type device
action create
action update
action delete
type user
type deployment

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.

Save Audit Log

Code samples

# You can also use wget
curl -X POST https://hosted.mender.io/api/internal/v1/auditlogs/tenants/{tenant_id}/logs \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

POST https://hosted.mender.io/api/internal/v1/auditlogs/tenants/{tenant_id}/logs HTTP/1.1
Host: hosted.mender.io
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "actor": {
    "id": "string",
    "type": "user",
    "email": "string",
    "identity_data": "string"
  },
  "time": "2019-08-24T14:15:22Z",
  "action": "create",
  "object": {
    "id": "string",
    "type": "user",
    "user": {
      "email": "user@acme.com"
    },
    "deployment": {
      "application/json": {
        "name": "production",
        "artifact_name": "Application 0.0.1"
      }
    }
  },
  "change": "string"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('https://hosted.mender.io/api/internal/v1/auditlogs/tenants/{tenant_id}/logs',
{
  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/internal/v1/auditlogs/tenants/{tenant_id}/logs',
  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/internal/v1/auditlogs/tenants/{tenant_id}/logs', 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/internal/v1/auditlogs/tenants/{tenant_id}/logs', 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/internal/v1/auditlogs/tenants/{tenant_id}/logs");
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/internal/v1/auditlogs/tenants/{tenant_id}/logs", data)
    req.Header = headers

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

POST /tenants/{tenant_id}/logs

Log event.

Body parameter

{
  "actor": {
    "id": "string",
    "type": "user",
    "email": "string",
    "identity_data": "string"
  },
  "time": "2019-08-24T14:15:22Z",
  "action": "create",
  "object": {
    "id": "string",
    "type": "user",
    "user": {
      "email": "user@acme.com"
    },
    "deployment": {
      "application/json": {
        "name": "production",
        "artifact_name": "Application 0.0.1"
      }
    }
  },
  "change": "string"
}

Parameters

Name In Type Required Description
tenant_id path string true Tenant ID.
body body AuditLog true

Example responses

500 Response

{
  "error": "error description"
}

Responses

Status Meaning Description Schema
201 Created Event has been successfully logged. None
500 Internal Server Error Internal Server Error. Error

Schemas

AuditLog

{
  "actor": {
    "id": "string",
    "type": "user",
    "email": "string",
    "identity_data": "string"
  },
  "time": "2019-08-24T14:15:22Z",
  "action": "create",
  "object": {
    "id": "string",
    "type": "user",
    "user": {
      "email": "user@acme.com"
    },
    "deployment": {
      "application/json": {
        "name": "production",
        "artifact_name": "Application 0.0.1"
      }
    }
  },
  "change": "string"
}

Audit log.

Properties

Name Type Required Description
actor Actor true The actor may be a user or device.
Depending on the type of the actor different information will be available.
time string(date-time) true
action string true
object Object true Various types of objects are supported.
Depending on the type of object different information will be available.
change string false

Enumerated Values

Property Value
action create
action update
action delete

Actor

{
  "id": "string",
  "type": "user",
  "email": "string",
  "identity_data": "string"
}

The actor may be a user or device. Depending on the type of the actor different information will be available.

Properties

Name Type Required Description
id string true A unique identifier of the actor.
type string true The type of the actor.
email string false The email address of the user.
identity_data string false The identity data of the device.

Enumerated Values

Property Value
type user
type device

Object

{
  "id": "string",
  "type": "user",
  "user": {
    "email": "user@acme.com"
  },
  "deployment": {
    "application/json": {
      "name": "production",
      "artifact_name": "Application 0.0.1"
    }
  }
}

Various types of objects are supported. Depending on the type of object different information will be available.

Properties

Name Type Required Description
id string true A unique identifier of the object.
type string true The type of the object.
user User false The user descriptor.
deployment Deployment false The deployment descriptor.

Enumerated Values

Property Value
type user
type deployment

User

{
  "email": "user@acme.com"
}

The user descriptor.

Properties

Name Type Required Description
email string true The email address of the user.

Deployment

{
  "application/json": {
    "name": "production",
    "artifact_name": "Application 0.0.1"
  }
}

The deployment descriptor.

Properties

Name Type Required Description
name string true
artifact_name string true

Error

{
  "error": "error description"
}

The error descriptor.

Properties

Name Type Required Description
error string false The description of the error.

Device connect

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 for managing persistent device connections. Intended for use by the web GUI.

Base URLs:

Email: Mender Support Web: Mender Support License: Apache 2.0

Check Health

Code samples

# You can also use wget
curl -X GET https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/health \
  -H 'Accept: application/json'

GET https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/health HTTP/1.1
Host: mender-deviceconnect:8080
Accept: application/json


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

fetch('https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/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 'https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/health',
  params: {
  }, headers: headers

p JSON.parse(result)

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

r = requests.get('https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/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','https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/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("https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/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", "https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/health", data)
    req.Header = headers

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

GET /health

Get health status of service

Example responses

400 Response

{
  "error": "<error description>",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

Responses

Status Meaning Description Schema
204 No Content Service is healthy. None
400 Bad Request Invalid Request. Error
500 Internal Server Error Internal Server Error. Error

Check Liveliness

Code samples

# You can also use wget
curl -X GET https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/alive \
  -H 'Accept: application/json'

GET https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/alive HTTP/1.1
Host: mender-deviceconnect:8080
Accept: application/json


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

fetch('https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/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 'https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/alive',
  params: {
  }, headers: headers

p JSON.parse(result)

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

r = requests.get('https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/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','https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/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("https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/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", "https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/alive", data)
    req.Header = headers

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

GET /alive

Get service liveliness status.

Example responses

500 Response

{
  "error": "<error description>",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

Responses

Status Meaning Description Schema
204 No Content Service is up and serving requests. None
500 Internal Server Error Internal Server Error. Error

Provision tenant

Code samples

# You can also use wget
curl -X POST https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

POST https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants HTTP/1.1
Host: mender-deviceconnect:8080
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "tenant_id": "string"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/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 'https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants',
  params: {
  }, headers: headers

p JSON.parse(result)

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

r = requests.post('https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/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','https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/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://mender-deviceconnect:8080/api/internal/v1/deviceconnect/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", "https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants", data)
    req.Header = headers

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

POST /tenants

Initialize internal state for a new tenant

Body parameter

{
  "tenant_id": "string"
}

Parameters

Name In Type Required Description
body body NewTenant false

Example responses

400 Response

{
  "error": "bad request parameters",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

500 Response

{
  "error": "internal error",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

Responses

Status Meaning Description Schema
201 Created Tenant initialized successfully. None
400 Bad Request Invalid Request. Error
500 Internal Server Error Internal Server Error. Error

Provision device

Code samples

# You can also use wget
curl -X POST https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/devices \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'

POST https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/devices HTTP/1.1
Host: mender-deviceconnect:8080
Content-Type: application/json
Accept: application/json

const inputBody = '{
  "device_id": "3bafab7b-4400-4bcf-8e6e-09f954699940"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};

fetch('https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/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'
}

result = RestClient.post 'https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/devices',
  params: {
  }, headers: headers

p JSON.parse(result)

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

r = requests.post('https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/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('POST','https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/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://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/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"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("POST", "https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/devices", data)
    req.Header = headers

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

POST /tenants/{tenantId}/devices

Register a new device with the deviceconnect service.

Body parameter

{
  "device_id": "3bafab7b-4400-4bcf-8e6e-09f954699940"
}

Parameters

Name In Type Required Description
tenantId path string true ID of tenant the device belongs to.
body body Device false

Example responses

400 Response

{
  "error": "bad request parameters",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

500 Response

{
  "error": "internal error",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

Responses

Status Meaning Description Schema
201 Created Device was provisioned successfully. None
400 Bad Request Invalid Request. Error
500 Internal Server Error Internal Server Error. Error

Decomission device

Code samples

# You can also use wget
curl -X DELETE https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/devices/{deviceId} \
  -H 'Accept: application/json'

DELETE https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/devices/{deviceId} HTTP/1.1
Host: mender-deviceconnect:8080
Accept: application/json


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

fetch('https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/devices/{deviceId}',
{
  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://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/devices/{deviceId}',
  params: {
  }, headers: headers

p JSON.parse(result)

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

r = requests.delete('https://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/devices/{deviceId}', 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://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/devices/{deviceId}', 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://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/devices/{deviceId}");
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://mender-deviceconnect:8080/api/internal/v1/deviceconnect/tenants/{tenantId}/devices/{deviceId}", data)
    req.Header = headers

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

DELETE /tenants/{tenantId}/devices/{deviceId}

Remove a device from the deviceconnect service.

Parameters

Name In Type Required Description
tenantId path string true ID of tenant the device belongs to.
deviceId path string true ID of the target device.

Example responses

500 Response

{
  "error": "internal error",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

Responses

Status Meaning Description Schema
202 Accepted Device was deleted successfully None
500 Internal Server Error Internal Server Error. Error

Schemas

Error

{
  "error": "<error description>",
  "request_id": "eed14d55-d996-42cd-8248-e806663810a8"
}

Error descriptor.

Properties

Name Type Required Description
error string false Description of the error.
request_id string false Request ID passed with the request X-MEN-RequestID header or generated by the server.

NewTenant

{
  "tenant_id": "string"
}

Properties

Name Type Required Description
tenant_id string true ID of new tenant.

Device

{
  "device_id": "3bafab7b-4400-4bcf-8e6e-09f954699940"
}

Properties

Name Type Required Description
device_id string(uuid) true ID of the new device.