Back to top

Knowledge Model Management API User Tutorial

Introduction

The purpose of this document is to describe the REST API of the Knowledge Model Management application. The intended audience for this document includes anyone who is interested in programmatically interacting with the Knowledge Model Management server application.

Authorisation

Any call from an external client will require authentication by the presence of a security token. Such a token must currently be generated manually. Token generation process is different depending on how Semaphore is hosted.

Semaphore Cloud token generation

All Semaphore Cloud interfaces require an API key be used to generate a session token that is used in every request.

Generating an API key

From the Semaphore Cloud, select the “Account Settings” option from under your user menu (in the top right corner) then press the “Re-generate Api Key” link or use the one currently displayed if it has previously been generated. A few things to note:

  • If you generate a new API key the previous API key will be invalid and cannot be used.

  • The API key is user specific so if the user is inactive, deleted or their permissions altered in such a way to prohibit access to the APIs, their API key will no longer function.

Generating a session token

An application wishing to access any of the Semaphore Cloud API interfaces must do the following:

  1. Use the API key to generate a session/access token - This involves submitting a POST request to “https://cloud.smartlogic.com/token” with parameter “grant_type” with a value of “apiKey” and a “key” parameter containing the API key. The token generated is valid for 14 days though it is recommended that any automated processes always re-generate the session token.
  2. Execute the relevant API calls with the session/access token in the “request header” - The request header key is “Authorization” and the syntax for the key value is “bearer ” (the ”” generated from the previous step).

Server-hosted Semaphore token generation

To generate the token, a user must first log into the Knowledge Model Management application and enter any model. (It doesn’t matter which model as the token generated will contain the user’s permissions for all models.)

Once logged in, accessing the following URI:

http://[Studio application url]:[Studio application port]/api/token?lifeTime=[time in seconds]

will return:

{“tokenId”: [generated token]}

The parameter “lifeTime” determines for how long the token will be valid in seconds. E.g. for 24-hour valid token, lifeTime needs to be set to 86400. For one year validity, it should be set to 31536000.

How to use the token

Once the token is generated every call can be authorized by adding “x-api-key”: [generated token] pair to the request header.

Alternatively you can embed the token in the REST URL as follows. However, from Semaphore 5.10.2 forwards, you need to explicitly enable this functionality in Studio by adding the parameter “studio.auth.tokenInsideUrl=true” to the studio-authentication.properties file.

http://[Studio application url]:[Studio application port]/t/[generated token]/kmm/api/[api call part]

E. g. the authorised call to get task count from model “Foo model” would have the following look:

http://[Studio application url]:[Studio application port]/t/[generated token]/kmm/api/sys/model:Foo-model?properties=meta:meta/(meta:hasTerm)/meta:count

Note, however, that this method can lead to very long URLs that may not be accepted by some proxied services.

API Tutorial

For all examples in this tutorial it is assumed that in the KMM application we have authorised access to model “Demo Model” (with id model:Demo-Model) The basic URL for all operations described below is:

http://[Studio application url]:[Studio application port]/kmm/api/model:Demo-Model

Sometimes we will also need following url:

http://[Studio application url]:[Studio application port]/kmm/api/sys/model:Demo-Model

We are going to use this url if we need to get model meta data, that are not connected with model’s Concept/ConceptScheme structure. We will refer to this url as basic meta URL

Please note, this tutorial is aimed at enable you to create the REST calls as detailed in the Blueprint files. These files provide the details for all API requests that are available. This tutorial just shows how to implement a few of the simpler calls. The intention is that although the code here is written in Java, the combination of these examples and the Blueprint files should be enough information to generate calls in any language.

We’ve developed a library that implements many of these functions - it is available at Semaphore-OE-Client. Please feel free to download and play with this code - or use it in your projects. It is available from Maven Central - see: https://mvnrepository.com/artifact/com.smartlogic.oeclient/Semaphore-OE-Client.

Adding a new concept scheme

Let’s create a concept scheme “Foo Concept Scheme” that has an URI http://example.com/demo-model#Foo-Concept-Scheme

To add a new concept scheme we need to provide:

  • the URL (basic URL + “/skos:ConceptScheme/rdf:instance”) to which the POST request is sent

  • the concept scheme label “Foo Concept Scheme”

  • the concept scheme URI (optional, it will be generated from the label if not provided)

JSON-LD that would be send should look as follows:

{ “@id”: "http://example.com/demo-model#Foo-Concept-Scheme", “@type”: [“skos:ConceptScheme”], “rdfs:label”: “Foo Concept Scheme” }

Possible response codes are:

  • 201 in case of success

  • 409 in case of constraint violation (if e. g. concept scheme of this URI already exists)

Adding a new concept to concept scheme

Let’s create a concept with URI "http://example.com/demo-model#Foo-Bar-Concept" and name “Foo Bar Concept” (in English).

To add a new concept scheme we need to provide:

  • the URL (basic URL) to which the POST request is sent

  • the concept label “Foo Bar Concept” and its language code

  • the concept scheme URI (optional, it will be generated from the label if not provided)

  • the concept scheme to which it is related in via the “skos:topConceptOf” relation

  • the concept type list (“skos:Concept” should be on the list)

JSON-LD that would be send should look as follows:

{ “@id”: "http://example.com/demo-model#Foo-Bar-Concept“, “@type”: [“skos:Concept”], “skos:topConceptOf”: {”@id": "http://example.com/demo-model#Foo-Concept-Scheme"}, “skosxl:prefLabel”: [ { “@type”: [“skosxl:Label”], “skosxl:literalForm”: [{ “@value”: “Foo Bar Concept”, “@language”: “en” }] } ] }

Possible response codes are:

  • 201 in case of success

  • 409 in case of constraint violation (if e. g. concept of this uri already exists)

Adding a new concept to another concept

It is easy to use the example above to create a concept that is related to another concept. The only difference is that instead of passing a concept scheme URI, we pass the URI of the concept to which our new concept will be related hierarchically. This means that we are going to use “skos:narrower” relation instead of “skos:topConceptOf”.

JSON-LD that would be sent should look as follows:

{ “@id”: "http://example.com/demo-model#Foo-Bar-Baz-Concept“, “@type”: [“skos:Concept”], “skos:narrower”: {”@id": "http://example.com/demo-model#Foo-Bar-Concept"}, “skosxl:prefLabel”: [ { “@type”: [“skosxl:Label”], “skosxl:literalForm”: [{ “@value”: “Foo Bar Baz Concept”, “@language”: “en” }] } ] }

Attaching transaction message to transaction

There are two ways to specify transaction message:

  • sending text in “X-Transaction-Message” header

  • sending specific json in “X-Transaction-Message” header

The former case is simple one. The text from the header will directly become a transaction message.

In latter case the of the header should be a valid JSON with two keys:

  • “templateKey” to specify message template

  • “params” to specify parameters the template requires

Eg. the transaction message for creating a new concept will look as follows:

{ “templateKey”: “concept-multiple-added”, “params”: [1, [http://example.com/demo-model#Yet-Another-Foo-Concept]] }

In this case we could also use “concept-added” templateKey but then we would not see details of the added concept in history list as “concept-added” does not take any parameters.

List of templates for transaction messages can be found here

There are relevant examples in simple demo maven project

Getting concept details

Let’s get some details of “Foo Bar Concept” that has an URI http://example.com/demo-model#Foo-Bar-Concept

To get details of the concept we need to provide:

  • the URL (basic URL + encoded concept URI) of which the GET request is made

If the request is sent with no parameters only the concept URI (@id) is returned. In order to retrieve more details we need to pass “properties” parameter and specify there what we need in return. There is a special notation to be used to specify what we need to retrieve.

  • commas are used to separate properties we want to retrieve

  • “/” are used to give more details of a specific property

E.g. to retrieve a concept’s preferred labels we can set properties to

properties=skosxl:prefLabel

However this way we will get only URI of preferred labels. In order to get labels values we need to retrieve their display names

properties=skosxl:prefLabel/meta:displayName

We can use comma to get also concept’s type and display name

properties=skosxl:prefLabel/meta:displayName,rdf:type,meta:displayName

Finally, this is how to get all properties of the concept.

properties=[]

Please refer to API documentation for more examples.

Possible response codes are:

  • 200 always

It is not obvious how to verify that the resource exists. Getting the resource details will always result in response code 200 (not 404). The proper way to verify if the resource exists is to try to get all of its properties. A non-existent resource will have no properties except id. Concept is a resource, but there is a more efficient test for its existence. It is sufficient to check if it has rdf:type property set to skos:Concept.

Getting concept history (changes list)

Let’s get list of changes for “Foo Bar Concept” that has an URI http://example.com/demo-model#Foo-Bar-Concept

To get the changes of the concept we need to provide:

  • the URL (basic meta URL + “/teamwork:Change/rdf:instance”) of which the GET request is made

Mind we are using basic meta URL this time.

By default only change ids are returned. To retrieve more changes’ details we need to pass “properties” parameter as in the example for getting concept details above. If we want to get the author, date and transaction message we need to set parameters to:

properties=dcterms:created,sioc:has_creator/meta:displayName,meta:transactionMessage,teamwork:subject

By default we are getting back in reply all changes for the model. Parameter “filters” can be used to specify expression filtering query results. As we want to get results related only to our concept, we can set the filter as follows:

filters=subject(sem:about = http://example.com/demo-model#Foo-Bar-Concept)

We can narrow down the results by adding more filters:

by date:

subject(dcterms:created > “2015-10-28T12:46:09.144Z”^^xsd:dateTime)

by author:

subject(sioc:has_creator=user:Administrator)

by predicate:

subject((teamwork:added|teamwork:deleted)/teamwork:predicate=skos:broader)

by concept class:

subject(sem:about/rdf:type=${api.test.prefix}:City)

by concept subclass:

subject(sem:about/rdf:type/rdfs:subClassOf*=skos:Concept)

by language:

subject((teamwork:added|teamwork:deleted)/teamwork:object contains “*”@en)

with no language:

subject((teamwork:added|teamwork:deleted)/teamwork:object contains “*”@)

Parameter “sort” can be used to determine how do we want to have the results sorted. For chronologically decreasing order it should be set to:

sort=-dcterms:created

There is also a paging support available. Parameter “offset” can be used to specify the index of history record we want to start getting results from. Parameter “limit” can be used to specify how many records maximum we would like to have in query result. Following setting will return maximum 10 first changes:

offset=0 limit=10;

Possible response codes are:

  • 200 in case of success

  • 404 if model not found

Now we can ask for triples included in particular change. In order to fetch this information we must provide change uri:

  • the URL (basic meta URL + “/{changeUri}”) of which the GET request is made

The following will calculate counts for deleted and added triples:

properties=meta:meta/teamwork:added/meta:count,meta:meta/teamwork:deleted/meta:count

When we want to display details of triples included in particular change, use the uri:

  • the URL (basic meta URL + “/{changeUri}/teamwork:added|teamwork:deleted”) of which the GET request is made

…and properties:

properties=^teamwork:added,?bNode/meta:displayName&offset=0&limit=50

It is recommended to use limit and offset parameters to avoid potential performance & memory issues.

Frontend displays change summary (“Resource”) information for each change. It is calculated on base of data retrieved in such way:

  • the URL (basic meta URL + “/{changeUri}”) of which the GET request is made

…and additional parameters:

properties=innerLimit=100&noInnerSort=true&properties=sem:about/(meta:displayName|meta:transitiveSubPropertyOf|meta:transitiveType|meta:transitiveSubClassOf)

It is important to use noInnerSort=true flag, to avoid performance issues for large changes.

Changing concept name

Let’s change name of “Foo Bar Concept” to “Baz Concept”. This operation is same as changing the preferred label value.

To change the concept label we need to provide:

  • the URL (basic URL + preferred label URI) to which the PATCH request is sent

  • the old concept name “Foo Bar Concept”

  • the new concept name “Baz Concept”

JSON-LD that would be send should look as follows:

[ { “op”: “test”, “path”: “@graph/0/skosxl:literalForm/0”, “value”: { “@value”: “Foo Bar Concept”, “@language”: “en” } }, { “op”: “replace”, “path”: “@graph/0/skosxl:literalForm/0”, “value”: { “@value”: “Baz Concept”, “@language”: “en” } } ]

Note, we could use the same method to change the language of the preferred label.

Possible response codes are:

  • 200 if the request was successful

  • 409 in case of constraint violation

Deleting concept

Let’s delete “Baz Concept”. The URI of the concept is still "http://example.com/demo-model#Foo-Bar-Concept" as changing the concept name does not change its URI.

To delete the concept we need:

  • URL (basic URL + concept URI) to which the DELETE request sent

We also need to pass “mode” parameter with the request. This is necessary to indicate what should be done with concepts in the sub-tree of the concept we are removing. The parameter is required. The possible values are:

  • “empty” to remove a concept that does not have children

  • “reattach” to attach the direct child of the deleted concept the its parent

  • “withSubtree” to remove concepts from sub-tree (unless they are attached also somewhere else)

Please refer to API documentation for more details.

Possible response codes are:

  • 204 in case of success

  • 400 and type set to “validation.conceptNotEmpty” if concept has children

Full API Reference

Generated by aglio on 19 Dec 2025