API capabilities
This tutorial demonstrates how to use the capabilities endpoint to dynamically check which endpoints are supported by the current state of your Nureva® device.
What can be done with the API?
The capabilities endpoint returns an OpenAPI description of Nureva's local APIs. The description returned is a JSON object that follows the OpenAPI Specification, allowing both humans and computers to understand the capabilities of the API. Since the description is machine-readable, developers are able to programmatically extract information from the schema. Developers can also use tools that utilize the description to assist development against the API, such as generating client code, creating mock servers or visualizing the API. We have also extended the OpenAPI Specification with an extension property to indicate which endpoints or attributes are supported by the current state of the Nureva device.
After completing this tutorial, you will know how to make a request to the capabilities endpoint to retrieve the OpenAPI description. Included are instructions for creating an example program to parse through the Nureva extension properties to better understand the capabilities of the Nureva device. For more general information about the OpenAPI description, refer to the OpenAPI Specification.
The OpenAPI description may include endpoints and properties that have not been documented in our tutorials and references due to their unfinished state. These endpoints and properties are subject to change and should not be developed against.
Minimum role required: none
This endpoint does not require authorization, so no role is required.
Overview
- Use capabilities to make a request to get the OpenAPI description that describes the capabilities of the audio device.
- Understand the Nureva extension object schema.
- Write a program to parse through the OpenAPI description to understand the device capabilities.
Instructions
Step 1 - Make a request to get the OpenAPI description
Use the capabilities endpoint:
- Set the path with the IP address of the Nureva device followed by
/api/v1
. - Send the GET request. The code sample below is a request to retrieve the settings for the device with the IP address of
10.0.0.1
. - Add the header
Nureva-Client-Id
as key andintegration_app_name
as the value. - Add the header
Nureva-Client-Version
as key and0.0.1
as the value.
curl --request GET \
--url https://10.0.0.1/api/v1 \
--header 'Nureva-Client-Id: integration_app_name' \
--header 'Nureva-Client-Version: 0.0.1'
- If the call is successful, an HTTP status code of 200 OK will be returned. The body of the response will contain the OpenAPI description in JSON format. The schema of the OpenAPI description is described in the OpenAPI Specification schema section.
Step 2 - Understand the Nureva extension object schema
The OpenAPI description has a paths property, which is an object that contains the relative paths for each endpoint. Each endpoint path is a path item object which describes the endpoint and its operations. The operation objects have been extended to include an optional x-nureva
property that contains a Nureva extension object. The Nureva extension object contains additional information about the operation such as device requirements. Refer to the capabilities reference to see the schema and a few examples.
Step 3 - Write a program to parse through the OpenAPI description to determine endpoint capabilities
This tutorial will demonstrate how to parse through the OpenAPI description and print out your device's capabilities in Node.js.
First, save the OpenAPI description retrieved in Step 1 to a file. In this example, assume the file is saved as api.json
and the paths property in the OpenAPI description contains these endpoints:
{
"/api/example/endpoint1": {
"get": {
"x-nureva": {
"minimumRoleRequired": "general",
"requirements": {
"minimumBars": 1
}
}
}
},
"/api/example/endpoint2": {
"get": {
"x-nureva": {
"minimumRoleRequired": "general",
"requirements": {
"minimumBars": 2
},
"requirementsFailed": {
"minimumBars": 1
}
}
},
"patch": {
"x-nureva": {
"minimumRoleRequired": "general",
"requirements": {
"minimumBars": 1
},
"capabilities": {
"exampleCapability1": {},
"exampleCapability2": {
"requirements": {
"minimumFirmware": "1.5"
}
},
"exampleCapability3": {
"requirements": {
"minimumFirmware": "1.9"
},
"requirementsFailed": {
"minimumFirmware": "1.8"
}
}
}
}
}
}
}
You may choose to replace the paths
property in your OpenAPI description with the object above to follow the example more closely.
From a new Node.js project, let's start off by reading the OpenAPI description from a file and parsing it into an object. Copy the contents below to the entry point file.
const fs = require('fs');
fs.readFile('./api.json', (error, data) => {
const openApiDescription = JSON.parse(data);
getCapabilities(openApiDescription);
});
function getCapabilities(openApiDescription) {
// To be implemented
}
Let's implement the getCapabilities
method to parse the OpenAPI description to check which endpoints are supported by the device.
function getCapabilities(openApiDescription) {
const paths = openApiDescription.paths;
// Keep track of device support here
let support = {};
if (paths) {
// Iterate through each endpoint (path item object) in paths
for (const [pathItemObjectKey, pathItemObject] of Object.entries(paths)) {
// Iterate through each property in path item object
for (const [
pathItemObjectPropertyKey,
pathItemObjectPropertyObject,
] of Object.entries(pathItemObject)) {
const HttpMethods = [
'get',
'put',
'post',
'delete',
'options',
'head',
'patch',
'trace',
];
// Look for the Nureva Extension Object only in the operation objects (HTTP methods)
if (!HttpMethods.includes(pathItemObjectPropertyKey)) continue;
const operationKey = pathItemObjectPropertyKey;
const operationObject = pathItemObjectPropertyObject;
// Get the Nureva Extension Object from the path item object
const nurevaExtensionObject = operationObject['x-nureva'];
const supportOperationPropertyName = `${operationKey} ${pathItemObjectKey}`;
// If the Nureva Extension Object is null, there are no requirements so the endpoint is supported
if (!nurevaExtensionObject) {
support[supportOperationPropertyName] = {
isEndpointSupported: 'supported',
};
continue;
}
// Get the requirementsFailed object
const requirementsFailed = nurevaExtensionObject.requirementsFailed;
// The endpoint is not supported if this object is non-null
if (requirementsFailed) {
support[supportOperationPropertyName] = {
isEndpointSupported: 'not supported',
};
}
// Otherwise, the endpoint is supported if the object is null
else {
support[supportOperationPropertyName] = {
isEndpointSupported: 'supported',
};
}
}
}
}
console.log(support);
}
Let's run the code and look at the output. Both GET /api/example/endpoint1
and PATCH /api/example/endpoint2
are supported since they do not have any failed requirements. GET /api/example/endpoint2
is not supported because it requires a minimum of two bars.
{
"get /api/example/endpoint1": {
"isEndpointSupported": "supported"
},
"get /api/example/endpoint2": {
"isEndpointSupported": "not supported"
},
"patch /api/example/endpoint2": {
"isEndpointSupported": "supported"
}
}
We can add on to the implementation to also check for capabilities within an endpoint. Let's update the getCapabilities
method to parse the capabilities object.
function getCapabilities(openApiDescription) {
const paths = openApiDescription.paths;
// Keep track of device support here
let support = {};
if (paths) {
// Iterate through each endpoint (path item object) in paths
for (const [pathItemObjectKey, pathItemObject] of Object.entries(paths)) {
// Iterate through each property in path item object
for (const [
pathItemObjectPropertyKey,
pathItemObjectPropertyObject,
] of Object.entries(pathItemObject)) {
const HttpMethods = [
'get',
'put',
'post',
'delete',
'options',
'head',
'patch',
'trace',
];
// Look for the Nureva Extension Object only in the operation objects (HTTP methods)
if (!HttpMethods.includes(pathItemObjectPropertyKey)) continue;
const operationKey = pathItemObjectPropertyKey;
const operationObject = pathItemObjectPropertyObject;
// Get the Nureva Extension Object from the path item object
const nurevaExtensionObject = operationObject['x-nureva'];
const supportOperationPropertyName = `${operationKey} ${pathItemObjectKey}`;
// If the Nureva Extension Object is null, there are no requirements so the endpoint is supported
if (!nurevaExtensionObject) {
support[supportOperationPropertyName] = {
isEndpointSupported: 'supported',
};
continue;
}
// Get the requirementsFailed object
const requirementsFailed = nurevaExtensionObject.requirementsFailed;
// The endpoint is not supported if this object is non-null
if (requirementsFailed) {
support[supportOperationPropertyName] = {
isEndpointSupported: 'not supported',
};
}
// Otherwise, the endpoint is supported if the object is null
else {
support[supportOperationPropertyName] = {
isEndpointSupported: 'supported',
};
}
// Get the capabilities within the endpoint
const capabilities = nurevaExtensionObject.capabilities;
if (capabilities) {
support[supportOperationPropertyName] = {
...support[supportOperationPropertyName],
capabilities: {},
};
// Iterate through each capability
for (const [capabilityKey, capability] of Object.entries(
capabilities,
)) {
const requirementsFailed = capability.requirementsFailed;
// The capability is not supported if this object is non-null
if (requirementsFailed) {
support[supportOperationPropertyName].capabilities = {
...support[supportOperationPropertyName].capabilities,
[capabilityKey]: 'not supported',
};
}
// Otherwise, the capability is supported if the object is null
else {
support[supportOperationPropertyName].capabilities = {
...support[supportOperationPropertyName].capabilities,
[capabilityKey]: 'supported',
};
}
}
}
}
}
}
console.log(support);
}
The output will now look like this:
{
"get /api/example/endpoint1": {
"isEndpointSupported": "supported"
},
"get /api/example/endpoint2": {
"isEndpointSupported": "not supported"
},
"patch /api/example/endpoint2": {
"isEndpointSupported": "supported",
"capabilities": {
"exampleCapability1": "supported",
"exampleCapability2": "supported",
"exampleCapability3": "not supported"
}
}
}
Tutorial complete!
You now know how to check device capabilities.
Updated 12 days ago