API Documentation

1 About the API

1.1 General API notes

OS2autoproces exposes a series of APIs, and this documentation is intended for developers building a frontend application on top of these APIs.

As the APIs are being developed in parallel with the frontend, each API is clearly labeled with the current state of the API. These states can be

  • Final. The API is finished according to the current requirement specification. Change requests from the customer may affect this API, but otherwise it can be assumed to be as stable as is possible during a development project.
  • Stable. The API is working as intended, but there may still be a few changes to the fields (a field may be added or a field removed, and a type on a field may change, or similar minor changes)
  • Experimental. The API is being actively developed, and behavior may change without notice. It is possible to use the API, but it should only be done for experimental purposes.
  • Planned. The API is planned - documentation is probably non-existent besides the note about the API being planned.

1.2 Unsecured endpoints

OS2autoproces exposes a set of APIs that are unsecured, meaning they can be called without being logged into the application. All unsecured APIs are exposed at the following base-address (each actual API has an endpoint located below this base-address).

https://www.os2autoproces.eu/public

All Unsecured endpoints are read-only, and are used for retrieving information useful for displaying in the UI, or dealing with the login process or similar flows that happens before the user is logged in.

1.3 Generated secured endpoints

OS2autoproces makes use of the Spring Data REST framework to generate CRUD-like APIs for many of the entities being handled by the backend. These APIs can be configured to some extend, but there are limitations to what can be be customized, and as such, these APIs all follow the same usage-pattern.

The generated APIs are secured by a SAML-based login mechanism, which means that before calling any of these APIs, a login-flow must have been completed successfully, which results in a cookie being issued by the backend, which the client/browser must supply on all calls to these APIs.

Where relevant, the users identity is always derived from the session, and is never supplied by the frontend when calling the API. In the same way, data is automatically filtered on the way out, so if/when a user performs a search/read operation on data, where the user only has access to some of this data, the rest is filtered away - the frontend does not need to perform any data-filtering or security checks with regards to access to data (but should do security checks for functionality, so actions are not exposed to the user, which the user cannot perform anyway)

1.4 Custom secured endpoints

In the cases where the restrictions of the Spring Data REST framework is a limiting factor, custom APIs are implemented in OS2autoproces. These APIs does not offer the same CRUD-like operations of the Spring Data REST APIs, but are limited to exactly the operations required by the functionality in the frontend.

The custom APIs can be modified much more easily than the generated ones, so where needed, there is some flexibility in the development proces for these APIs.

All of these APIs are secured in the same way as the generated APIs.

2 Security

2.1 About CSRF and CORS

The backend exposes a series of API operations that gives access to sensitive information, as well as allows updating and creating data. These operation are secured by ordinary access control mechanisms, requiring SAML-based authentication of the end-user.

These mechanisms only prevents unauthorized users from accessing the API, it does not protect against malicious parties tricking the authorized users into performing API with "evil" payloads.

CORS and CSRF protection are two elements that attempt to hinder these types of attacks, and both are enabled on the backend.

How does this affect the frontend?

The CORS configuration will inform the web-browser that it must not perform javascript-based calls to the API, unless the call originates from HTML hosted on specific web-addresses. The backend is configured with a list of legal web-addresses, and it will inform the end-users browser about this, so the browser will block the call to the API.

As long as the web-address that hosts the frontend, is known by the backend, CORS will not be an issue with regards to calling the API. The frontend framework may have to be configured to run in "CORS-mode", though this is framework specific.

The CSRF protection on the backend requires a bit more work on the frontend. The backend will send a couple of headers back containing CSRF information, that the frontend must supply on all requests. The response headers are the following:

X-CSRF-HEADER: X-CSRF-TOKEN
X-CSRF-PARAM: _csrf
X-CSRF-TOKEN: af45908f-a262-4e6e-ad43-85d272fb4cf7

The only value that is important to handle is the X-CSRF-TOKEN response header. It contains the session specific CSRF token, that must be supplied as a request header in all non-GET calls to the API, like this (note the headername is X-CSRF-TOKEN and the value is the one returned in the response header)

X-CSRF-TOKEN: af45908f-a262-4e6e-ad43-85d272fb4cf7

The easiest way to get the X-CSRF-TOKEN value is probably to call the /pubic/whoami endpoint right after a user has successfully logged in, as the response will contain the mentioned header.

2.2 About SAML

The end-users can only access the front-page of OS2autoproces without being signed into the application. All actual functionality requires that the application knows who the user is, and can tie that user to organizational data found in the application.

OS2autoproces uses SAML as the authentication mechanism, as it is easy to implement, fully supported by all municipalities, supports the concept of roles, and finally because it is a federation technology that allows OS2autoproces to push the actual authentication process to the municipalities own internal it-infrastructure, thus reducing development and operation costs for the solution.

The SAML login flow happens roughly as outlined below

  1. The login process is triggered. This can happen either explicitly (the user actively tries to login), or implicitly (the user tried to access a protected resource, and was rejected due to an invalid/expired session). When this happens, the frontend will likely store (cookie, local storage or some other mechanism) whatever resource that the user attempts to access, so the user can be navigated back to that "page" after a successful login.
  2. The users browser is redirected to the "discovery page" at the KOMBIT support system "Adgangsstyring for brugere".
  3. The "discovery page" asks the user which municipality he or she is coming from (the discovery page allows the end-user to store this choice in a cookie, and not ask the user on the next visit, but just skip directly to the next step)
  4. This step is out of scope of OS2autoproces - here the user performs the actual login in their local it-infrastructure - if this succeeds, the user is redirected back to a login-handler on the OS2autoproces backend, which establishes a session with the user, and issues a HTTP cookie, which the user stores in his or her browser
  5. The backend then redirects to the user to a pre-configured login-handler page on the frontend, which will perform any post-login code (like calling /public/whoami - getting information about the end-user, and retrieving a fresh CSRF token), and finally send the user to the page the user originally intended to visit (looking up that information in a cookie, localStorage or similar mechanism).

2.3 Temporary Development Setup

To support development, Syddjurs Municipality has allowed us to setup a SAML Identity Provider in the KOMBIT infrastructure which uses their CVR number. Below are the users that can login using this infrastructure

  • itminds1@digitalidentity / Test1234 (has the role ROLE_SUPERUSER)
  • itminds2@digitalidentity / Test1234 (has the role ROLE_FRONTPAGE_EDITOR)
  • itminds3@digitalidentity / Test1234 (has the role ROLE_ADMINISTRATOR)

The login flow works as outlined below

  1. Access a protected resource on the backend (or navigate directly to https://www.os2autoproces.eu/saml/login)
  2. If a protected resource is requested, and no session exists, the backend will respond with HTTP 302, and a Location header containing the KOMBIT login page - if the /saml/login page is navigated to, the browser will automatically redirect to the KOMBIT login page
  3. The browser is redirected to the KOMBIT discovery page - here pick "OS2autoproces (Syddjurs)"
  4. The browser is now redirected to an AD FS login page - login using the supplied username/password
  5. The browser is then returned to the OS2autoproces backend, which will redirect the browser back to the frontend (preconfigured login page)

To trigger a logout, simply navigate the browser to this URL - upon succesful logout, the user is returned to the frontend on a preconfigured URL.

https://www.os2autoproces.eu/saml/logout

2.4 Frontend Implementation

The SAML flow is handled by the backend, but the frontend needs to be aware of the interactions that can trigger the flow, as the frontend plays a part in this flow. This chapter outlines the flow that the frontend must implement.

Deal with redirects from the backend

When the frontend performs calls to the backend APIs using javascript, the backend will prevent access to the secured APIs if the user is not currently logged in (the users browser does not supply a valid session cookie - either because it does not have any, or because the session has expired).

When this happens, the backend will return a HTTP 302 (redirect), with a Location header set to the discovery page, expecting the browser to perform an actual navigation to the discovery page, so the user can perform a login.

The frontend must deal with these 302 responses correctly, and instead of redirecting the javascript query to the new location, perform a browser navigation to the discovery page... as the discovery page is a well-known resource, the javascript code could look for this specific endpoint, and perform the browser navigation in that specific scenario, and default to doing javascript query-redirect in all other cases.

Implementing a discovery page

NOTICE. The discovery flow will likely be removed, so wait with this section.

The temporary discovery page on the backend must be replaced by a (much) prettier discovery page on the frontend, and the backend must know the location of this page, so it can return the correct URL in the redirect mentioned above.

The backend exposes a simple API for retrieving a list of municipalities that can login to the solution, which can be used to retrieve a list choices for the end-user. This API should be used to populate the discovery page with choices.

Once the user has chosen which municipality he or she comes from, the discovery page should perform a navigation to the following URL on the backend

https://www.os2autoproces.eu/saml/login?idp=<identifier>

Note that the <identifier> value in the URL should be replaced with the identifier of the municipality that the user chooses. An example is shown below

https://www.os2autoproces.eu/saml/login?idp=http://adfs.digital-identity.dk/adfs/services/trust

Upon successful login, the user is redirected back to some configured endpoint on the frontend application.

2.5 XAPI Security

The frontend accesses the APIs using the logged-in users session, and the user logs in using a SAML login flow. Using the same approach to create an actual system-integration against the APIs is possible, but somewhat cumbersome. But there is an easier way.

Getting access to the APIs without being logged in

There is an API endpoint exposed here /xapi/auth, can can be used to exchange an API Key for a user-session, which grants access to the API's, just as if a super-user had logged into OS2autoproces.

To call this endpoint, the following is needed

  • A REST client (any framework or tool that can call REST endpoints and supports cookies will work)
  • An API Key (contact Digital Identity for an Api Key)

Exchanging the API Key can be done by performing a HTTP POST operation against the /xapi/auth endpoint, in combination with a HTTP Header called ApiKey, containing the actual API Key

			POST https://www.os2autoproces.eu/xapi/auth
			ApiKey: xxxxxxxx
		

If the REST endpoint returns HTTP 200, and a Set-Cookie header, the operation is succesful. The value of the Set-Cookie is the session-cookie that must be used on all calls to the rest of the API.

Note that it is also possible to use the standardized Authorization header like shown below (note the Bearer prefix)

			POST https://www.os2autoproces.eu/xapi/auth
			Authorization: Bearer xxxxxxxx
		

3 Spring Data REST

3.1 Reading objects

Basic queries

Data is read from the APIs using ordinary GET methods, either by accessing the root of the API, or by accessing a specific object by its ID.

Access root of KLE api
GET https://www.os2autoproces.eu/api/kles
Read specific KLE
GET https://www.os2autoproces.eu/api/kles/27.24.27

The output from a basic query either returns a list of objects, or a single object, always matching the datamodel for that specific object-type. When the output is a list of objects, metadata about the result-set is also returned - how this is used is described in the following chapters.

Projections

Getting the objects "plain" datamodel might not always be the most useful output, and the APIs support projections. A projection is a predefined mapping from the objects normal datamodel, to something else. This project can be a small subsets of the fields found in the full datamodel, but it can also be extra fields that are computed or pulled in from other objects.

A single projection can be applied to the output, and the allowed projections are documented in the various API sections. A projection is applied by adding a 'projection' parameter to the request as shown below.

Read a specific process and project it to a different output
GET https://www.os2autoproces.eu/api/processes/7?projection=extended

3.2 Maintaining objects

Spring Data REST is used for generating several of the APIs. When an API is generated, it automatically gets all the features that Spring Data REST supports, including a specific pattern for creating and maintaining objects

The following standard operations are used for creating, updating and deleting objects through the generated APIs, and for all of them, the Content-Type "application/json" is used.

  • POST. This operation is always used for creating new objects - the operation targets the root API endpoint for the given entity (e.g. /api/processes)
  • PUT. This operation can be used to update an existing object, and as input, the full (updated) object must be supplied in the body. The input overwrites the existing object in the backend. The operation targets the root API endpoint + the id of the entity to be updated (e.g. /api/processes/47)
  • PATCH. This operation can be used to update individual fields on an object. The body contains a partial object, and the backend updates the fields supplied in the body, leaving all other fields "as-is". The operation targets the same endpoint as the PUT operation.
  • DELETE. This operation can be used to delete a given object, and the operation targets the same endpoint as the PUT operation

It is also possible to use JsonPatch style operations against the Spring Data REST APIs. This is not something that we (Digital Identity) have a lot of experience with, but it is a way to perform multiple PATCH operations in one command, and perform more complex updates than allowed by simple PATCH operations.

For more details on how to use the APIs generated by Spring Data REST, the Spring Documentation can be a good place to go - though the APIs follows a pretty standard approach, so if something seems like the logical way to use the API, it most likely is.

3.3 Working with relationships

Relationships are used solely on the Process, and when using the Process API, the output from a GET on a given Process, will contain a series of links to other objects, examples being the User that reported the Process, the OrgUnit(s) that are associated with the Process, etc.

These relationships can be managed in much the same was as ordinary attributes, except only PATCH operations can be used. Below are shown how to work with both one-to-one relationships like the "owner" on a Process, and one-to-many relationships like "orgUnits" on a Process.

One-to-one relationships

A one-to-one relationships is managed simply by adding a field to the payload with the name of the relationship, and then supplying a URI value that points to the target of the relationship. Notice that the URI is the exact URL that the object can be read through the corresponding API - that means that the URI has the domain-name of the server as part of the URI-value, as shown below.

Change the 'owner' relationship on a given process using PATCH
PATCH https://www.os2autoproces.eu/api/process/501
{
  "owner" : "https://www.os2autoproces.eu/api/users/1009"
}

One-to-many relationships

One-to-many relationships are handled in the same way, but the references are to arrays of objects.

Change the 'orgUnits' relationship on a given process using PATCH
PATCH https://www.os2autoproces.eu/api/process/501
{
  "orgUnits" : [
      "https://www.os2autoproces.eu/api/orgUnits/11",
      "https://www.os2autoproces.eu/api/orgUnits/17",
  ]
}

3.4 Searching

The generated APIs support a wide range of functionality for searching, sorting, paging and other handy operations like that. This section outlines the basics of these.

Note. The various searching, sorting and paging operations can be combined, as needed.

Searching using QueryDSL

The generated APIs all support QueryDSL style search-parameters, meaning that performing a GET operation on the root entity (e.g. /api/processes) can be combined with search-parameters that matches fields in the datamodel. Some examples are shown below

Find all processes with a specific KLE number
GET https://www.os2autoproces.eu/api/processes?kle=27.00.00
Find all processes with a specific KLE number and a high level of uniformity
GET https://www.os2autoproces.eu/api/processes?kle=27.00.00&levelOfUniformity=HIGH

By default, the parameters must be exact matches, but it is possible to setup rules on the backend, that specifices how a match is computed (prefix, suffix, infix match, case insensitive/sensitive, greater than, less than, etc etc). If it turns out that the frontend needs customization like this, please contact Brian to get it setup.

Paging

By default paging is turned on for all the generated API's. This means that the output contains a paging section, that looks like this

{
  "page" : {
    "size" : 20,
    "totalElements" : 207,
    "totalPages" : 11,
    "number" : 4
  }
}

The page section of the output contains information about how many results are shown per page (size), how many elements in total matches the search-criteria (totalElements), how mange pages that results in (totalPages), and what page the output matches (number).

It is possible to navigate the pages, as well as change the page-size, using the following arguments

  • page. What page to retrieve
  • size. How many elements to show per page
Some examples are given below

Navigate to page 7 on the list of processes
GET https://www.os2autoproces.eu/api/processes?page=7
Navigate to page 4 with a page size of 200
GET https://www.os2autoproces.eu/api/processes?page=4&size=200

Sorting

It is also possible to sort the output, either ascending or descending, according to a specific field in the datamodel. Examples are given below

Sort processes by rating, highest ratings first
GET https://www.os2autoproces.eu/api/processes?sort=rating,desc
Sort processes by domain, alphabetical sorting, A before B
GET https://www.os2autoproces.eu/api/processes?sort=domain,asc

3.5 Advanced searching

When performing searches on Processes, sometimes the fields that are part of the query is located inside another object referenced by the Process. An example would be the need to search for all Processes reported by a given User. The QueryDSL syntax allows for search-parameters that matches referenced objects, as shown by the example below

Find all processes reported by the user with the ID 7
GET https://www.os2autoproces.eu/api/process?reporter.id=7

As with all query parameters, they can be combined, so searching for all processes reported by a specific user, which has a specific status, and has been updated after a specific time is also possible, simply by adding more search parameters

4 Public APIs

4.1 Municipality API

Description

Type Status Comment
Unsecured API Stable This API is used by the Discovery Page in the login flow, for finding the list of possible municipalities that can login to the solution

Operations

Fetch a list of municipalities
GET https://www.os2autoproces.eu/public/municipalities
Fetch a single municipality by its CVR number
GET https://www.os2autoproces.eu/public/municipalities/<cvr>

Example output

[
	{
		entityId: "http://adfs.digital-identity.dk/adfs/services/trust",
		name: "Demo Kommune 1",
		cvr: "36074051"
	},
	{
		entityId: "http://adfs-prod.digital-identity.dk/adfs/services/trust",
		name: "Demo Kommune 2",
		cvr: "12345678"
	}
]

Datamodel

Field Type Nullable Description
entityId string no Business key for the identifier. This value should be used when calling the backend to indicate which Identity Provider the end-user picked.
name string no Friendly name that can be displayed in the UI - will contain the name of the municipality.
cvr string no The CVR number of the municipality - is likely not needed in the UI, but is available just in case.

4.2 Who am I API

The purpose of this API is to expose information about the currently logged in user to the frontend, as well as give the frontend an easy way to figure out if the user has a valid session.

Description

Type Status Comment
Unsecured API Stable This API gives information about the currently logged in user

Useful operations

Fetch information about the currently logged in user
GET https://www.os2autoproces.eu/public/whoami

Example output

Output when user is logged in:
{
	"uuid": "3eb85486-361e-4aa6-b2bf-843c810bc95a",
	"email": "psu@digital-identity.dk",
	"name": "Piotr Suski",
	"cvr": "36074051",
	"roles": [ROLE_SUPERUSER,ROLE_FRONTPAGE_EDITOR]
}

Output when user is not logged in:
{
	uuid: null,
	email: null,
	name: null,
	cvr: null,
	roles: []
}

Datamodel

Field Type Nullable Description
uuid string yes Contains the users unique identifier (unique across all municipalities)
email string yes Contains the users email address
name string yes Contains the users name
cvr string yes Contains the CVR number of the municipality that the user comes from
roles array of strings yes Contains an array of roles that that the user has. The list of possible values are
  • ROLE_USER
  • ROLE_LOCAL_SUPERUSER
  • ROLE_SUPERUSER
  • ROLE_ADMINISTRATOR
  • ROLE_FRONTPAGE_EDITOR

5 Generated APIs

5.1 Technology API

Description

Type Status Comment
Generated Secure API Stable This API is intended for managing the Technology classification that is part of one of the change requests from the customer. The API allows for listing all technologies, as well as creating, deleting and editing existing technologies. Note that the API is generated by the Spring Data REST framework.

Useful operations

Note that this is a generated API, so it supports all of the operations that Spring Data REST allows - this list is just the operations that are useful for the frontend. Note that when fetching all technologies, it might be useful to set the size parameter to some very high number, to effectively disable pagination, as the list will likely only have some 50-200 values, and the data-size is very small.

Fetch a list of technologies
GET https://www.os2autoproces.eu/api/technologies
(returns a list of technologies, example given in the subchapter below)
Delete a given technology
DELETE https://www.os2autoproces.eu/api/technologies/<id>
Create a given technology
POST https://www.os2autoproces.eu/api/technologies
{
  "name": "My Technology"
}

Example output

The output follows the standard structure for list-output on generated APIs, meaning that the result comes in the '_embedded' field, and pagination metadata comes in the 'page' field. The result contains an array of (simple) Technology objects, which are described in the datamodel chapter below.

{
  "_embedded" : {
    "technologies" : [ {
      "id" : 1,
      "name" : "BluePrism"
    }, {
      "id" : 3,
      "name" : "RoboCopy v2"
    }, {
      "id" : 2,
      "name" : "UIPath"
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "https://www.os2autoproces.eu/api/technologies{?page,size,sort}",
      "templated" : true
    },
    "profile" : {
      "href" : "https://www.os2autoproces.eu/api/profile/technologies"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 3,
    "totalPages" : 1,
    "number" : 0
  }
}

Datamodel

Field Type Nullable Description
id integer no Unique identifier for the Technology. The value is used as input for the DELETE operation, if a technology needs to be deleted.
name string no The actual technology value. This is the value that should be displayed in the UI when this new classification is used.

5.2 KLE API

Description

Type Status Comment
Generated Secure API Stable This API gives read-only access to the KLE classification

Useful operations

Note that this is a generated API, so it supports all of the operations that Spring Data REST allows (though updating operations are disabled). This list is just the operations that are useful for the frontend. Note that when fetching all KLE values, it might be useful to set the size parameter to some very high number, to effectively disable pagination, as the list will likely only have some 2800 values, and the data-size is very small. Also the data practically never changes (roughly once every 3 months), so it makes sense for the frontend to load all KLE values in the beginning, and then store them locally in the DOM.

Fetch a list of KLE values
GET https://www.os2autoproces.eu/api/kles
(returns a list of KLE values, example given in the subchapter below)
Fetch all FORM values that belong to the KLE identified by the given ID
GET https://www.os2autoproces.eu/api/kles/<id>/forms
(returns a list of FORM values, see the FORM API for the datamodel for FORM)

Example output

The output follows the standard structure for list-output on generated APIs, meaning that the result comes in the '_embedded' field, and pagination metadata comes in the 'page' field. The result contains an array of (simple) KLE objects, which are described in the datamodel chapter below.

{
  "_embedded" : {
    "kles" : [ {
      "code" : "00",
      "name" : "Kommunens styrelse"
    }, {
      "code" : "00.01",
      "name" : "Kommunens styrelse"
    }, {
      "code" : "00.01.00",
      "name" : "Kommunens styrelse i almindelighed"
    }, {
      "code" : "00.01.10",
      "name" : "Opgaver der dækker flere hovedgrupper"
    }, {
      "code" : "00.03",
      "name" : "International virksomhed og EU"
    }, {
      "code" : "00.03.00",
      "name" : "International virksomhed og EU i almindelighed"
    }, {
      "code" : "00.03.02",
      "name" : "Internationale organisationers virksomhed"
    }, {
      "code" : "00.03.04",
      "name" : "Regionaludvikling EU"
    }, {
      "code" : "00.03.08",
      "name" : "EU-interessevaretagelse"
    }, {
      "code" : "00.03.10",
      "name" : "Internationalt samarbejde"
    }, {
      "code" : "00.05",
      "name" : "Besøg, repræsentation mv."
    }, {
      "code" : "00.05.00",
      "name" : "Besøg, repræsentation mv. i almindelighed"
    }, {
      "code" : "00.05.01",
      "name" : "Venskabsbysamarbejde"
    }, {
      "code" : "00.05.02",
      "name" : "Kommunale skibsadoptioner"
    }, {
      "code" : "00.05.03",
      "name" : "Festdage, mærkedage og jubilæer"
    }, {
      "code" : "00.05.06",
      "name" : "Receptioner"
    }, {
      "code" : "00.05.07",
      "name" : "Hædersbevisninger, priser og prisuddelinger"
    }, {
      "code" : "00.05.09",
      "name" : "Indsamlinger"
    }, {
      "code" : "00.05.10",
      "name" : "Gaver til og fra kommunen/institutionen"
    }, {
      "code" : "00.05.11",
      "name" : "Besøg til og fra kommunen/modtagelse af gæster"
    } ]
  },
  "_links" : {
    "first" : {
      "href" : "https://www.os2autoproces.eu/api/kles?page=0&size=20"
    },
    "self" : {
      "href" : "https://www.os2autoproces.eu/api/kles{?page,size,sort}",
      "templated" : true
    },
    "next" : {
      "href" : "https://www.os2autoproces.eu/api/kles?page=1&size=20"
    },
    "last" : {
      "href" : "https://www.os2autoproces.eu/api/kles?page=138&size=20"
    },
    "profile" : {
      "href" : "https://www.os2autoproces.eu/api/profile/kles"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 2767,
    "totalPages" : 139,
    "number" : 0
  }
}

Datamodel

Field Type Nullable Description
code string no This field contains a 2-6 digit number, formatted as a string where each 2 digits are separated by a dot. The code is known as the KLE group, subgroup or subject (depending on the amount of digits), and is a code that can be attached to any work performed by a municipality.
name string no This is the title/name of the KLE group, subgroup or subject, and should be displayed (along with the code) in the UI, and both the name and code should be searchable in the UI when selecting a KLE value, as some workers use the codes and others tend to search by the name instead.

5.3 FORM API

Description

Type Status Comment
Generated Secure API Stable This API gives read-only access to the FORM classification

Useful operations

Note that this is a generated API, so it supports all of the operations that Spring Data REST allows (though updating operations are disabled). This list is just the operations that are useful for the frontend. Note that when fetching all FORM values, it might be useful to set the size parameter to some very high number, to effectively disable pagination, as the list will likely only have some 3100 values, and the data-size is very small. Also the data practically never changes (roughly once every 3 months), so it makes sense for the frontend to load all FORM values in the beginning, and then store them locally in the DOM.

Fetch a list of FORM values
GET https://www.os2autoproces.eu/api/forms
(returns a list of FORM values, example given in the subchapter below)

Example output

The output follows the standard structure for list-output on generated APIs, meaning that the result comes in the '_embedded' field, and pagination metadata comes in the 'page' field. The result contains an array of (simple) FORM objects, which are described in the datamodel chapter below.

{
  "_embedded" : {
    "forms" : [ {
      "code" : "02",
      "description" : "Internationale aftaler"
    }, {
      "code" : "02.05",
      "description" : "Internationale aftaler"
    }, {
      "code" : "02.05.05",
      "description" : "Aftaler vedrørende De Forenede Nationer (FN)"
    }, {
      "code" : "02.05.05.05",
      "description" : "Danmarks aftaler vedrørende De Forenede Nationers (FN) styrende organer"
    }, {
      "code" : "02.05.05.10",
      "description" : "Danmarks aftaler vedrørende De Forenede Nationers (FN) særorganisationer"
    }, {
      "code" : "02.05.05.15",
      "description" : "Danmarks aftaler vedrørende De Forenede Nationers (FN) fonde og programmer med videre"
    }, {
      "code" : "02.05.05.20",
      "description" : "Danmarks aftaler vedrørende De Forenede Nationers (FN) finansielle institutioner"
    }, {
      "code" : "02.05.10",
      "description" : "Aftaler vedrørende Europarådet"
    }, {
      "code" : "02.05.10.05",
      "description" : "Danmarks aftaler vedrørende Europarådet"
    }, {
      "code" : "02.05.15",
      "description" : "Aftaler vedrørende Den Europæiske Union (EU)"
    }, {
      "code" : "02.05.15.05",
      "description" : "Danmarks aftaler vedrørende Den Europæiske Union (EU)"
    }, {
      "code" : "02.05.20",
      "description" : "Aftaler vedrørende nordisk samarbejde"
    }, {
      "code" : "02.05.20.05",
      "description" : "Danmarks aftaler vedrørende nordisk samarbejde"
    }, {
      "code" : "02.05.25",
      "description" : "Aftaler vedrørende internationale specialorganisationer"
    }, {
      "code" : "02.05.25.10",
      "description" : "Danmarks aftaler vedrørende Den Nordatlantiske Traktats Organisation (NATO)"
    }, {
      "code" : "02.05.25.15",
      "description" : "Danmarks aftaler vedrørende Organisationen for Sikkerhed og Samarbejde i Europa (OSCE)"
    }, {
      "code" : "02.05.25.20",
      "description" : "Danmarks aftaler vedrørende Organisationen for Økonomisk Samarbejde og Udvikling (OECD)"
    }, {
      "code" : "02.05.25.25",
      "description" : "Danmarks aftaler vedrørende Verdenshandelsorganisationen (WTO)"
    }, {
      "code" : "02.05.25.30",
      "description" : "Danmarks aftaler vedrørende Den Internationale Kriminalpolitiorganisation (INTERPOL)"
    }, {
      "code" : "02.05.25.35",
      "description" : "Danmarks aftaler vedrørende Østersørådet"
    } ]
  },
  "_links" : {
    "first" : {
      "href" : "https://www.os2autoproces.eu/api/forms?page=0&size=20"
    },
    "self" : {
      "href" : "https://www.os2autoproces.eu/api/forms{?page,size,sort}",
      "templated" : true
    },
    "next" : {
      "href" : "https://www.os2autoproces.eu/api/forms?page=1&size=20"
    },
    "last" : {
      "href" : "https://www.os2autoproces.eu/api/forms?page=153&size=20"
    },
    "profile" : {
      "href" : "https://www.os2autoproces.eu/api/profile/forms"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 3080,
    "totalPages" : 154,
    "number" : 0
  }
}

Datamodel

Field Type Nullable Description
code string no This field contains a 2-8 digit number, formatted as a string where each 2 digits are separated by a dot FORM is related to KLE, in the sense that each FORM element is related to a single KLE element, though multiple FORM elements may be related to the same KLE element.
description string no This is the title/name of the FORM element, and should be displayed (along with the code) in the UI.

5.4 ItSystem API

Description

Type Status Comment
Generated Secure API Stable This API gives access to the ItSystem classification for read and create.

Useful operations

Note that the read endpoint is a generated API, so it supports all of the operations that Spring Data REST allows (though updating operations are disabled). This list is just the operations that are useful for the frontend. Note that when fetching all ItSystem values, it might be useful to set the size parameter to some very high number, to effectively disable pagination, as the list will likely only have some 3000 values, and the data-size is very small. Also the data practically never changes (roughly once every week), so it makes sense for the frontend to load all ItSystem values in the beginning, and then store them locally in the DOM. The create and update is provided by a custom API. Only the ItSystems created through this API can be modified or removed. ItSystems created through the custom API will be returned as output on the generated API, which will indicate if it can be edited through the "fromKitos" field. Any ItSystem that has "fromKitos" set to "true" cannot be edited through the custom API endpoints.

Fetch a list of ItSystems
GET https://www.os2autoproces.eu/api/itSystems
(returns a list of ItSystem values, example given in the subchapter below)
Create ItSystem
POST https://www.os2autoproces.eu/api/managedItSystem/
{
  "name": "Adobe Photoshop",
  "vendor": "Adobe Systems Danmark Aps"
}
Edit ItSystem
PUT https://www.os2autoproces.eu/api/managedItSystem//<id>
{
  "name": "Adobe Photoshop",
  "vendor": "Adobe Systems Danmark Aps"
}
Remove an ItSystem
DELETE https://www.os2autoproces.eu/api/managedItSystem/<id>

Example output

The output of the it-system read operations follows the standard structure for list-output on generated APIs, meaning that the result comes in the '_embedded' field, and pagination metadata comes in the 'page' field. The result contains an array of (simple) ItSystem objects, which are described in the datamodel chapter below.

{
  "_embedded" : {
    "itSystems" : [ {
      "id" : 1,
      "name" : "Microsoft Office pakken",
      "vendor" : null
    }, {
      "id" : 2,
      "name" : "Mirasys",
      "vendor" : null
    }, {
      "id" : 3,
      "name" : "Smart Parking",
      "vendor" : "Fælles Kommune"
    }, {
      "id" : 4,
      "name" : "Opendata.dk",
      "vendor" : "Fælles Kommune"
    }, {
      "id" : 5,
      "name" : "Startsag",
      "vendor" : "Fælles Kommune"
    }, {
      "id" : 6,
      "name" : "EAS ErhvervsAffaldsSystem",
      "vendor" : "Fælles Kommune"
    }, {
      "id" : 7,
      "name" : "Hyena",
      "vendor" : "Fælles Kommune"
    }, {
      "id" : 8,
      "name" : "Virksomhedsoverblikket",
      "vendor" : "Fælles Kommune"
    }, {
      "id" : 9,
      "name" : "EG Nemjournalisering NFS Workbase",
      "vendor" : "Fælles Kommune"
    }, {
      "id" : 10,
      "name" : "Kommunal sundhedskort",
      "vendor" : "Fælles Kommune"
    }, {
      "id" : 11,
      "name" : "Instant Survey",
      "vendor" : "Fælles Kommune"
    }, {
      "id" : 12,
      "name" : "Icura Activity",
      "vendor" : "Fælles Kommune"
    }, {
      "id" : 13,
      "name" : "CutePDF",
      "vendor" : "Acro Software Inc."
    }, {
      "id" : 14,
      "name" : "Acta Pension",
      "vendor" : "Acta Data"
    }, {
      "id" : 15,
      "name" : "Adobe Reader",
      "vendor" : "Adobe Systems Danmark Aps"
    }, {
      "id" : 16,
      "name" : "Adobe LiveCycle",
      "vendor" : "Adobe Systems Danmark Aps"
    }, {
      "id" : 17,
      "name" : "Adobe Digital Editions",
      "vendor" : "Adobe Systems Danmark Aps"
    }, {
      "id" : 18,
      "name" : "Adobe Indesign",
      "vendor" : "Adobe Systems Danmark Aps"
    }, {
      "id" : 19,
      "name" : "Adobe Photoshop",
      "vendor" : "Adobe Systems Danmark Aps"
    }, {
      "id" : 20,
      "name" : "Adobe Professional",
      "vendor" : "Adobe Systems Danmark Aps"
    } ]
  },
  "_links" : {
    "first" : {
      "href" : "https://www.os2autoproces.eu/api/itSystems?page=0&size=20"
    },
    "self" : {
      "href" : "https://www.os2autoproces.eu/api/itSystems{?page,size,sort}",
      "templated" : true
    },
    "next" : {
      "href" : "https://www.os2autoproces.eu/api/itSystems?page=1&size=20"
    },
    "last" : {
      "href" : "https://www.os2autoproces.eu/api/itSystems?page=117&size=20"
    },
    "profile" : {
      "href" : "https://www.os2autoproces.eu/api/profile/itSystems"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 2343,
    "totalPages" : 118,
    "number" : 0
  }
}

Datamodel

Field Type Nullable Description
id integer no The unique id of the ItSystem, used for referencing the ItSystem
name string no The productname of the ItSystem
vendor string yes The vendor of this ItSystem
fromKitos boolean no True if the it-system is managed by KITOS (and cannot be updated through the custom API)

5.5 Process API

Description

Type Status Comment
Generated Secure API Stable This API gives access to the processes in the solution. Read/write access depends on the currently logged in user. Users can only read processes they have read access to, and all other processes are filtered out in search results. Attempts to write to a process that the user does not have write access to, will result in HTTP 403.

Useful operations

Note that this is a generated API, so it supports all of the operations that Spring Data REST allows (though updating operations are disabled). This list is just the operations that are useful for the frontend.

Pagination. As there are potentially many processes, it makes sense to use the pagination feature, which is build into the API. Look in chapter 3 for details on how to use the various API features generated by Spring Data REST.

Searching. The API also supports searching using QueryDSL, which is described in chapter 3.

There are to additional searchParameters that can be used while searching, these are not part of the datamodel directly, but are taken into account when performing searches, these are

  • bookmarkUsers. Adding a bookmarkUsers.id=xxx or bookmarkUsers.uuid=xxx as a search parameter will ensure that only processes that have been bookmarked by that user is returned. Example: https://www.os2autoproces.eu/api/processes?bookmarkUsers.id=1
  • freetext. Adding a freetext=xxx as a search parameter, will perform a search for processes that has xxx as an infix of a series of textfields within the process datamodel (not implemented yet). Example: https://www.os2autoproces.eu/api/processes?freetext=Hello

Fetch a list of processes
GET https://www.os2autoproces.eu/api/processes
(returns a list of processes, example given in the subchapter below)
Fetch a single process
GET https://www.os2autoproces.eu/api/processes/<id>
(returns a single process with the given id)
Create a new process
POST https://www.os2autoproces.eu/api/processes
(body should contain the process to be created)
Copy an existing process
POST https://www.os2autoproces.eu/api/processes/<id>/copy
(returns a copy of the process with the given id - the copy has a new id)
Overwrite an existing process
PUT https://www.os2autoproces.eu/api/processes/<id>
(body should contain the process to be updated)
Update individual fields on existing process
PATCH https://www.os2autoproces.eu/api/processes/<id>
(body should contain the fields the be updated, and their new values (partial process JSON object))
Update individual fields on existing process
PATCH https://www.os2autoproces.eu/api/processes/<id>
(body should contain the fields the be updated, and their new values (partial process JSON object))

Example output

The output follows shows the output from GET on a single process. When reading more than one process at a time, the output will be structured as the other generated API's, so the result will be in _embedded, with metadata about the request in _links and _page sections.

{
  "id" : 501,
  "klId" : null,
  "esdhReference" : null,
  "phase" : "OPERATION",
  "status" : "PENDING",
  "created" : "2018-06-28T10:08:33.000+0000",
  "lastChanged" : "2018-06-28T10:08:33.000+0000",
  "putIntoOperation" : null,
  "decommissioned" : null,
  "statusText" : "Lorem ipsum dolor sit amet,",
  "title" : "Demo dolor sit amet,",
  "shortDescription" : "Lorem ipsum",
  "longDescription" : "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut",
  "domains" : [
    "ADMINISTRATION",
    "WORK"
  ],
  "visibility" : "MUNICIPALITY",
  "type" : "CHILD",
  "legalClause" : "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et",
  "legalClauseLastVerified" : null,
  "kle" : "00.00.00",
  "form" : "00.01.00.04",
  "kla" : null,
  "klaProcess" : false,
  "links" : [ {
    "url" : "http://blah.dk",
    "internal" : false
  }, {
    "url" : "http://blah2.dk",
    "internal" : true
  } ],
  "services": [
    {
      "name": "Service Number One"
    },
    {
      "name": "Service #2"
    }
  ],
  "vendor" : null,
  "cvr" : "12345678",
  "municipalityName": "Syddjurs Kommune",
  "internalNotes" : null,
  "processChallenges" : "Lorem ipsum",
  "solutionRequests" : "Lorem ipsum dolor sit amet, consetetur sadipscing",
  "itSystemsDescription" : "Lorem ipsum",
  "timeSpendOccurancesPerEmployee" : 2,
  "timeSpendPerOccurance" : 0,
  "timeSpendEmployeesDoingProcess" : 0,
  "timeSpendPercentageDigital" : 0,
  "timeSpendComputedTotal" : 1,
  "timeSpendComment" : null,
  "targetsCompanies" : false,
  "targetsCitizens" : false,
  "levelOfProfessionalAssessment" : "VERY_LOW",
  "levelOfChange" : "HIGH",
  "levelOfStructuredInformation" : "VERY_LOW",
  "levelOfUniformity" : "LOW",
  "levelOfDigitalInformation" : "LOW",
  "levelOfQuality" : "LOW",
  "levelOfSpeed" : "LOW",
  "levelOfRoutineWorkReduction" : "LOW",
  "evaluatedLevelOfRoi" : "VERY_HIGH",
  "technicalImplementationNotes" : "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet",
  "organizationalImplementationNotes" : "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor",
  "rating" : 0,
  "ratingComment" : null,
  "automationDescription" : null,
  "expectedDevelopmentTime": "100.12",
  "searchWords": "",
  "codeRepositoryUrl": null,
  "runPeriod": "ONDEMAND",
  "sepMep": false,
  "childrenCount": 0,
  "_links" : {
    "self" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501"
    },
    "process" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501{?projection}",
      "templated" : true
    },
    "orgUnits" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/orgUnits"
    },
    "reporter" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/reporter"
    },
    "users" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/users"
    },
    "technologies" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/technologies"
    },
    "owner" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/owner"
    },
    "children" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/children"
    },
    "parents" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/parents"
    },
    "itSystems" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/itSystems"
    },
    "contact" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/contact"
    }
  }
}

Datamodel - Fields

Field Type Nullable Description
id integer no The unique id of the process
klId string (64 char) yes An optional id used by KL
esdhReference string (300 char) yes An optional reference to the municipalities ESDH system
phase enum no One of the following: IDEA, PREANALYSIS, SPECIFICATION, DEVELOPMENT, IMPLEMENTATION, OPERATION, DECOMMISSIONED
type enum no (defaults to CHILD) One of the following: CHILD, PARENT, GLOBAL_PARENT
status Enum no One of the following: REJECTED, FAILED, PENDING, INPROGRESS, NOT_RATED, NOT_RELEVANT
statusText string (10.000 char) yes Optional text coupled with status
created Timestamp no Set by the backend upon creation
lastChanged Timestamp no Set by the backend upon change
putIntoOperation Timestamp yes The date the process was put into operation
decommissioned Timestamp yes Indicate decommissioned date
title String (50 char) no Title of the process
shortDescription String (140 char) no Short description
longDescription String (10.000 char) yes Long description
itSystemsDescription String (10.000 char) yes A description of the it-systems used in the process
domain Array of Enum empty is allowed Zero or more of the following: HEALTH, ENVIRONMENT, DEMOCRACY, ADMINISTRATION, EMPLOYMENT, PROFESSION, FAMILY, EDUCATION, TECHNIQUE, SOCIAL, SUSTAINABILITY, HR, IT, CULTURE, ECONOMY
visibility Enum no One of the following: PERSONAL, MUNICIPALITY, PUBLIC
legalClause String (140 char) yes Plain text reference to some legislation
legalClauseLastVerified Timestamp yes indicating when last verified against legislation
kle String (8 char) yes KLE code (use KLE Api for legal values)
form String (11 char) yes FORM code (use FORM Api for legal values)
kla String (14 char) yes KLA code (freetext)
klaProcess Boolean no backend managed - true if kla is non-null
links Array empty array List of links (contains a char(1024) url value and a boolean internal field)
services Array empty array List of services (contains a 255 char name)
vendor String (255 char) yes Plaintext description of who the vendor is (if any)
cvr String (8 char) no managed by backend
municipalityName String (64 char) no managed by backend
internalNotes String (10.000 char) yes Note that field is null unless the user has write access to this process
processChallenges String (10.000 char) yes Freetext field for describing challenges in this process
solutionRequests String (10.000 char) yes Freetext field for describing solution requests for this process
timeSpendOccurancesPerEmployee Integer no (default 0) Time indication
timeSpendPerOccurance Integer no (default 0) Time indication
timeSpendEmployeesDoingProcess Integer no (default 0) Time indication
timeSpendPercentageDigital Integer no (default 0, max 100) Percentage of process that is digital (can be automated)
timeSpendComputedTotal Integer no Computed field, maintained by the backend. Read-only access through API
timeSpendComment String (10.000 char) no Required field, contains comments to the time-spend sections
targetsCompanies Boolean no Does the process involve companies
targetsCitizens Boolean no Does the process involve citizens
levelOfProfessionalAssessment Enum no (default to NOT_SET) One of the following: VERY_HIGH, HIGH, LOW, VERY_LOW, UNKNOWN, NOT_SET
levelOfChange Enum no (default to NOT_SET) One of the following: VERY_HIGH, HIGH, LOW, VERY_LOW, UNKNOWN, NOT_SET
levelOfStructuredInformation Enum no (default to NOT_SET) One of the following: VERY_HIGH, HIGH, LOW, VERY_LOW, UNKNOWN, NOT_SET
levelOfUniformity Enum no (default to NOT_SET) One of the following: VERY_HIGH, HIGH, LOW, VERY_LOW, UNKNOWN, NOT_SET
levelOfDigitalInformation Enum no (default to NOT_SET) One of the following: VERY_HIGH, HIGH, LOW, VERY_LOW, UNKNOWN, NOT_SET
levelOfQuality Enum no (default to NOT_SET) One of the following: VERY_HIGH, HIGH, LOW, VERY_LOW, UNKNOWN, NOT_SET
levelOfSpeed Enum no (default to NOT_SET) One of the following: VERY_HIGH, HIGH, LOW, VERY_LOW, UNKNOWN, NOT_SET
levelOfRoutineWorkReduction Enum no (default to NOT_SET) One of the following: VERY_HIGH, HIGH, LOW, VERY_LOW, UNKNOWN, NOT_SET
evaluatedLevelOfRoi Enum no (default to NOT_SET) One of the following: VERY_HIGH, HIGH, LOW, VERY_LOW, UNKNOWN, NOT_SET
technicalImplementationNotes String (10.000 char) yes Freetext field
organizationalImplementationNotes String (10.000 char) yes Freetext field
rating Integer yes rating of this proces
ratingComment String (10.000 char) yes Freetext field
automationDescription String (10.000 char) yes Freetext field
searchWords String (1000 char) yes Optional list of search words (use SearchWord API to get good values to add to this list)
codeRepositoryUrl String (300 char) yes Optional http link to a code repository
runPeriod enum no Legal values: ONDEMAND, ONCE, DAILY, WEEKLY, MONTHLY, QUATERLY, YEARLY
sepMep Boolean no set to true if this is a SEP or MEP process
expectedDevelopmentTime Double yes Indicate the expected development time for that process. 10 digits max length including 2 max digits of precision f.x. 100.30
otherContactEmail String (225 char) yes Other contact email is shown instead of contact if not null when process is shown to other municipalities. Defaults to null, can be changed by UI

Datamodel - Relationships

Relationship Type Required Description
reporter 1 USER yes managed by backend
users USER(s) no list of associated users, managed through UI
owner USER yes who owns the process, defaults to reporter, can be changed by UI
contact USER yes Contact person (only user that is visible to other municipalities). Defaults to reporter, can be changed by UI
itSystems ITSYSTEM(s) no A list of associated it-systems managed by UI - use the ItSystem API
orgUnits ORGUNIT(s) no A list of associated orgUnits managed by UI - use the OrgUnit API
children PROCESS(es) no If 'type' is PARENT/GLOBAL_PARENT, this relationship can maintain all child processes
parents PROCESS(es) no If 'type' is CHILD, this relationship gives read access to all parent processes
technologies TECHNOLOGY(s) no A list of used technologies managed by UI - use the Technologies API

Projections

The Process API offers 2 projections, which can be used on all the READ operations, both for single processes and for lists. The projections are

  • grid. This projection returns a small subset of the fields in the datamodel, making it a good choice for listing process information in the UI. The fields returned are (id, title, shortDescription, lastChanged, rating, phase, status, domain, kle, legalClause, municipalityName, visibility, timeSpendOccurancesPerEmployee, timeSpendPerOccurance, timeSpendPercentageDigital, runPeriod, technologies), as well as a couple of extra computed fields: childrenCount (containing the amount of children the process has), hasAttachments (if the process has attachments), hasBookmarked (if the logged in user has bookmarked the process). The list can be modified if needed, contact Brian in that case. Note the grid projection is a good projection to use when listing processes (calls to the API with more than one result).
  • extended. This projection returns everything that a Process normally contains, including three extra fields containing information about the currently logged in users relation to the process. These are (canEdit, hasBookmarked, emailNotification), which are boolean values indicating just what the names says. Note that this projection also expands relationships, so the data from associated users, the reporter, the owner, orgUnits, etc are all included in the output.

A projection is applied to the output one of the GET operations mentioned above, and can be combined with search/pagination parameters. The projection is applied as shown in the example below

Do a grid-projected search
GET https://www.os2autoproces.eu/api/processes?projection=grid
Do an extended-projected read of a single process
GET https://www.os2autoproces.eu/api/processes/<id>?projection=extended

Example grid projected output on a single process

{
  "id" : 1,
  "status" : "FAILED",
  "cvr" : "87654321",
  "phase" : "IMPLEMENTATION",
  "rating" : 0,
  "title" : "Demo dolor sit",
  "lastChanged" : "2018-06-28T07:41:37.000+0000",
  "domains" : [
    "ADMINISTRATION",
    "WORK"
  ],
  "shortDescription" : "Lorem ipsum dolor sit amet,",
  "timeSpendOccurancesPerEmployee" : 0,
  "timeSpendPerOccurance" : 0,
  "timeSpendPercentageDigital" : 0,
  "runPeriod" : "ONDEMAND",
  "hasAttachments" : false,
  "hasBookmarked" : false,
  "technologies" : [],
  "_links" : {
    "self" : {
      "href" : "https://www.os2autoproces.eu/api/processes/1"
    },
    "process" : {
      "href" : "https://www.os2autoproces.eu/api/processes/1{?projection}",
      "templated" : true
    },
    "orgUnits" : {
      "href" : "https://www.os2autoproces.eu/api/processes/1/orgUnits"
    },
    "reporter" : {
      "href" : "https://www.os2autoproces.eu/api/processes/1/reporter"
    },
    "users" : {
      "href" : "https://www.os2autoproces.eu/api/processes/1/users"
    },
    "technologies" : {
      "href" : "https://www.os2autoproces.eu/api/processes/1/technologies"
    },
    "owner" : {
      "href" : "https://www.os2autoproces.eu/api/processes/1/owner"
    },
    "children" : {
      "href" : "https://www.os2autoproces.eu/api/processes/1/children"
    },
    "parents" : {
      "href" : "https://www.os2autoproces.eu/api/processes/1/parents"
    },
    "itSystems" : {
      "href" : "https://www.os2autoproces.eu/api/processes/1/itSystems"
    },
    "contact" : {
      "href" : "https://www.os2autoproces.eu/api/processes/1/contact"
    }
  }
}

Example extended projected output on a single process

{
  "longDescription" : "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut",
  "hasBookmarked" : false,
  "created" : "2018-06-28T10:08:33.000+0000",
  "status" : "PENDING",
  "type" : "CHILD",
  "users" : [ {
    "id" : 2,
    "uuid" : "097ff0a8-d853-4bfe-90e0-22ca3287dc24",
    "name" : "IT Minds 1",
    "email" : "itminds1@digital-identity.dk",
    "active" : true,
    "cvr" : "12345678"
  }, {
    "id" : 1,
    "uuid" : "39223c72-bfd5-4fd1-aee1-6c9a740b8f7f",
    "name" : "Piotr Suski",
    "email" : "psu@digital-identity.dk",
    "active" : true,
    "cvr" : "12345678"
  }, {
    "id" : 2,
    "uuid" : "097ff0a8-d853-4bfe-90e0-22ca3287dc24",
    "name" : "IT Minds 1",
    "email" : "itminds1@digital-identity.dk",
    "active" : true,
    "cvr" : "12345678"
  } ],
  "cvr" : "12345678",
  "municipalityName": "Syddjurs Kommune",
  "esdhReference" : null,
  "evaluatedLevelOfRoi" : "VERY_HIGH",
  "kle" : "00.00.00",
  "form" : "01.08.11.41",
  "kla" : null,
  "klaProcess" : false,
  "klId" : null,
  "legalClause" : "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et",
  "legalClauseLastVerified" : null,
  "levelOfChange" : "HIGH",
  "levelOfDigitalInformation" : "LOW",
  "levelOfProfessionalAssessment" : "VERY_LOW",
  "levelOfQuality" : "LOW",
  "levelOfSpeed" : "LOW",
  "levelOfRoutineWorkReduction" : "LOW",
  "levelOfStructuredInformation" : "VERY_LOW",
  "levelOfUniformity" : "LOW",
  "organizationalImplementationNotes" : "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor",
  "phase" : "OPERATION",
  "processChallenges" : "Lorem ipsum",
  "rating" : 0,
  "emailNotification" : true,
  "ratingComment" : null,
  "automationDescription" : null,
  "solutionRequests" : "Lorem ipsum dolor sit amet, consetetur sadipscing",
  "targetsCitizens" : false,
  "targetsCompanies" : false,
  "technicalImplementationNotes" : "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet",
  "technologies" : [ ],
  "itSystemsDescription" : "Lorem ipsum",
  "timeSpendComment" : null,
  "timeSpendComputedTotal" : 1,
  "timeSpendPercentageDigital" : 0,
  "timeSpendEmployeesDoingProcess" : 0,
  "timeSpendOccurancesPerEmployee" : 2,
  "timeSpendPerOccurance" : 0,
  "title" : "Demo dolor sit amet,",
  "vendor" : null,
  "reporter" : {
    "id" : 1,
    "uuid" : "39223c72-bfd5-4fd1-aee1-6c9a740b8f7f",
    "name" : "Piotr Suski",
    "email" : "psu@digital-identity.dk",
    "active" : true,
    "cvr" : "12345678"
  },
  "searchWords" : "",
  "orgUnits" : [ ],
  "statusText" : "Lorem ipsum dolor sit amet,",
  "lastChanged" : "2018-06-28T10:08:33.000+0000",
  "putIntoOperation" : null,
  "decommissioned" : null,
  "visibility" : "MUNICIPALITY",
  "itSystems" : [ ],
  "contact" : {
    "id" : 2,
    "uuid" : "097ff0a8-d853-4bfe-90e0-22ca3287dc24",
    "name" : "IT Minds 1",
    "email" : "itminds1@digital-identity.dk",
    "active" : true,
    "cvr" : "12345678"
  },
  "otherContactEmail" : null,
  "internalNotes" : null,
  "canEdit" : true,
  "domains" : [
    "ADMINISTRATION",
    "WORK"
  ],
  "shortDescription" : "Lorem ipsum",
  "expectedDevelopmentTime": "100.12",
  "id" : 501,
  "owner" : {
    "id" : 2,
    "uuid" : "097ff0a8-d853-4bfe-90e0-22ca3287dc24",
    "name" : "IT Minds 1",
    "email" : "itminds1@digital-identity.dk",
    "active" : true,
    "cvr" : "12345678"
  },
  "_links" : {
    "self" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501"
    },
    "process" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501{?projection}",
      "templated" : true
    },
    "orgUnits" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/orgUnits"
    },
    "reporter" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/reporter"
    },
    "users" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/users"
    },
    "technologies" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/technologies"
    },
    "owner" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/owner"
    },
    "children" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/children"
    },
    "parents" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/parents"
    },
    "itSystems" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/itSystems"
    },
    "contact" : {
      "href" : "https://www.os2autoproces.eu/api/processes/501/contact"
    }
  }
}

5.6 OrgUnit API

Description

Type Status Comment
Generated Secure API Stable This API gives read-only access to the OrgUnits from the currently logged in users municipality

Useful operations

Note that this is a generated API, so it supports all of the operations that Spring Data REST allows (though updating operations are disabled). The set of data changes daily, and is between 500 and 1000 entries per municipality.

NOTICE. It is currently undecided if the backend will allow cross-municipality lookup of organizational data.

Query for OrgUnits that matches a given name (case-insensitive infix search - supply at least 3 characters)
GET https://www.os2autoproces.eu/api/orgUnits?name=<name>&cvr=<cvr>
(returns a list of orgUnits that has the supplied name-parameter anywhere in their name, owned by the supplied CVR number)
Read a single OrgUnit
GET https://www.os2autoproces.eu/api/orgUnits/<id>
(returns the data on the orgUnit that matches the supplied id)

Example output

The output follows the standard structure for list-output on generated APIs, meaning that the result comes in the '_embedded' field, and pagination metadata comes in the 'page' field. The result contains an array of User objects, which are described in the datamodel chapter below.

{
  "_embedded" : {
    "orgUnits" : [ {
      "id" : 1,
      "uuid" : "7913234e-e253-4309-905e-84a3cf433e89",
      "name" : "My Orgunit 01",
      "active" : true,
      "cvr" : "87654321"
    }, {
      "id" : 2,
      "uuid" : "87f27b27-753e-4168-ba61-5ea7bf1efa98",
      "name" : "My Orgunit 11",
      "active" : true,
      "cvr" : "87654321"
    }, {
      "id" : 3,
      "uuid" : "2ef27647-8e88-4334-90da-6f3dd748511d",
      "name" : "My Orgunit 21",
      "active" : true,
      "cvr" : "87654321"
    }, {
      "id" : 4,
      "uuid" : "30a09715-f72a-4275-a21a-561d6c5d814d",
      "name" : "My Orgunit 31",
      "active" : true,
      "cvr" : "87654321"
    }, {
      "id" : 5,
      "uuid" : "fd1c8180-2205-472a-81b0-a2def1454d27",
      "name" : "My Orgunit 41",
      "active" : true,
      "cvr" : "87654321"
    }]
  },
  "_links" : {
    "self" : {
      "href" : "https://www.os2autoproces.eu/api/orgUnits{?page,size,sort}",
      "templated" : true
    },
    "profile" : {
      "href" : "https://www.os2autoproces.eu/api/profile/orgUnits"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 5,
    "totalPages" : 1,
    "number" : 0
  }
}

Datamodel

Field Type Nullable Description
id integer no The unique id of the orgUnit, used for referencing the orgUnit
uuid string no The municipalities local id of the orgUnit
name string no The full name of the orgUnit
active boolean no Indicates if the orgUnit is active (a part of the current organisation), or inactive (closed orgUnit)
cvr string no The cvr number of the municipality to which the orgUnit belongs

5.7 User API

Description

Type Status Comment
Generated Secure API Stable This API gives read-only access to user data

Useful operations

Note that this is a generated API, so it supports all of the operations that Spring Data REST allows (though updating operations are disabled). The set of data changes daily, and be rather large (anywhere between 5.000 and 10.000 entries per municipality), so it might be useful to use the backend for querying data.

NOTICE. It is currently undecided if the backend will allow cross-municipality lookup of user data.

Query for users that matches a given name (case-insensitive infix search - supply at least 3 characters)
GET https://www.os2autoproces.eu/api/users?name=<name>&cvr=<cvr>
(returns a list of users that has the supplied name-parameter anywhere in their name, coming from the supplied cvr number)
Read a single user
GET https://www.os2autoproces.eu/api/users/<id>
(returns the data on the user that matches the supplied id)

Example output

The output follows the standard structure for list-output on generated APIs, meaning that the result comes in the '_embedded' field, and pagination metadata comes in the 'page' field. The result contains an array of User objects, which are described in the datamodel chapter below.

{
  "_embedded" : {
    "users" : [ {
      "id": 1,
      "uuid" : "5611fef7-1892-41f6-adf6-16bcd672487f",
      "name" : "Brian Graversen",
      "email" : "bsg@digital-identity.dk",
      "active" : true,
      "cvr" : "12345678"
    }, {
      "id" : 2,
      "uuid" : "fbd9342f-802f-4125-8a25-d7552933e90b",
      "name" : "Piotr Suski",
      "email" : "psu@digital-identity.dk",
      "active" : true,
      "cvr" : "12345678"
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "https://www.os2autoproces.eu/api/users{?page,size,sort}",
      "templated" : true
    },
    "profile" : {
      "href" : "https://www.os2autoproces.eu/api/profile/users"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 2,
    "totalPages" : 1,
    "number" : 0
  }
}

Datamodel

Field Type Nullable Description
id integer no The unique id of the user, used for referencing the user
uuid string no The municipalities local id of the user
name string no The full name of the user
email string no The users email address
active boolean no Indicates if the user is active (currently employeed), or inactive (no longer employeed at the municipality)
cvr string no The cvr number of the municipality from which the user comes

5.8 SearchWords API

Description

Type Status Comment
Generated Secure API Stable This API gives read-only access to search words added to existing processes

The SearchWords API grants read-only access to all existing SearchWords added to other Processes. The intended use for this API is to support a type-ahead feature in the UI when adding SearcWords to a Process.

Please note that a scheduled job runs through all processes at regular intervals to update the set of searchWords, so new searchWords (entered into processes), are not immediately available through this API.

Useful operations

Note that this is a generated API, so it supports all of the operations that Spring Data REST allows (though updating operations are disabled). This list is just the operations that are useful for the frontend. The last one is the one intended for type-ahead use, as it filters the result set according to the supplied argument

Fetch all searchWords
GET https://www.os2autoproces.eu/api/searchWords
(returns a list of registered searchWords, example given in the subchapter below)
Fetch all searchWords containing the string 'cat' (infix search)
GET https://www.os2autoproces.eu/api/searchWords?searchWord=cat
(returns a list of registered searchWords, example given in the subchapter below)

Example output

The output follows the standard structure for list-output on generated APIs, meaning that the result comes in the '_embedded' field, and pagination metadata comes in the 'page' field. The result contains an array of searchWords as described in the datamodel below.

{
  "_embedded" : {
    "searchWords" : [ {
      "searchWord" : "RPA 2.0"
    }, {
      "searchWord" : "UIPath"
    }, {
      "searchWord" : "BluePrism"
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "https://www.os2autoproces.eu/api/searchWords{?page,size,sort}",
      "templated" : true
    },
    "profile" : {
      "href" : "https://www.os2autoproces.eu/api/profile/searchWords"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 3,
    "totalPages" : 1,
    "number" : 0
  }
}

Datamodel

Field Type Nullable Description
searchWord string no This is the actual stored searchWord

6 Custom APIs

6.1 Bookmark API

Description

Type Status Comment
Custom Secure API Stable This API is intended for managing the a users bookmarks, and is custom created, as the bookmarks cannot be managed directly from the user object (the user object is an externally managed object, and the User API is read-only).

Useful operations

Below are listed the operations available on this API.

Fetch all of the currently logged in users bookmarks
GET https://www.os2autoproces.eu/api/bookmarks
(returns a list processes - the output matches the datamodel for Processes ())
Add a bookmark for a given process on the currently logged in user
PUT https://www.os2autoproces.eu/api/bookmarks/<id>
(the supplied id should match a process - if the user has read-access to the process, a bookmark is added to the user)
Remove a bookmark for a given process on the currently logged in user
DELETE https://www.os2autoproces.eu/api/bookmarks/<id>
(the supplied id should match a process - if the user has a bookmark for that process, it is removed)

Example output

The output is based on the grid projection of processes, and will contain an array of the processes the user currently has bookmarked. As the API is not generated by Spring Data REST, the output does not match the output structure of the Process API, but is just a plain JSON array with grid-projected processes. Note that any changes to the grid projection on processes, will automatically be applied to this API, as it reuses the projection logic.

[
  {
    "status": "INPROGRESS",
    "cvr": "87654321",
    "lastUpdated": 1529674565000,
    "phase": "PREANALYSIS",
    "rating": 0,
    "title": "Demo dolor sit amet,",
    "domain": "VALUE3",
    "id": 33,
    "shortDescription": "Lorem ipsum dolor sit amet,"
  },
  {
    "status": "INPROGRESS",
    "cvr": "12345678",
    "lastUpdated": 1529748063000,
    "phase": "PREANALYSIS",
    "rating": 0,
    "title": "Demo dolor sit amet,",
    "domain": "VALUE3",
    "id": 1001,
    "shortDescription": "Lorem ipsum dolor sit amet,"
  }
]

Datamodel

See the datamodel for Process

6.2 Comment API

Description

Type Status Comment
Custom Secure API Stable This API is intended for managing comments on a Process. The comments cannot be managed directly on the Process object, as only users with write-access can edit a Process, but anyone with read-access can add a comment.

Useful operations

Below are listed the operations available on this API.

Get all comments for a given process
GET https://www.os2autoproces.eu/api/technologies/<id>
(returns an array of comments for the process with the given id - will return an empty array of the user does not have read-access)
Add a comment to a given process
PUT https://www.os2autoproces.eu/api/technologies/<id>
{
  "message": "My take on this process is that there are too few comments!"
}

(will do nothing if attempted on processes that the user does not have read-access to)

Example output

The output when reading all comments looks like this

[
  {
    "name": "Piotr Suski (psu@digital-identity.dk)",
    "message": "hello 1",
    "created": "2018-06-23 10:35"
  },
  {
    "name": "Piotr Suski (psu@digital-identity.dk)",
    "message": "hello 2",
    "created": "2018-06-23 10:35"
  },
  {
    "name": "Piotr Suski (psu@digital-identity.dk)",
    "message": "hello 3",
    "created": "2018-06-23 10:35"
  }
]

Datamodel

Field Type Nullable Description
name String no A constructed ID of the user, containing name and email address
message String no The actual message entered by the user as a comment
created Date no The timestamp for when the message was created

6.3 Attachment API

Description

Type Status Comment
Custom Secure API Stable This API is managing attachments, and Spring DATA Rest is not an obvious choice for API's with a side-effect (uploading an attachment requires the attachment to be stored outside the database), so a custom API has been written for dealing with attachments.

Useful operations

Below are listed the operations available on this API.

Get a list of attachments for a given process
GET https://www.os2autoproces.eu/api/attachments/<id>
Upload one or more attachments (files) to a given process
POST https://www.os2autoproces.eu/api/attachments/<id>
Upload one or more attachments (files) to a given process, making them visible to other municipalities
POST https://www.os2autoproces.eu/api/attachments/<id>/public
Delete a specific attachment from a given process
DELETE https://www.os2autoproces.eu/api/attachments/<id>/<attachmentId>

Notes about file-upload

The PUT operation accepts ordinary file-uploads, as performed by a web-browser that uploads user selected files from the local file-system. It should be possible to use the standard browser-controls to upload the files to a FORM element, and the PUT the FORM element against the API endpoint.

Example output

When retrieving attachments for a given process, the actual attachments are not returned, but rather metadata about the attachment (filename and the URL where the file can be downloaded)

[
  {
    "id": 1,
    "fileName": "myfile.png",
    "url": "http://domain.com/myfile.png",
    "visibleToOtherMunicipalities": true
  },
  {
    "id": 2,
    "fileName": "mydoc.docx",
    "url": "http://domain.com/mydoc.docx",
    "visibleToOtherMunicipalities": false
  }
]

Datamodel

Field Type Nullable Description
id integer no Unique identifier for the attachment - can be used to delete the attachment later
fileName string no The name of the attachment
url string no The url where the attachment can be downloaded from
visibleToOtherMunicipalities boolean no true if this attachment can be seen by other municipalities

6.4 CMS API

Description

Type Status Comment
Custom Secure API Stable This API allows all users to read data, and users with the role ROLE_FRONTPAGE_EDITOR to update data, where the data is used for modifying text in the frontend (e.g. frontpage). Note that the data is not municipality specific, so any data stored is available for all municipalities.

Useful operations

Below are listed the operations available on this API (note the difference in URL patterns on the two first operations)

Retrieve all stored data
GET https://www.os2autoproces.eu/public/cms
(returns an array of stored data)
Retrieve a given piece of information
GET https://www.os2autoproces.eu/public/cms/<label>
(returns the data stored under the supplied label)
Store/update a given piece of information
POST https://www.os2autoproces.eu/api/cms/<label>
CONTENT

(the body content is stored "as-supplied" - no JSON wrapping)
Delete a given piece of information
DELETE https://www.os2autoproces.eu/api/cms/<label>
(the entry in the database is deleted)

Example output

[
  {
    "label": "frontPageText",
    "content": "Please change this text"
  }
]

Datamodel

Field Type Nullable Description
label String no The id under which the data is stored
content String no The data that is stored

6.5 Notification API

Description

Type Status Comment
Custom Secure API Stable This API is intended for managing the a users notification subscriptions, and is custom created, as the notification subscriptions cannot be managed directly from the user object (the user object is an externally managed object, and the User API is read-only).

Useful operations

Below are listed the operations available on this API.

Start subscribing to notifications for a given process on the currently logged in user
PUT https://www.os2autoproces.eu/api/notifications/<id>
(the supplied id should match a process - if the user has read-access to the process, a subscription is added to the user)
Stop subscribing to notifications for a given process on the currently logged in user
DELETE https://www.os2autoproces.eu/api/notifications/<id>
(the supplied id should match a process - if the user has a subscription for that process, it is removed)

6.6 Excel API

Description

Type Status Comment
Custom Secure API Stable This API is intended for download excel files containing the searched for processes.

Useful operations

Below are listed the operations available on this API. Note there is only one method, and it takes as arguments the exact same as the Process API when searching for processes. The intended use is for the frontend to download an EXCEL file with the processes that a previous search supplied

Download excel file
GET https://www.os2autoproces.eu/api/excel