Overview

Unikum API

Contact information

Contact: Unikum API Team

Contact Email: api@unikum.net

Build version

1.0.1162

Authentication methods

This section describes the different ways of authenticating against Unikum Connect API.

First you need to decide what authentication method that suits your use-case. Use these guidelines to make a decision.

OAuth 2.0

The API supports different grant flows depending on your client needs and use-cases.

If you are developing a backend application working with batches, running headless, without user interaction, usually acting on behalf of multiple other users, you should be using the Client Credentials flow.

Choose any other flow under the following circumstances:

  • You have an application that is acting on behalf of a user.

  • You are developing a mobile application.

  • You want to put the user in control of what sensitive data is shared to external parties.

  • You want Unikum Connect API to handle authentication and authorization flows.

These flows are covered in RFC 6749: https://tools.ietf.org/html/rfc6749

Please read this RFC thoroughly before implementing OAuth 2.0 or other any other security flows for that matter.

Client Credentials Flow

Replaces the now deprecated Server Tokens.

To access any API resource you need to acquire an Access Token from the Unikum Authorization Servers token endpoint.

Unikum needs to provide you with:

  • client_id

  • client_secret

  • token endpoint

Requesting an Access Token from the Authorization Server
HTTP Request

The flow below should be automated using commonly available OAuth 2 client libraries. For reference only.

$ curl https://token_endpoint/unikum/auth/oauth2/token?grant_type=client_credentials -i -X POST \
  --basic \
  --user client_id:client_secret
HTTP Response
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8

{
  "access_token" : "kldfgd34t8fDFKsldjfsf04ifosdFKSLDL...very_long_token...up_to_1024_bytes...",
  "token_type" : "bearer",
  "scope" : "read write"
}

The response is a JSON structure that contains the access token. It is valid only for some time (client dependent). When making API requests, your client must be prepared for it to be invalid at any time, and act by requesting a new fresh token.

Performing an API request

We use Bearer tokens. Hence the Access Token must be passed along as a header with each HTTP request.

HTTP Request
$ curl https://api.unikum.net/me -i -X GET \
  -H "Authorization: Bearer kldfgd34t8fDFKsldjfsf04ifosdFKSLDL..."
GET /me HTTP/1.1
Host: api.unikum.net
Authorization: Bearer kldfgd34t8fDFKsldjfsf04ifosdFKSLDL...
HTTP Response
HTTP/1.1 200 OK

{ ... response ... }
Expired tokens

At any point a token can be invalid; it may have been revoked or simply expired. Your client should then automatically request a new access token as per the flow described above. You must only try to refresh the token once, if it fails again, something else is wrong and your client should back off and flag an error.

Example response when a token is invalid:

HTTP/1.1 401 Unauthorized
Content-Type: application/json;charset=UTF-8
WWW-Authenticate: Bearer realm="oauth2-resource", error="invalid_token", error_description="Error message."

{
  "error" : "invalid_token",
  "error_description" : "Error message."
}

Authorization Code Flow

Use when developing a mobile application or a more advanced web application. This flow keeps the user login credentials safe from your application in that the authentication flow is delegated entirely to being a matter between the user and Unikum.

Your applicaton is only aware of the access token grant delivered when authentication flow is complete.

Accessing the API is done in the same way as with Client Credentials - by passing the Access Token as a Bearer token with each HTTP request.

However retrieving the Access Token is different; this flow requires the user you want to act as to be present and complete the authentication before handing over the Access Token to your application.

Unikum needs to provide you with:

  • client_id

  • client_secret (never expose this to customers, store in backend apps only)

  • authorization endpoint

  • token endpoint

You need to provide Unikum with:

  • redirect_uri

This flow is not outlined in detail but a quick summary is below.

Begin user authentication

Send user to the Authorization Endpoint URL below to initiate the user authentication and/or authorization process.

https://start.unikum.net/unikum/auth/oauth2/authorize
Table 1. Query parameters
Parameter Description

client_id

client_id provided by Unikum.

response_type

Set to 'code'.

scope

Leave empty unless instructed otherwise.

redirect_uri

The full URI or URL the user will be redirected to once authentication is completed.

Receive the authorization code

When the user has authenticated and approved your application to access their data, the user will be redirected to the provided redirect_uri together with a code query parameter:

On users client
HTTP/1.1 302 Found
Location https://redirect_uri?code=abcdefgh
On your server

Extract the (authorization) code query parameter and prepare to use it to exchange for an access token.

Exchange Authorization Code for an Access Token

This step should be server-side only, you must not do this on the user client at all. There are some exceptions to this but generally keep it server-side.

POST to the Unikum Token Endpoint to receive an access token. The endpoint is protected with Basic Auth, use your client credentials to authenticate.

HTTP Request
$ curl https://start.unikum.net/unikum/auth/oauth2/token?code= -i -X POST \
  --basic \
  --user client_id:client_secret
Table 2. Query parameters
Parameter Description

code

The code received in the request above.

grant_type

Set to 'authorization_code'.

redirect_uri

The full URI or URL as used above, must exactly match.

HTTP Response
HTTP/1.1 200 OK

{
  "access_token" : "very_long_access_token",
  "refresh_token" : "very_long_refresh_token",
  "token_type" : "bearer",
  "scope" : "read write"
}
Refreshing an Access Token

Access tokens have a relatively short time-to-live and expires frequently. When expired you should perform a server-side call to the token endpoint to retrieve a new access token. You need to utilize the refresh_token in this flow.

HTTP Request
$ curl https://start.unikum.net/unikum/auth/oauth2/token?grant_type=&refresh_token= -i -X POST \
  --basic \
  --user client_id:client_secret
Table 3. Query parameters
Parameter Description

grant_type

Set to 'refresh_token'.

refresh_token

The most recent received value of 'refresh_token'.

HTTP Response
HTTP/1.1 200 OK

{
  "access_token" : "a_new_very_long_access_token",
  "refresh_token" : "a_new_very_long_refresh_token",
  "token_type" : "bearer",
  "scope" : "read write"
}

Implicit Flow

Disabled by default for security, enabled for special use-cases only.

Using the API

The API is built up of RESTful resources with UTF-8 encoded JSON as payload where applicable. As stipulated by the concepts of RESTful the intended operation to perform is indicated by a HTTP verb. The API follows best-practices, summarized in the table below.

HTTP verbs

HTTP method Description

GET

Read a resource.

POST

Create a new resource.

PATCH

Partially update an existing resource.

PUT

Replace an existing resource or update selected fields.

DELETE

Delete a resource.

Some older HTTP client libraries does not support all of these verbs. In such cases you may need to consider using another more modern library. If this is not possible, please get in touch with the Unikum API Team.

Errors

Errors are indicated with RESTful HTTP codes, enhanced with a common Error object with more detailed information of what went wrong.

Example Error object:

{
  "code": 404,
  "message": "The Person could not be found."
}

Error object description:

Field Data type Description

code

Integer

An optional error code to further narrow the cause of the error. Both code and the HTTP status code may have the same value. In which case the HTTP status code indicates the error root cause, and code is to be treated as a sub-code, even if equal.

message

String

An optional error message that - in a human readable form - describes what went wrong. This message can be changed at any time and is not to be used for automatic error detection in API consumers (in code).

HTTP status codes

These are common HTTP status codes used by the API to indicate the results of an API operation. Status codes >= 400 will be accompanied by an Error object. Here are some of the most commonly used.

200 OK

Returned on successful GET, or after a successful PATCH request.

201 Created

Returned after a successful POST request. Should also contain a Location: header pointing to the newly created resource however this is not yet implemented.

204 No Content

Returned when a resource has been successfully deleted using a DELETE request.

400 Bad Request

Invalid request such as a missing parameter.

401 Unauthorized

We have no idea who you are. You must authenticate yourself. In some cases this is also returned when you don’t have access to a resource to prevent disclosure of whether resources exists or not.

403 Forbidden

You have authenticated yourself but lack access to the resource you are trying to access.

404 Not Found

The resource you tried to access does not exist.

405 Method Not Allowed

Method not accepted on this resource, for example when trying to POST to a resource only supporting GET.

500 Internal Server Error

An unknown error occurred internally with the service provider.

More information on general RESTful patterns and common HTTP status codes can be found in RFC 7231 Section 6.1 (external resource).

Resources

Person

Person object

Description of the Person object. When working with Persons, pay extra attention to the formatting of PID.

Path Type Description

sourcedIds

Array

List of SourcedId objects that identifies this Person.

name

Object

The Name object.

email

String

DEPRECATED Use emails[]. Email address.

adr

Object

The postal address of this person. See Adr object.

emails

Array

List of email addresses associated with the person. See Email object.

phoneNumbers

Array

List of phone numbers associated with the person. See PhoneNumber object.

extension.hideContactDetails

Boolean

Hide contact details. Default: true

extension.allowNotificationMail

Boolean

Allow notification emails. Default: true

extension.allowSchoolMail

Boolean

Allow emails from school. Default: true

extension.allowNewsLetter

Boolean

Allow newsletters from class. Default: true

extension.schoolYear

Number

Curpe rent school year of the Person.

extension.secureSms

String

Mobile phone number to use for step-up authentication (only to be used if agreed with Unikum).

extension.eduPersonPrincipalName

String

Also known as EPPN, if available. Read-only.

Operations

Retrieve a Person

A GET request to retrieve one specific Person.

Table 4. /v1/persons/sourcedId/{source}/{id}
Parameter Description

source

Source of SourcedId

id

Id of SourcedId

Example request
GET /v1/persons/sourcedId/PID/19990101-9999 HTTP/1.1
Host: api.unikum.net
Example response
HTTP/1.1 200 OK
Content-Type: application/json

{
  "sourcedIds" : [ {
    "source" : "UNID",
    "id" : "1"
  }, {
    "source" : "EXTID",
    "id" : "ABC-DEF"
  }, {
    "source" : "PID",
    "id" : "19990101-9999"
  } ],
  "name" : {
    "given" : "Kalle",
    "family" : "Karlsson"
  },
  "adr" : {
    "street" : "Karlsgatan 987",
    "pcode" : "654 32",
    "locality" : "Karlstad"
  },
  "extension" : {
    "hideContactDetails" : false,
    "allowNotificationMail" : true,
    "allowSchoolMail" : false,
    "allowNewsLetter" : true,
    "schoolYear" : 3,
    "secureSms" : "070-22334455",
    "eduPersonPrincipalName" : "kalle@testkommun.edu"
  },
  "phoneNumbers" : [ {
    "phoneNumber" : "0100-10203040",
    "type" : "WORK"
  }, {
    "phoneNumber" : "070-11223344",
    "type" : "HOME",
    "mobile" : true
  }, {
    "phoneNumber" : "098-7654321",
    "type" : "HOME"
  } ],
  "emails" : [ {
    "email" : "kalle.karlsson@student.unikum.net",
    "type" : "STUDENT"
  }, {
    "email" : "kalle.karlsson@privat.unikum.net",
    "type" : "GUARDIAN"
  }, {
    "email" : "kalle.karlsson@testskola.unikum.net",
    "type" : "STAFF"
  } ]
}
Create a new Person

A POST request to create a new Person in Unikum. The Person will by default not belong to any groups or schools. Once the Person is created it can be updated with the PUT method.

An existing Person can currently in v1 also be updated by POSTing the same user data again, however this is to be removed in future versions so please use PUT instead when updating.

See SourcedId documentation for details of how to specify an identifier that can be used for later retrieval of the created Person.

When creating a new Person some fields are mandatory, see table below.

Mandatory fields
Path Type Description

sourcedIds

Array

List of SourcedId objects that identifies this Person.

name

Object

The Name object.

email

String

DEPRECATED Use emails[]. Email address.

adr

Object

The postal address of this person. See Adr object.

emails

Array

List of email addresses associated with the person. See Email object.

phoneNumbers

Array

List of phone numbers associated with the person. See PhoneNumber object.

extension.hideContactDetails

Boolean

Hide contact details. Default: true

extension.allowNotificationMail

Boolean

Allow notification emails. Default: true

extension.allowSchoolMail

Boolean

Allow emails from school. Default: true

extension.allowNewsLetter

Boolean

Allow newsletters from class. Default: true

extension.schoolYear

Number

Curpe rent school year of the Person.

extension.secureSms

String

Mobile phone number to use for step-up authentication (only to be used if agreed with Unikum).

extension.eduPersonPrincipalName

String

Also known as EPPN, if available. Read-only.

Example request
POST /v1/persons HTTP/1.1
Content-Type: application/json
Host: api.unikum.net

{
  "sourcedIds" : [ {
    "source" : "PID",
    "id" : "19990101-9999"
  } ],
  "name" : {
    "given" : "Kalle",
    "family" : "Karlsson"
  },
  "extension" : {
    "allowSchoolMail" : true,
    "allowNewsLetter" : true
  },
  "phoneNumbers" : [ {
    "phoneNumber" : "098-7654321",
    "type" : "HOME"
  }, {
    "phoneNumber" : "070-11223344",
    "type" : "HOME",
    "mobile" : true
  }, {
    "phoneNumber" : "0100-10203040",
    "type" : "WORK"
  } ],
  "emails" : [ {
    "email" : "kalle.karlsson@privat.unikum.net",
    "type" : "GUARDIAN"
  }, {
    "email" : "kalle.karlsson@testskola.unikum.net",
    "type" : "STAFF"
  }, {
    "email" : "kalle.karlsson@student.unikum.net",
    "type" : "STUDENT"
  } ]
}
Example response
HTTP/1.1 201 Created
Location: /v1/persons/sourcedId/UNID/1
Content-Type: application/json

{
  "sourcedIds" : [ {
    "source" : "UNID",
    "id" : "1"
  }, {
    "source" : "EXTID",
    "id" : "ABC-DEF"
  }, {
    "source" : "PID",
    "id" : "19990101-9999"
  } ],
  "name" : {
    "given" : "Kalle",
    "family" : "Karlsson"
  },
  "adr" : {
    "street" : "Karlsgatan 987",
    "pcode" : "654 32",
    "locality" : "Karlstad"
  },
  "extension" : {
    "hideContactDetails" : false,
    "allowNotificationMail" : true,
    "allowSchoolMail" : false,
    "allowNewsLetter" : true,
    "schoolYear" : 3,
    "secureSms" : "070-22334455",
    "eduPersonPrincipalName" : "kalle@testkommun.edu"
  },
  "phoneNumbers" : [ {
    "phoneNumber" : "0100-10203040",
    "type" : "WORK"
  }, {
    "phoneNumber" : "070-11223344",
    "type" : "HOME",
    "mobile" : true
  }, {
    "phoneNumber" : "098-7654321",
    "type" : "HOME"
  } ],
  "emails" : [ {
    "email" : "kalle.karlsson@student.unikum.net",
    "type" : "STUDENT"
  }, {
    "email" : "kalle.karlsson@privat.unikum.net",
    "type" : "GUARDIAN"
  }, {
    "email" : "kalle.karlsson@testskola.unikum.net",
    "type" : "STAFF"
  } ]
}
Update a Person

A PUT request to update an existing Person in Unikum. All fields are optional except the fields that should be updated. Note that if you update the SourcedId the resource URL will change to the new reference and the previous resource will return 404. Also note that null fields are ignored and not cleared as might be expected.

Table 5. /v1/persons/sourcedId/{source}/{id}
Parameter Description

source

Source of SourcedId

id

Id of SourcedId

Example request

Changes given name, family name, secureSms property and removes one phone number and modifies the other two. Emails are left unchanged.

To trigger removal of all emails or phone numbers send in an array with only one entry with an empty string as email or phone.

The arrays are always updated as a block, so if a Person has three emails, and you provide one email in the array, only that will be saved and the other removed.

PUT /v1/persons/sourcedId/PID/19990101-9999 HTTP/1.1
Content-Type: application/json
Host: api.unikum.net

{
  "name" : {
    "given" : "Kalle-Karl",
    "family" : "Karlsson-Efternamn"
  },
  "extension" : {
    "secureSms" : "070-1234567"
  },
  "phoneNumbers" : [ {
    "phoneNumber" : "0200-20304050",
    "type" : "WORK"
  }, {
    "phoneNumber" : "070-22334455",
    "type" : "HOME",
    "mobile" : true
  } ]
}
Example response
HTTP/1.1 200 OK
Content-Type: application/json

{
  "sourcedIds" : [ {
    "source" : "UNID",
    "id" : "1"
  }, {
    "source" : "PID",
    "id" : "19990225-9999"
  } ],
  "name" : {
    "given" : "Kalle-Karl",
    "family" : "Karlsson-Efternamn"
  },
  "adr" : { },
  "extension" : {
    "allowNotificationMail" : true,
    "allowNewsLetter" : true,
    "secureSms" : "070-1234567",
    "eduPersonPrincipalName" : "kalle@testkommun.edu"
  },
  "phoneNumbers" : [ {
    "phoneNumber" : "070-22334455",
    "type" : "HOME",
    "mobile" : true
  }, {
    "phoneNumber" : "0200-20304050",
    "type" : "WORK"
  } ],
  "emails" : [ {
    "email" : "kalle.karlsson@student.unikum.net",
    "type" : "STUDENT"
  }, {
    "email" : "kalle.karlsson@privat.unikum.net",
    "type" : "GUARDIAN"
  }, {
    "email" : "kalle.karlsson@testskola.unikum.net",
    "type" : "STAFF"
  } ]
}
Create and/or Update a Person

A POST will currently both create a Person if it does not exist, or if it exists it will update the Person.

This is useful if you don’t need to know the previous state of a Person but just want to "mirror" whatever information is in the source system.

To only update, please use PUT.

Delete a Person

A DELETE request will completely remove all memberships the Person has in the organization.

Table 6. /v1/persons/sourcedId/{source}/{id}
Parameter Description

source

Source of SourcedId

id

Id of SourcedId

Example request
DELETE /v1/persons/sourcedId/PID/19990101-9999 HTTP/1.1
Host: api.unikum.net
Example response
HTTP/1.1 204 No Content

Group

A group is a holder object for entities other than Persons, such as a school, organizational unit, class, a department, an educational unit, etc. Allowed group types are listed in Appendix: groupType object.

Below is details on how to work with each of these group types.

Classes

Description of the Group object when groupType is of type CLASS.

Path Type Description

sourcedIds

Array

List of SourcedId objects that identifies this Group.

groupType

String

Appendix: groupType CLASS

description.short

String

Name of the class.

description.long

String

Longer description of the class.

extension.subject

String

Subject code, if available.

extension.course

String

Course code, if available.

extension.ageRangeFrom

Number

From grade (school year).

extension.ageRangeTo

Number

To grade (school year).

extension.integratedSchoolType

String

The school type of this group, may differ from the parent schools school type, see Appendix: schoolType

extension.tuitionGroup

Boolean

True if it is a tuition group.

Create a Class

A POST request to create a new Class.

Example request
POST /v1/groups HTTP/1.1
Content-Type: application/json
Host: api.unikum.net

{
  "sourcedIds" : [ {
    "source" : "EXTID",
    "id" : "SVA01"
  } ],
  "description" : {
    "short" : "Svenska A",
    "long" : "Grundkurs i svenska nivå A"
  },
  "groupType" : "CLASS",
  "extension" : {
    "course" : "SVSESVASVA01",
    "ageRangeFrom" : 7,
    "ageRangeTo" : 7,
    "tuitionGroup" : true,
    "integratedSchoolType" : "SE_GYS"
  }
}
Example response
HTTP/1.1 201 Created
Location: /v1/groups/sourcedId/EXTID/SVA01
Content-Type: application/json

{
  "sourcedIds" : [ {
    "source" : "UNID",
    "id" : "400"
  }, {
    "source" : "EXTID",
    "id" : "SVA01"
  } ],
  "description" : {
    "short" : "Svenska A",
    "long" : "Grundkurs i svenska A"
  },
  "groupType" : "CLASS",
  "extension" : {
    "course" : "SVSESVASVA01",
    "courseCode" : "SVSESVASVA01",
    "ageRangeFrom" : 7,
    "ageRangeTo" : 7,
    "tuitionGroup" : false,
    "integratedSchoolType" : "SE_GYS"
  }
}

Schools

Description of the Group object when groupType is of type SCHOOL.

Path Type Description

sourcedIds

Array

List of SourcedId objects that identifies this Group.

groupType

String

Appendix: groupType SCHOOL

description.short

String

Name of the school.

description.long

String

Longer description of the school.

url

String

URL to the schools homepage.

extension.schoolType

String

Type of school see Appendix: schoolType

extension.detailedSchoolType

String

If available may be a more specific school type see Appendix: schoolType

extension.visitingAddress

Object

Address of school. See Adr object.

extension.extraAddress

String

Additional address or address information.

extension.tel

String

Primary telephone number.

extension.telFax

String

Telefax number.

extension.sisSchoolUnitCode

String

Numeric code for the school (SCB school unit code)

extension.ageRangeFrom

Number

From grade (school year).

extension.ageRangeTo

Number

To grade (school year).

Create a School

A POST request to create a new School.

Example request
POST /v1/groups HTTP/1.1
Content-Type: application/json
Host: api.unikum.net

{
  "sourcedIds" : [ {
    "source" : "EXTID",
    "id" : "TYSKSKOL1"
  } ],
  "description" : {
    "short" : "Tyska skolan",
    "long" : "Tyska Skolan Stockholm (DSS)"
  },
  "groupType" : "SCHOOL",
  "extension" : {
    "schoolType" : "SE_GY",
    "visitingAddress" : {
      "street" : "Karlavägen 25",
      "pcode" : "114 31",
      "locality" : "Stockholm"
    },
    "extraAddress" : "En annan adress 99, 111 22 Stockholm",
    "tel" : "070-000 00 00",
    "telFax" : "08-00 00 00",
    "sisSchoolUnitCode" : "300050",
    "ageRangeFrom" : 16,
    "ageRangeTo" : 19,
    "detailedSchoolType" : "SE_GYS"
  },
  "url" : "http://tyskaskolan.se/"
}
Example response
HTTP/1.1 201 Created
Location: /v1/groups/sourcedId/EXTID/TYSKSKOL1
Content-Type: application/json

{
  "sourcedIds" : [ {
    "source" : "UNID",
    "id" : "300"
  }, {
    "source" : "EXTID",
    "id" : "TYSKSKOL1"
  } ],
  "description" : {
    "short" : "Tyska skolan",
    "long" : "Tyska Skolan Stockholm (DSS)"
  },
  "groupType" : "SCHOOL",
  "extension" : {
    "schoolType" : "SE_GY",
    "visitingAddress" : {
      "street" : "Karlavägen 25",
      "pcode" : "114 31",
      "locality" : "Stockholm"
    },
    "extraAddress" : "En annan adress 99, 111 22 Stockholm",
    "tel" : "070-000 00 00",
    "telFax" : "08-00 00 00",
    "sisSchoolUnitCode" : "300050",
    "ageRangeFrom" : 10,
    "ageRangeTo" : 12,
    "detailedSchoolType" : "SE_GYS"
  },
  "url" : "http://tyskaskolan.se/"
}

Common operations

Get a Group

A GET request to retrieve an existing Group.

GET /v1/groups/sourcedId/EXTID/SVA01

The response is a Group structure.

Update a Group

A PUT request to update information about an existing Group. Works for all group types.

All fields in the supplied Group object are optional except the fields that should be updated. Note that if you update the SourcedId the resource URL will change to the new reference and the previous resource will return 404. Also note that fields set to null will be ignored as opposed to being cleared as might be expected.

Table 7. /v1/groups/sourcedId/{source}/{id}
Parameter Description

source

Source of SourcedId

id

Id of SourcedId

Example request
PUT /v1/groups/sourcedId/EXTID/TYSKSKOL1 HTTP/1.1
Content-Type: application/json
Host: api.unikum.net

{
  "sourcedIds" : [ ],
  "description" : {
    "long" : "Tyska Skolan (En annan beskrivning)"
  },
  "extension" : {
    "visitingAddress" : {
      "street" : "Ny gatuadress 999",
      "pcode" : "123 45"
    },
    "tel" : "000-888 88 88"
  }
}
Example response
HTTP/1.1 200 OK
Content-Type: application/json

{
  "sourcedIds" : [ {
    "source" : "UNID",
    "id" : "300"
  }, {
    "source" : "EXTID",
    "id" : "TYSKSKOL1"
  } ],
  "description" : {
    "short" : "Tyska skolan",
    "long" : "Tyska Skolan (En annan beskrivning)"
  },
  "groupType" : "SCHOOL",
  "extension" : {
    "schoolType" : "SE_GY",
    "visitingAddress" : {
      "street" : "Ny gatuadress 999",
      "pcode" : "123 45",
      "locality" : "Stockholm"
    },
    "tel" : "000-888 88 88",
    "telFax" : "08-00 00 00",
    "sisSchoolUnitCode" : "300050",
    "ageRangeFrom" : 10,
    "ageRangeTo" : 12
  },
  "url" : "http://tyskaskolan.se/"
}
Delete a Group

A DELETE request will remove a Group from your inventory. There are rules of deletion that applies depending on the type of Group you are trying to delete.

Deleting a Group of type SCHOOL will remove all decending Group entities connected to this Group. This means that for example every CLASS linked to the Group will be removed.

Deleting a Group of type CLASS will unlink all Persons belonging to this Group.

This example will remove a school and all entities connected to it.

Table 8. /v1/groups/sourcedId/{source}/{id}
Parameter Description

source

Source of SourcedId

id

Id of SourcedId

Example request
DELETE /v1/groups/sourcedId/EXTID/TYSKSKOL1 HTTP/1.1
Content-Type: application/json
Host: api.unikum.net
Example response
HTTP/1.1 204 No Content

Membership

Use this resource to control memberships and relations between objects such as groups and persons.

Membership object

Description of the Membership object. This model describes the relationship between groups and persons or groups and groups. For example a Person can be added as a Teacher in a Group. A Class can be added to a School. A Timeframe field that specifies the memberships validity may also be provided.

Path Type Description

member

Object

The SourcedId object that is assigned as a member in the resource SourcedId.

idType

String

Member type, one of: GROUP, PERSON

roleType

String

Membership role, see roleType.

timeframe

Object

The Timeframe object that limits the membership by time.

roleType is one of the following:

Constant Description

ADMINISTRATOR

Administrator for a school or a class.

GUARDIAN

Guardian of a child.

HEADMASTER

Headmaster of a school.

INSTRUCTOR

Teacher of a class.

MEMBER

A class in a school, a school in an organization, a person in a team, a team in a group or school

MENTOR

A mentor for a child.

STAFF

Staff in a school or in a team.

STUDENT

A student in a school, a class or a team.

Operations

Add a Membership

A PUT request adds a membership of the provided member to the resource. A resource can have multiple memberships. If the membership already exists it will be re-created with the parameters provided.

The example below will add the Person with PID 19550101-9999 as an INSTRUCTOR to the GROUP (a class) EXTID SVA01.

Table 9. /v1/memberships/sourcedId/{source}/{id}
Parameter Description

source

Source of SourcedId

id

Id of SourcedId

Request object
Path Type Description

member

Object

The SourcedId object that is assigned as a member in the resource SourcedId.

idType

String

Member type, one of: GROUP, PERSON

roleType

String

Membership role, see roleType.

timeframe

Object

The Timeframe object that limits the membership by time.

Example request

Add a Person to a Group.

PUT /v1/memberships/sourcedId/EXTID/SVA01 HTTP/1.1
Content-Type: application/json
Host: api.unikum.net

{
  "member" : {
    "source" : "PID",
    "id" : "19550101-9999"
  },
  "idType" : "PERSON",
  "roleType" : "INSTRUCTOR",
  "timeframe" : {
    "fromDate" : "2014-02-05",
    "toDate" : "2017-01-06"
  }
}
Example response
HTTP/1.1 200 OK
Remove a Membership

A DELETE request to remove a membership (relation) between this resource and the member provided. Successful deletes returns status code 204 with an empty payload. The payload is the same as when adding memberships, i.e. this operation reverts the operation in the example above.

You should not use this method to delete entities such as Groups or Persons. Use corresponding DELETE methods instead.

Example request

Deletes the membership created in the example above.

DELETE /v1/memberships/sourcedId/EXTID/SVA01 HTTP/1.1
Content-Type: application/json
Host: api.unikum.net

{
  "member" : {
    "source" : "PID",
    "id" : "19550101-9999"
  },
  "idType" : "PERSON",
  "roleType" : "INSTRUCTOR"
}
Example response
HTTP/1.1 204 No Content

Export (version 2)

Please note that this describes version 2 of the Export feature.

The Export resource provides a complete dump of the Persons, Groups and Memberships in your entity.

The Export resource also has a Delta capability that provides changes based off a previous export.

An export or a delta generally involves three steps:

  1. A POST request to start the export.

  2. A GET request to periodically query the export progress.

  3. A GET request to retrieve the full export results once completed.

To export Teams related data the structures and documentation below still applies, but you need to use different HTTP endpoints. Please read the Teams Export documentation for further Teams specific details.

Start an Export

A POST request to start an Export. The post body can be empty.

POST /v2/exports

Response:

HTTP/1.1 202 Accepted

{
    "jobId": "4d8abbf3-10a8-4582-8b2b-af49a139073c",
    "monitorHref": "/v2/exports/queue/4d8abbf3-10a8-4582-8b2b-af49a139073c"
}

HTTP response code 202 indicates a new export was created. HTTP response code 200 means there is already an export ongoing and that you need to check the monitorHref for progress.

Your application should now periodically poll the monitorHref endpoint for progress.

Export progress

A GET request to check the progress of an export.

GET /v2/exports/queue/7e2074cb-79db-4a7a-84c8-9873b88925e2

Response:

{
    "jobId": "7e2074cb-79db-4a7a-84c8-9873b88925e2",
    "resourceHref": "/v2/exports/a0df0328-f8b4-4efb-9f25-2e0f7380f2c6",
    "status": "DONE",
    "statusChangeDate": "2019-05-29T10:02:37.166Z"
}

Status codes:

Status Description

ACCEPTED

The request was accepted but not yet started. Poll every minute for progress.

IN_PROGRESS

The export has started and will be completed usually within half an hour. Poll every minute for progress.

DONE

Export operation completed. The results is available on the resourceHref path. Status will not change again so stop polling for progress.

ERROR

An error has occured. Check the error field for more details. Status will not change again so stop polling for progress.

Retrieve an Export

A GET request to retrieve a previously created Export.

GET /v2/exports/9ef84b06-f758-4f6c-9d1e-ebd411531b38

Response:

{
    "exportId": "9ef84b06-f758-4f6c-9d1e-ebd411531b38",
    "persons": [ ],
    "groups": [ ],
    "memberships": [ ]
}

Request a Delta

You can retrieve a Delta with changes between a previously created Export and now. The semantics of starting a delta export is the same as a regular export but the endpoints differ.

POST /v2/exports/9ef84b06-f758-4f6c-9d1e-ebd411531b38/delta

Response:

HTTP/1.1 202 Accepted

{
    "jobId": "4d8abbf3-10a8-4582-8b2b-af49a139073c",
    "monitorHref": "/v2/exports/queue/4d8abbf3-10a8-4582-8b2b-af49a139073c"
}

HTTP response code 202 indicates a new delta export was created. HTTP response code 200 means there is already a delta export ongoing and that you need to check the monitorHref for progress.

Your application should now periodically poll the monitorHref endpoint for progress.

Delta progress

See section "Export progress".

Retrieve a Delta

Make note of the newExportId property, it is used when you again want to request a new Delta with changes from this Delta.

You can also use the newExportId property to retrieve the associated full Export.

GET /v2/exports/9ef84b06-f758-4f6c-9d1e-ebd411531b38/delta

Response:

{
    "oldExportId": "9ef84b06-f758-4f6c-9d1e-ebd411531b38",
    "newExportId": "2ce39d2f-963d-49fe-8730-3026b9fbd053",
    "persons": {
        "add": [ ],
        "remove": [ ],
        "replace": [ ]
    },
    "groups": {
        "add": [ ],
        "remove": [ ],
        "replace": [ ]
    },
    "memberships": {
        "add": [ ],
        "remove": [ ],
    }
}

Teams

Team object

A Team is a subset of a Group with some additional data in the extension section.

Teams Export

Exporting teams works exactly the same as the regular Export except that the endpoints are different. Since a Team is a subset of a Group, the teams are listed in the groups section with its groupType set to TEAM.

Other types of groups such as schools may also be present and the relationship described via the memberships section.

Retrieve an Export
GET /v2/teams/exports/37f5ee05-d0af-41c8-82b8-d09b4686d365 HTTP/1.1
Host: api.unikum.net
Fields in a Teams Export
Path Type Description

exportId

String

Id of the retrieved export.

teamsConfig

Object

Common configuration for this team setup.

academicYear

Object

Academic year.

groups[].sourcedIds[].source

String

Always set to 'SIS'

groups[].sourcedIds[].id

String

ID of the Team or School.

groups[].description.short

String

Name of the Team or School.

groups[].description.long

String

Longer description of the Team or School.

groups[].timeframe

Object

Timeframe with start/stop dates for a Team.

groups[].groupType

String

One of 'TEAM' or 'SCHOOL'

groups[].extension.team

Object

Team details

groups[].extension.team.type

String

Always set to 'CLASS'

groups[].extension.team.useMSAssignment

Boolean

Whether or not to use Assignments

groups[].extension.team.channels[].isDefaultChannel

Boolean

True if this channel is the default.

groups[].extension.team.channels[].name

String

Name of the non-default channel.

groups[].extension.team.channels[].tabs[]

Array

tabs

memberships[].sourcedId

Object

A SourcedId object of a Team or School. Source is always 'SIS'.

memberships[].rel[].member

Object

A SourcedId object of a Person or Team that is a member of the parent object.

memberships[].rel[].roleType

String

The role of this member, onr of STUDENT, STAFF or TEAM.

persons[].sourcedIds[].source

String

Should be 'SIS'

persons[].sourcedIds[].id

String

ID of the Person

persons[].name.given

String

First name of the Person.

persons[].name.family

String

Family name of the Person.

persons[].email

String

Email address of the Person.

Objects

Adr

This object represents an address and its location.

Path Type Description

street

String

Street address

pcode

String

Postal/Zip code

locality

String

Postal city, town, area

Email

This object represents an email address and its properties.

Path Type Description

email

String

Email address.

type

String

The scope of this email address. One of:

STAFF

GUARDIAN

STUDENT

emails[]

Some APIs return an array of email addresses. There is no de-duplication done, so it’s possible that the same email is present multiple times in the list, or that e.g. STAFF have two or more emails listed. This all depends on what data we receive from our upstreams.

Usually though each type is present only once.

Extension

Some operations require additional data passed to the API that may vary on other input such as group type or membership type. This is explained in their respective API method documentation.

Name

This object contains the name of a Person.

Path Type Description

given

String

Given name, e.g. John

family

String

Family name, e.g. Smith

PhoneNumber

This object represents a phone number and its properties.

Path Type Description

phoneNumber

String

The phone number.

type

String

One of:

HOME

WORK

mobile

Boolean

(optional) "true" or "false". Defaults to "false". Indicates if this is a mobile/cellphone number. Note that it’s only an indication and no guarantee that the number is a cellphone or not.

phoneNumbers[]

Some APIs return an array of phone numbers. There is no de-duplication done, so it’s possible that the same phone number is present multiple times in the list, or that e.g. HOME have two or more phone numbers listed. This all depends on what data we receive from our upstreams.

Usually though each type is present only once.

SourcedId

An identifier to uniquely identify the resource within an organization. A resource can be identified by one or more sourcedIds.

Example of one sourcedId:

"sourcedId" : {
    "source" : "PID",
    "id" : "19990101-9999"
}

Example of a resource identified by one or more sourcedIds:

"sourcedIds": [
    {
        "source" : "UNID",
        "id" : "12345"
    },
    {
        "source" : "EXTID",
        "id" : "My_School_123_Unit_456_Class"
    }
]
Path Type Description

source

String

Describes the scope of the resource. The meaning of this value must be agreed upon between the consumer and the provider. Currently accepted values are: PID, EXTID, UNID, SIS

See table below for specifics.

id

String

The id part of the sourcedId. If referencing a Person, this value would be for example 19991231-1234 or for a TF-number it’d be 19991231-TF01.

See below for specifics of formatting a PID.

SourcedId 'source' types

Type Description

PID

Personal ID, see formatting a PID.

EXTID

String defined by the source system (you) that can identify the resource in subsequent calls.

UNID

Persistent ID that is provided by Unikum to uniquely identifiy a resource. It stays the same even when the EXTID or PID changes.

SIS

School Information System ID. Used with Teams.

Personal ID formatting

Different countries issues personal ids in different forms and factors. Below are examples from the countries we support and how the personal ids MUST be formatted.

Country Common name Length Format

Sweden

Personnummer

13

YYYYMMDD-NNNN

19991231-0123

20001231-TF99

Finland

Personbeteckning

11

DDMMYYCNNNX

311299-1234

311200A1234

Please note that the first 6 digits are in order Day-Month-Year. C is a century indicator: "+" is 1800, "-" is 1900 and "A" is 2000. NNN = 3 digits with gender and other info. The last X is a control character.

Tel

This object represents a contact phone number like a mobile number, landline, or fax.

Path Type Description

tel

String

Telephone number, no specific format required.

telType

String

Type of phone number. Values are: "1" for Voice, "3" for Mobile.

Timeframe

The object specifies the timeframe validity of an entity. An empty or missing object means that there is no timeframe that limits the object. A timeframe can however be present in future requests.

Path Type Description

fromDate

String

A date string, e.g. 2014-03-01. Empty or missing date means eternity. The range can between 0001-01-01 to 9999-12-31.

toDate

String

A date string, e.g. 2018-03-01. Empty or missing date means eternity. The range can between 0001-01-01 to 9999-12-31.

Appendix

Appendix: groupType

Data type: String

Set to one of the following constants:

Constant Description

CLASS

Class

SCHOOL

School

TEAM

Team

There may be additional information that needs to be passed to the API that varies depending on what value is set here. This additional data is specified in the Extension object.

Appendix: roleType

Data type: String

Used when creating memberships. Not all roles are applicable to all group types. Set to one of the following constants:

Constant Description

ADMINISTRATOR

Administrator for a school or a class.

GUARDIAN

Guardian of a child.

HEADMASTER

Headmaster of a school.

INSTRUCTOR

Teacher of a class.

MEMBER

A class in a school, a school in an organization, a person in a team, a team in a group or school

MENTOR

A mentor for a child.

STAFF

Staff in a school or in a team.

STUDENT

A student in a school, a class or a team.

Appendix: schoolType

Data type: String

Set to one of the following constants:

Constant Description

SE_PC

Familjedaghem

SE_F

Fritids

SE_FK

Förskoleklass

SE_FS

Förskola

SE_GS

Grundskola

SE_GSS

Anpassad grundskola

SE_GY

Gymnasieskola

SE_GYS

Anpassad gymnasieskola

SE_MED

Medarbetarsamtal

SE_SPS

Specialskola

SE_TRS

Träningsskola (deprecated)

SE_SFI

SFI

SE_FHS

Folkhögskola

SE_UNI

Universitet

SE_VUX

Vuxenutbildning

SE_VUXS

Anpassad vuxenutbildning

Other endpoints

Health status

Ping

Verify that the API on this address is alive and well. Returns http status code 200 if all is well.

Example request
$ curl 'https://api.unikum.net/ping' -i -X GET
GET /ping HTTP/1.1
Host: api.unikum.net
Example response
HTTP/1.1 200 OK
Content-Type: text/plain;charset=UTF-8

pong