Overview


This provides a basic introduction to the MachineMetrics API.

API Access

The MachineMetrics API is accessed over HTTPS from https://api.machinemetrics.com. All requests and responses are transmitted as Content-Type: application/json unless otherwise specified.

If you are testing the APIs out using an API key on https://demo.machinemetrics.com, the API URL is https://api-demo.machinemetrics.com.

Client Errors

Errors in API requests will be returned with an appropriate HTTP status code and JSON object describing the error.

Sending invalid JSON or the wrong content-type will result in a 400 Bad Request response.

HTTP/1.1 400 Bad Request
Content-Length: 34

{"message":"Problem parsing JSON"}

Sending invalid fields in a query will result in a 400 Bad Request response with additional information.

HTTP/1.1 400 Bad Request
Content-Length: 146

{
    "code": "ValidationError",
    "message": "Validation Error",
    "errors": [
        {
            "field": "data",
            "code": "InvalidDataItem",
            "message": "Metric 'abc' is not valid"
        }
    ]
}

Most error objects include a code, message, and an errors array containing additional information on 0 or more distinct fields.

Authentication


API requests at MachineMetrics are authenticated via one of two ways:

bearerAuth

The standard way to authenticate with the MachineMetrics API is via OAuth tokens.

OAuth tokens will authenticate your application on behalf of a user for a given set of scopes.

To authenticate on behalf of a company, you can use OAuth-compatible API keys. API keys are created with the same scopes as standard OAuth tokens. Your key should be treated like a password and kept secure.

The following cURL request is an example of HTTP Authorization header authentication using your API key:

curl -H "Authorization: Bearer API-KEY" https://api.machinemetrics.com

To create an API key, login to MachineMetrics and go to https://app.machinemetrics.com/settings/api-keys.

Security Scheme Type HTTP
HTTP Authorization Scheme bearer

jwtAuth

JSON Web Tokens, or JWTs, are used as an additional layer of security to authenticate various requests.

The following request is an example of JWT authentication using your token as a query parameter:

https://api.machinemetrics.com?token={{JWT}}

See our warehouse report CSV operations for some examples of use cases.

Security Scheme Type API Key
Query parameter name: token

OAuth Authorization

All third party applications must be authorized through the OAuth protocol.

Creating an OAuth application

To get started with writing an OAuth application for MachineMetrics, contact support@machinemetrics.com to register your application and include the following:

  • The name of your application.
  • The redirect URI of your application (more information below).
  • The MachineMetrics user that is responsible for managing this application, if applicable.

Support will return a client id and client secret that identify your application. Keep these credentials safe. In particular, the client secret should never be exposed and cannot be recovered by MachineMetrics if lost. We can generate new credentials for you, but previous credentials will stop working in that instance.

MachineMetrics only supports the authorization code grant type. If this grant type is not suitable for your application, consider using API keys instead.

Implementing the Authorization Code grant

This standard grant type flows through several basic steps:

  1. Users are redirected to MachineMetrics to login and authorize
  2. Users are redirected back to your application by MachineMetrics
  3. Your application accesses the MachineMetrics API with the provided access token

1. Users are redirected to MachineMetrics

GET https://login.machinemetrics.com/oauth/authorize

Parameters

Name Description
response_type Required. Must always be set to "code".
client_id Required. The client ID you received from MachineMetrics when you registered your application.
redirect_uri Required. The URL users will be redirected back to after authorization. Must match one of the redirect URLs registered to your application. See details about redirect urls.
scope A space-delimited list of scopes that your application is requesting access for. Users will be prompted to allow access for each scope. If a scope has been authorized by a previous authorization grant flow, the user will not be prompted again.
state A random string used to protect against cross-site request forgery attacks.

2. Users are redirected back to your application

After the user accepts or rejects your request, MachineMetrics will redirect them back to your application. If the request was denied or another error occurred in the process, the query string of the redirect will include an error and error_description parameter describing the result.

If the request was accepted, the query string of the redirect will include a temporary code parameter and a state parameter. The state parameter will match the state value your application provided in the original authorization request. If the states don't match, the request did not come from your application and the rest of the authorization process should be stopped.

Your application needs to issue a web request to exchange the code for an access token.

POST https://login.machinemetrics.com/oauth/token

The web request body must be x-form-urlencoded.

Parameters

Name Description
grant_type Required. Must always be set to authorization_code.
client_id Required. The client ID you received from MachineMetrics when you registered your application.
client_secret Required. The client secret you received from MachineMetrics when you registered your application.
redirect_uri Required. The same redirect_uri provided in step 1.
code Required. The code you received in the response from step 1.

Response

The token request will send back an application/json response with the following form:

{
  "access_token": "at-3fd2bb4d7f5046e9a8b807846e45dc4e",
  "token_type": "bearer",
  "scope": "user,operator"
}

3. Use the access token

The access token you get back is your credential for accessing MachineMetrics APIs on behalf of the user. The access token should be passed in the Authorization header of each request.

Bearer OAUTH-TOKEN

If the Authorization header cannot be used for some reason, then access tokens can be passed in the query string using the access_token parameter. This use is discouraged.

GET https://api.machinemetrics.com/locations?access_token={{ACCESS_TOKEN}}

Redirect URLs

The redirect_uri parameter in OAuth is required by MachineMetrics. Each authorization grant request must provide a redirect URL to return a user to after authorization. The URL must exactly match the URL that your application was registered with, or match a subpath of that URL. You may register multiple URLs with your application.

Request Walkthrough


Anatomy of a Query: Total In-Cycle Milliseconds by Machine

The Production API is very flexible in that it allows you to group data in various ways and extract different data points (such as in-cycle time, parts produced, quality, etc). The following walkthrough details how to use the Production API to get the total amount of time that a machine was in-cycle since it was first connected to MachineMetrics.

Getting Started

For starters, you're going to need a token to authorize your requests to our API. The easiest approach is to use an API key, but OAuth is also available if it's required for your implementation.

To get an API key, go to https://app.machinemetrics.com/settings/api-keys. The reporting scope is required for this API endpoint, so be sure to select that scope when creating your key.

There are four major parts to a request: the URL, method, headers, and body.

URL

The URL for this particular API endpoint is https://api.machinemetrics.com/reports/production.

Method

Every web request has a method associated with it in addition to its URL. When you go to a website like https://www.google.com, the first request is a GET request — the HTTP verb that is being used (or its method) is GET. For the Production API endpoint, a POST method is used so we can take advantage of the body portion of the request which we'll get to momentarily.

Headers

Every web request also contains headers. These are used to provide authentication information, tell the server what type of format the response should be in, or other meta data that are needed to process the request.

All of our endpoints require 2 headers: Authorization and Content-Type. The value of the Authorization header is Bearer API_KEY.

Body

The body is where you supply your query.

For this case, the body should look like the following:

{
    "start": "2014-01-01T00:00:00Z",
    "end": "2019-05-05T00:00:00Z",
    "groupBy": [{ "group": "machine" }],
    "data": [{ "metric": "timeInCycle" }]
}

Every query requires a time range. It doesn't really make sense for this particular use case, but if we choose a start date far enough into the past, we can get a picture of the overall in-cycle time across the entire period of time that a machine was monitored with our product. These times must be in ISO 8601 format. If you do not include a timezone offset, UTC will be assumed.

  • start - some date far enough in the past to capture the entire range of time that the equipment was monitored by MachineMetrics.
  • end - set this to tomorrow so we get all of the data in our system and don't crop any off the end.
  • groupBy - this is how the data will be segmented. For the use case of getting in-cycle data for every machine, we must group by the machine entity.
  • data - this is an array of all the different data items you're interested in. In this case, we're only interested in timeInCycle. This represents the number of milliseconds that a machine was in-cycle (this can be thought of as actively running a program).

Example

Request

Below is an example of how to perform this query using a tool called cURL. There is an additional example of an asynchronous C# static method (this example uses Newtonsoft's Json.NET package to generate the payload, which can be found here).

Note that you must replace API_KEY with the one you got from the Getting Started section above. Further to ensure safety and security of your API Keys, avoid storing them in your codebase; instead consider setting them as environment variables and reading those environment variables from your program.

cURL
curl -X POST \
  https://api.machinemetrics.com/reports/production \
  -H 'Authorization: Bearer API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "start": "2014-01-01T00:00:00Z",
    "end": "2019-05-05T00:00:00Z",
    "groupBy": [{ "group": "machine" }],
    "data": [{ "metric": "timeInCycle" }]
}
C#
using System;
using System.Text;
using System.Net.Http;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class MMAPI {
  public static async Task requestMachineMetricsUtilizationReport() {
      var payload = new JObject();
      payload["start"] = "2014-01-01T00:00:00Z";
      payload["end"] = "2019-05-05T00:00:00Z";
      JObject groupBy = new JObject();
      groupBy["group"] = "machine";
      payload["groupBy"] = new JArray(groupBy);
      JObject data = new JObject();
      data["metric"] = "timeInCycle";
      payload["data"] = new JArray(data);

      var payloadString = JsonConvert.SerializeObject(payload);
      var response = await MMAPI.requestMMAPI("/reports/production", "Bearer API_KEY", payloadString, HttpMethod.Post);
      Console.WriteLine(response);
  }

  //This requestMMAPI method can be passed any of our valid endpoints (assuming proper credentials with your API Key). In combination with a JSON library, it's possible to easily build out a custom api access interface
  static async Task<string> requestMMAPI(string path, string apiKey, string payload, HttpMethod httpMethod) {
      var baseUrl = "https://api.machinemetrics.com";
      var client = new HttpClient();
      var request = new HttpRequestMessage(httpMethod, $"{baseUrl}{path}");
      request.Headers.Add("Authorization", apiKey);
      request.Content = new StringContent(payload, Encoding.UTF8, "application/json");
      var response = await client.SendAsync(request);
      var resultContent = await response.Content.ReadAsStringAsync();
      return resultContent;
  }

// This static method (requestMachineMetricsUtilizationReport) can then be invoked asynchronously elsewhere like this:
using static MMAPI;
class Program{
  static void Main(){
    MMAPI.requestMachineMetricsUtilizationReport().Wait();
  }
}

Response

Below is what you'll get back from the above query. This is a long block with lots to unpack, so before scrolling down, we'll walk through each section:

Property Description
range This is basically an echo back of the time range that was provided in the query. However, due to how the data is stored, we might not have the exact time periods requested. This range will indicate that data for a wider range of time was captured than was originally requested.
csv If the request included csv: true, this section will provide you with a URL to retrieve the data in CSV format along with the timestamp of when that link expires.
aggregate This section includes every metric requested rolled up across the entire data set.
entities This is a list of every entity type along with information that can be used for display purposes. This reduces the amount of redundancy in the data set.
items This is a nested set of arrays based on the grouping provided in the requested query. In this case, we only grouped by "machine" so there is only one layer to the items block. Each item has an entity and an aggregate. The entity has a type and ID which can be used to look up the name in the entities block. The aggregate is a hashtable of all the data metrics requested with their respective values which are rolled up for the given grouping.
{
    "range": {
        "start": "2014-01-01T00:00:00.000Z",
        "end": "2019-05-05T00:00:00.000Z"
    },
    "csv": {
        "url": null,
        "expires": null
    },
    "aggregate": {
        "timeInCycle": 3404990284
    },
    "entities": {
        "machine": {
            "c37b9f9f-cb70-47b0-ac89-1cff25024cb8": {
                "id": "c37b9f9f-cb70-47b0-ac89-1cff25024cb8",
                "name": "CNC 1"
            },
            "dd942a48-67be-4bc5-9d34-281c9554183a": {
                "id": "dd942a48-67be-4bc5-9d34-281c9554183a",
                "name": "CNC 2"
            },
            "f0758dea-7277-4561-b337-3e8489ffb6ed": {
                "id": "f0758dea-7277-4561-b337-3e8489ffb6ed",
                "name": "CNC 3"
            },
            "cbca14c6-ed91-4bac-99a2-ff339e66c818": {
                "id": "cbca14c6-ed91-4bac-99a2-ff339e66c818",
                "name": "CNC 4"
            }
        }
    },
    "items": [
        {
            "entity": {
                "type": "machine",
                "id": "c37b9f9f-cb70-47b0-ac89-1cff25024cb8"
            },
            "aggregate": {
                "timeInCycle": 2807065907
            }
        },
        {
            "entity": {
                "type": "machine",
                "id": "dd942a48-67be-4bc5-9d34-281c9554183a"
            },
            "aggregate": {
                "timeInCycle": 597856520
            }
        },
        {
            "entity": {
                "type": "machine",
                "id": "cbca14c6-ed91-4bac-99a2-ff339e66c818"
            },
            "aggregate": {
                "timeInCycle": 67857
            }
        },
        {
            "entity": {
                "type": "machine",
                "id": "96ace055-bb5a-4345-afdb-705adb59ee96"
            },
            "aggregate": {
                "timeInCycle": 0
            }
        }
    ]
}

Aggregates

Operations for querying warehouse data via the various reporting apis.

Retrieve production metrics

Retrieve selected data metrics rollups for a given time frame.

Authorizations:
bearerAuth (reporting)
Request Body schema: application/json

Production Report Request Object

One of
  • withTimestamp
  • withShopDay
start
required
string <date-time>

Must be a valid ISO 8601 date-time format (e.g., "2017-07-19T10:00:00Z"); start must be before end

end
required
string <date-time>

Must be a valid ISO 8601 date-time format (e.g., "2017-07-19T10:00:00Z"); end must be after start

data
required
Array of objects

The data metrics provided are aggregated up to each level of grouping. If no groupBy is provided, the requested data metrics will roll up to the company level.

Example usage:

data: [ { "metric": "totalParts" }, { "metric": "timeInCut" } ]
groupBy
Array of withHours (object) or (withoutHours (withWeeks (object) or withoutWeeks (object)))

Groups and aggregates the data metrics requested in the data array in the order provided. Grouping is always optional. If no groupBy is provided, data metrics get aggregated to the company level.

Example usage:

groupBy: [ { "group": "machine" }, { "group": "day" } ]

This will group and aggregate your selected data metrics by machine, and additionally for each machine, it will provide a rollup of each day for that metric.

filter
object

Filters your query to include results for the items whose id is supplied in each respective array only. If the array is not supplied, or is empty, no filtering will be done on that item.

csv
boolean

When true, will provide a download link (and expiry) for csv. Must append a user-token to the link in order to download.

See operations for JWT generation and jwtAuth securities definition for more information.

flatten
boolean

When true, the items array will contain the deepest leaves with any entity information applied to every item.

Responses

200

Selected production data metrics rollups for a given time frame

401

Unauthorized

403

You do not have permission to access this resource

404

The specified resource was not found

post /reports/production
https://api.machinemetrics.com/reports/production
https://api-demo.machinemetrics.com/reports/production

Request samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "start": "2017-07-19T10:00:00Z",
  • "end": "2017-07-21T10:00:00Z",
  • "data":
    [
    ],
  • "groupBy":
    [
    ],
  • "filter":
    {
    }
}

Response samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "range":
    {
    },
  • "aggregate":
    {
    },
  • "entities":
    {
    },
  • "items":
    [
    ]
}

Retrieve downtime metrics

Retrieve downtime (ms) rollups for a given time frame.

Authorizations:
bearerAuth (reporting)
Request Body schema: application/json

Downtime Report Request Object

start
required
string <date-time>

Must be a valid ISO 8601 date-time format (e.g., "2017-07-19T10:00:00Z"); start must be before end

end
required
string <date-time>

Must be a valid ISO 8601 date-time format (e.g., "2017-07-19T10:00:00Z"); end must be after start

groupBy
Array of objects

Groups and aggregates the downtimeMs in the order provided. Grouping is always optional. If no groupBy is provided, downtimeMs gets aggregated to the company level.

Example usage:

groupBy: [ { "group": "reason" }, { "group": "machine" } ]

This will group and aggregate downtimeMs by downtime reason, and additionally for each machine, it will provide a rollup of each day for that metric.

filter
object

Filters your query to include results for the items whose id is supplied in each respective array only. If the array is not supplied, or is empty, no filtering will be done on that item.

csv
boolean

When true, will provide a download link (and expiry) for csv. Must append a