Table of Contents

Defining a new API

To create a new API, follow these steps as detailed below:

  1. Create the API Automation script
  2. Create the API definition(s) and token(s)
  3. Configure the UserDefinableApiEndpoint extension module
Note

This is the recommended workflow when creating new APIs using new scripts. If you want to use an existing script for the API, see Using existing scripts.

Creating the API Automation script

To define an API, you will need an Automation script that contains the logic of the API. This Automation script needs the OnApiTrigger entry point method, which will be executed when the API is triggered. The entry point should look like this:

using Skyline.DataMiner.Automation;
using Skyline.DataMiner.Net.Apps.UserDefinableApis;
using Skyline.DataMiner.Net.Apps.UserDefinableApis.Actions;

public class Script
{
    [AutomationEntryPoint(AutomationEntryPointType.Types.OnApiTrigger)]
    public ApiTriggerOutput OnApiTrigger(IEngine engine, ApiTriggerInput requestData)
    {
        var method = requestData.RequestMethod;
        var route = requestData.Route;
        var body = requestData.RawBody;

        return new ApiTriggerOutput
        {
            ResponseBody = $"Received {method} request for route: '{route}' with body: '{body}'",
            ResponseCode = (int) StatusCode.Ok,
        };
    }
}
Note
  • When developing the API script in DIS, make sure to update the Skyline.DataMiner.Dev.Automation NuGet package to its latest version so the types of the User-Defined APIs feature are available.
  • The Run method is not required in the script, but the entry point method must reside in the Script class, just like in any other DataMiner scripts.

Input

The entry point method has two parameters.

  • The IEngine object can be used to interact with the DataMiner Automation engine.

  • The ApiTriggerInput is an object that contains information about the API trigger. It has the following properties:

    Property Type Description
    RequestMethod RequestMethod The HTTP method of the request. See RequestMethod.
    Route string The suffix of the URL that this API call is triggered with. Having this available makes it possible to reuse the same script for different routes. See Route.
    RawBody string The full body of the HTTP request as a string. This can be deserialized and used in the script. See User input data.
    Parameters Dictionary<string, string> Contains the deserialized parameters if you select Dictionary (parsed from JSON) when configuring the API. See User input data.
    Context ApiTriggerContext Contains properties with info about the request. Available from DataMiner 10.3.9/10.4.0 onwards.
    QueryParameters IQueryParameters Contains the request query string parameters. Available from DataMiner 10.4.1/10.5.0 onwards.

ApiTriggerContext

Property Type Description
TokenId Guid Contains the ID of the ApiToken with which the API is triggered. Available from DataMiner 10.3.9/10.4.0 onwards.

RequestMethod

You can use the RequestMethod property to check the HTTP method of the trigger. It can contain the following values:

  • Get
  • Put
  • Post
  • Delete

This makes it possible to define the four CRUD (create, read, update, delete) actions in one script. If one or more methods should not be used, you can return a status code 405 (see ResponseCode).

User input data

There are two ways to pass data to the API:

  • You can use query parameters, which allow you to pass data in a key-value format.
  • You can use the request body, which you can either deserialize yourself in your script, or you can have deserialized to a key-value format by the built-in deserialization.
Query parameters

Query parameters are available in the QueryParameters property in the ApiTriggerInput. IQueryParameters exposes the following methods:

Method name Return type Summary
TryGetValues(string key, out List<string> values) bool Tries to get the values for the associated key. Returns true in case one or more values are found for the key, and false if not. The values will be in the out parameter.
TryGetValue(string key, out string value) bool Tries to get the value for the associated key. Returns true in case a value is found for the key, and false if not. The value will be in the out parameter. In case there are multiple values, the first value will be returned.
GetAllKeys() List<string> Returns all keys for which there is a value.
ContainsKey(string key) bool Returns whether the key is present or not.
Note
  • Multiple values can be added for one key.
  • Query parameter keys are case-sensitive.
  • The maximum size for the query string is 2 KB.
  • Query parameters are available from DataMiner 10.4.1/10.5.0 onwards.
Request body

There are two ways to pass the request body to the API script if you make use of the OnApiTrigger entry point method. Which way is used depends on the selected option in the dropdown when you define the API in Cube. See Creating the API definition(s).

  • If Dictionary (parsed from JSON) is selected, the JSON body of the HTTP request will automatically be converted to a Dictionary<string, string> in the Parameters property of the ApiTriggerInput object. In the RawBody property, the raw string body will remain available.

    Note

    Note that only JSON in the form of key-value pairs is accepted as parameters. For example:

    {
        "userName" : "JohnDoe",
        "limit" : "10"
    }
    
  • If the default option Raw body is selected, the Parameters property will contain an empty Dictionary<string, string>. In this case, you will need to take care of the deserialization of the raw body string which can be found in the RawBody property.

Tip

To see how these two options are used in an API script, see API script examples.

Route

The route describes the URL route where the API will be available. It is a suffix that comes after the base URL {hostname}/api/custom/.

  • The route must not start or end with a forward slash (/).
  • The route must be unique for each API definition. When it is saved, DataMiner will automatically check this to prevent conflicts.
  • Routes are case-insensitive.

For example, if you want to create an API to retrieve the status of all encoders in your system, a logical route would be encoders/status. The full API call would then look like this:

HTTP GET mydataminer.customer.local/api/custom/encoders/status
Tip

We recommend that you keep routes simple and straightforward. For some great tips on this, refer to restfulapi.net.

Output

The entry point method returns an instance of the ApiTriggerOutput class. This will be used to determine the response to the API caller.

The ApiTriggerOutput object has the following properties:

Property Type Description
ResponseCode int The HTTP status code. See ResponseCode.
ResponseBody string Contains the response body as a string. The size of this response body is limited to 29 MB.
Note

A valid output instance always has to be returned.

ResponseCode

The status of the API trigger request is reflected in the ResponseCode property of the ApiTriggerOutput. This is an integer, so any valid HTTP status code can be passed here.

You can also use the StatusCode enum, which contains suggestions, and cast that to an integer. These are the values of the enum:

Name Value Description
Ok 200 The request got executed successfully.
Created 201 The request succeeded, and a new resource was created as a result.
Accepted 202 The request was received, but not executed yet. Could be used for long-running async actions.
NoContent 204 There is no content to return for the request, but the request did succeed.
BadRequest 400 There was a client error, e.g. wrong parameters.
NotFound 404 The requested document was not found.
MethodNotAllowed 405 The HTTP method is not valid for this request. For example DELETE is used while GET was expected.
InternalServerError 500 Return this if something went wrong in your Automation script, e.g. you try to write to a file, but the file is in use by another application.
Tip

For more insight into which HTTP status codes to use in which circumstances, see HTTP status codes.

Creating an API and tokens in DataMiner Automation

Note
  • Before you try to execute this procedure, make sure you have the user permissions available under Modules > User-Defined APIs.
  • You can also create an API and tokens directly in code, for example if an API setup needs to be deployed in the install script of an application package. See Creating APIs and tokens in code.
  1. Open your API script in the Automation module in DataMiner Cube and click Configure API at the bottom of the window.

    This will open a window where you can create the API.

    Creating an API
    Creating an API in DataMiner 10.3.6

    Note

    You will only be able to see the button Configure API in the UI if the following conditions are met:

    • You are using DataMiner 10.3.6 or higher.
    • The DataMiner System has an active Indexing Engine (e.g. Elasticsearch).
    • You have the permission to read API definitions.
  2. Add a description (optional).

  3. In the URL box, specify the unique route.

  4. If you want to parse the JSON body of the HTTP request to a dictionary, make sure Dictionary (parsed from JSON) is selected. See User input data.

    Note

    Leave Method to be executed set to the default selection. This option should only be changed for legacy scripts without the OnApiTrigger entry point. See Using existing scripts.

  5. Under Tokens, select the tokens that need access. You can also create new tokens using the New token button.

    Note

    At least one token has to be linked before the API will be usable.

    Caution

    Once a token is created with a specified secret, it is not possible to retrieve that secret again. The value is stored securely in the database with a non-reversible hashing function. Make sure to save it somewhere secure or pass it in a secure way to the API user.

Note

You can change your API configuration at any time on the User-Defined APIs page in System Center. Alternatively, you can also open this window in the Automation module again to change the settings.

Configuring the UserDefinableApiEndpoint extension module

Make sure the UserDefinableApiEndpoint DxM has been configured to match your API needs. For more information, refer to UserDefinableApiEndpoint configuration.

If you have already configured the DxM, there is no need to repeat this step for each user-defined API you create.