znanja API
Using this guide
This guide will make use of cURL. cURL is not required for interacting with this API, and it's use in this guide is purely demonstrative. cURL can usually installed by default on your Linux-based environment, or can be installed with
apt-get install curl # Debian-based systems (Debian, Ubuntu)
yum install curl # RedHat based systems (RHEL, CentOS, Fedora)
pacman -S curl # ArchLinux
Instructions for Windows are not provided for the sake of this document, but can be found on the cURL website.
Important Note: Any library that allows you to make HTTP requests, and modify the request headers to include the Authorization
header can be used. For example, python-requests can be used in Python, rest-client for Ruby, cURL PHP for PHP, System.Net.Http in .NET, or Apache HttpComponents in Java.
Important Note: In the $ curl
examples, any trailing '\
' character before a newline denotes line continuation.
About our API
API Versioning
Our API is versioned based on it's version in the path name. This API documentation is for version v1. If no version is given in the path, the most recent version of the API will be used. Additionally, we will confirm the API version number with a response header of
X-znanja-API-version: v1
You can use this to verify which version you are working with.
Existing versions
- v1 - API version 1
- Available from August 2013
API Endpoint Locations
Version 1 API call are are sent to:
https://api.znanja.com/api/hawk/v1
If your Organization defines it's own sub-domain, calls cannot be made to that subdomain. That means, calls must be made to the above endpoint. Calls sent over http
rather than https
will be disregarded. This API requires use over HTTPS.
Request format
All requests that require sending additional information to the server must be sent as JSON. Additionally, you must pass your Content-Type
as application/json
.
Response format
All responses are JSON.
Status Codes
Normal HTTP status codes are returned, and their meaning is retained from the specification. For completion, the following codes are returned most frequently:
- 200 OK - The request was OK and occurred successfully.
- 201 Created - The request to create a resource was successful.
- 202 Accepted - The request has been accepted, and will be completed at a later time.
- This response status code generally means some work will be done asynchronously.
- 204 No Content - The request was successful, but no response body is returned.
- 400 Bad Request - The request that was sent was invalid or otherwise malformed.
- 401 Unauthorized - The request that was sent did not have a valid Authorization header, or was otherwise unauthorized.
- 403 Forbidden - The request was authorized successfully, but access to the requested resource was denied.
- 404 Not Found - The requested resource could not be found.
- 409 Conflict - The request is in a conflicted state with the API.
- 429 Too Many Requests - The request has been rate limited.
Authentication
The znanja API uses Hawk for authentication. Hawk "is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial HTTP request cryptographic verification".
Important Note: *The official Hawk client and server library is written in JavaScript. For unofficial ports in other languages, please see: https://github.com/hueniverse/hawk/issues?labels=port&page=1&state=closed. These language libraries are not the full znanja API library, but rather a helpful library that will take care of Authentication and verification. Understanding the below is still vital to using the znanja API.
Time Synchronization
In order to prevent certain types of "replay attacks", the znanja API requires some time synchronization between the API client and the znanja infrastructure. The znanja API requires synchronization of ±3 minutes.
To accommodate this, we highly recommend the use of NTP. Currently, znanja uses the following NTP servers maintained by National Research Council of Canada:
time.nrc.ca
Any trusted NTP should work within that 6 minute time skew. If the times are not synchronized, the request will be disregarded.
Important Note: This does not require the times to be exactly the same (i.e. timezone). You can continue to use your own timezone, as long as NTP is used.
Credentials
The credentials you are given consist of the following:
- Key identifier - Unique to you, i.e. your API username.
- Key - Your secret key, i.e. your API password.
- Algorithm - The hash algorithm to use to generate your HMAC.
Keep these credentials secret, as they are unique to you. Your credentials are tied directly to both your organization, and your user account. That is, the tuple (organization, user, key) is unique. This means, if you manage multiple organizations with your user account, that are in no way related to one and other via. a "managementship" you will need to generate multiple keys for each organization membership.
Generating an 'Authorization' header
The znanja API uses an Authorization
HTTP header to validate requests that are sent to it. This header can be generated with Hawk.header()
if you are using the Hawk client library, or otherwise as follows. If your credentials are:
- Key Identifier: some-organization-identifier
- Key: s0m3sup3rs3cr3tk3y
- Algorithm: "sha256"
And the current time is 1374546062, and you are sending a POST
request to https://api.znanja.com/api/hawk/v1/users
, with the body of the request the JSON string {"key": "value"}
then your Authorization
header passed must be:
Hawk id="some-organization-identifier", ts="1374546062", nonce="i2v02nvo", hash="tkSPNvcHGAh4c6F4sBmOz5AOZV9ebUrrVrOLigzDNOI=", mac="W1MfFWyncYytxOk5aP3ReoNVMzUmr7YF76Pc9e1YfAE=",
Important Note: The nonce
is created on the client's end to prevent replay attacks. Please do not always use "i2v02nvo" as the nonce
.
Generating a nonce
A nonce should be generated to be a random string. There are no restrictions on this string, however we suggest a random string of at least length 6. You must not re-used a nonce value.
Payload Validation (hash=
)
In order to ensure full understanding between the server and the client, and to verify the requested action, znanja's API makes use of Payload Validation. This allows the API client to validate that the server interacted with the API in the way in which you intended. It can also be used as a quick way to verify the server, and that the API client is communicating to the machine it expects to be communicating with.
The hash=
in the Authorization
header is calculated using the hash algorithm that is used to calculate the mac=
below. This value is then passed as the hash=
portion of the Authorization
header, which the server (and client) can use to verify the request payload. This value comes from calculating the hash using the algorithm
given, and computing the hash of the following string:
hawk.1.payload
CONTENT-TYPE
PAYLOAD
for example, if your payload is: {"key": "value"}
, and the hash algorithm is sha256
, the above would be:
hawk.1.payload
application/json
{"key": "value"}
Giving you a hash of: tkSPNvcHGAh4c6F4sBmOz5AOZV9ebUrrVrOLigzDNOI=
.
Be advised;
- Newlines are important.
- The
CONTENT-TYPE
must be the lower-case Content-Type header. For the sake of this API, it will always be 'application/json
'.
For example, in Python you would do:
from hashlib import sha256
from base64 import b64encode
hash_ = sha256()
hash_.update(b'hawk.1.payload\n\
application/json\n\
{"key": "value"}\n')
hash_digest = b64encode(hash_.digest())
Resulting in a payload hash of tkSPNvcHGAh4c6F4sBmOz5AOZV9ebUrrVrOLigzDNOI=
HMAC Signature Generation (mac=
)
In order to make a request, the client must generate and pass into the Authorization
header, the generated HMAC. This value comes from calculating the HMAC using the algorithm
and the key
, and computing the hash of the following string:
hawk.1.header
TIMESTAMP
NONCE
METHOD
RESOURCE
HOST
PORT
PAYLOAD_HASH
for example, in the above Authorization
header, your string would be
hawk.1.header
1374546062
i2v02nvo
POST
/api/hawk/v1/users
api.znanja.com
443
tkSPNvcHGAh4c6F4sBmOz5AOZV9ebUrrVrOLigzDNOI=
Be advised;
- Newlines are important, including the trailing newline.
- The
METHOD
must be the uppercase HTTP method name. - The
HOST
must be lower case.
For example, in Python you would do:
import hmac
from hashlib import sha256
from base64 import b64encode
mac = hmac.new(b's0m3sup3rs3cr3tk3y', digestmod=sha256)
mac.update(b"hawk.1.payload\n\
1374546062\n\
i2v02nvo\n\
GET\n\
/api/hawk/v1/users\n\
api.znanja.com\n\
443\n\
tkSPNvcHGAh4c6F4sBmOz5AOZV9ebUrrVrOLigzDNOI=\n\
\n")
mac_digest = b64encode(mac.digest())
Where mac_digest
is the string value of mac=
in the Authorization
header, and is calculated to be W1MfFWyncYytxOk5aP3ReoNVMzUmr7YF76Pc9e1YfAE=
Most languages provide an HMAC library already. It is highly suggested you use this library rather than implement your own.
Query Strings in URLs
Some API endpoints allow for additional query strings to be attached to the request to do things like pagination, searching, and filtering. These query parameters must be included in the URL portion used to generate the HMAC.
Validating the Server's Response
In addition to Payload Validation, the server will also send a Server-Authorization
response header, which is similar to the request Authorization
header. The Server-Authorization
header includes the mac=
in the response, which the server generates in the same method above, using the same string. This means, the response mac=
will be identical to the request mac=
.
The hash=
portion of the header is generated similarly as above, except using the server's response payload, rather than the request payload. For example, if the server's response to the above POST request is:
{"username": "kr@example.com"}
Then the response hash=
would be fivAvBQY65rn5+4o+tZYr5tZO1dlFL4ORfBV3DNYiDY=
, making the response Server-Authorization
header
Hawk mac="W1MfFWyncYytxOk5aP3ReoNVMzUmr7YF76Pc9e1YfAE=", hash="fivAvBQY65rn5+4o+tZYr5tZO1dlFL4ORfBV3DNYiDY="
Pagination
Some responses, specifically large lists, will be paginated. Pagination uses query strings to break down the responses that are sent. Query strings for paginations are:
page
- The page index (Default Value: 1)per_page
- The number of elements to show on a single page. You cannot show more than 100 resources per-page. (Default Value: 25, Limit: 100)
If page
and per_page
are omitted, the default values will be used. Additionally, as a Response Header, we will send back a Pageable-Total
header with the total number of resources that can be paginated over in this list.
To make a call to get a list of page 3 of the Organization's users, with 40 results per-page the URL would be: https://api.znanja.com/api/hawk/v1/users?page=3&per_page=40
Searching
Some lists can be searched using a similar mechanism as the Pagination above. This allows you to filter lists based on some criterion. To search append the query string search=
to your endpoint URL. For example to search for user's with the name "Jon", the URL would be: https://api.znanja.com/api/hawk/v1/users?search=Jon
.
The search query parameter can me mixed with the Pagination parameters to paginate the results.
Data types
Date/time strings
A value that specifies a date and optionally a time must be a string using a supported date/time format. While a variety of common date/time formats are accepted, it is recommended that date/time values use ISO 8901 format which is described below.
The date is required. The time and time zone are optional.
Format | Description | Example |
YYYY-MM-DD | Date only | 2000-01-02 (January 2, 2000) |
YYYY-MM-DDThh:mm:ssZ | Date and time | 2000-01-02T03:04:05Z (January 2, 2000 at 3:04:05 AM UTC) |
YYYY-MM-DDThh:mm:ss±zz:zz | Date, time, and time zone | 2000-01-02T03:04:05-04:00 (January 2, 2000 at 3:04:05 AM AST) |
YYYY
is the year.MM
is the month as a number (1 for January, 12 for December).DD
is the day.T
is the separator between the date and time, and appears as is.hh:mm:ss
is the time in hours, minutes, and seconds. If no time is specified, then midnight will be used.- Either
Z
or±zz:zz
specifies the time zone.±zz:zz
is the time zone offset in hours and minutes, positive or negative. IfZ
or no time zone offset is specified, then UTC will be used.
Locale strings
A locale must be specified as string containing a language code. The following is a list of locales supported by the LMS. Values are case sensitive and must not contain any whitespace.
Value | Description |
en | English |
fr | French |
es | Spanish |
zh-CN | Chinese (Simplified) |
zh-TW | Chinese (Traditional) |
ru | Russian |
tl | Tagalog (Filipino) |
ia | English - Alternate Terminology - Resources |
ik | English - Alternate Terminology - Sessions |
Resource types
The znanja API defines the following resource types
Messages
The API may return additional messages in its responses, particularly when an error occurs. A message is a JSON object containing the following values:
Name | Required | Type | Description |
type | No | string | Indicates severity. Possible types are: success , info , warning , and error |
for | No | string | The name of a parameter that is primarily related to this message. |
code | No | string | A machine-readable error code for this message. |
text | Yes | string | A human-readable description. |
For example:
{
"type": "error"
"for": "email",
"code": "duplicate_email",
"text": "That email address is already in use.",
}
It is not recommended to rely on messages for error handling in your application. Messages may change as we improve the platform.
As of August 2022, some endpoints may return message text (text
) that is
translated into the language used by the user calling the API. Some endpoints do
not support translated text and will instead return message text in English.
As of August 2022, some endpoints may return an error code (code
) which are
more specific than HTTP status codes and are intended to be usable by your
application's error handling. However, this is a beta feature. Error codes may
change as we improve the platform.
Errors
Errors are represented in the znanja API as an Error resource along with the appropriate HTTP Status Code. Error Resources are JSON objects containing the following
{
success: false,
messages: [...]
}
Where messages
is an array of message JSON objects described above.
Please do not rely on the messages
array for your error handling, instead rely on the HTTP Status Code response.
Course
A Course resource represents an eLearning course. This is a high-level overview of a course and does not include specifics like the actual contents of the course.
Definition
A Course resource is a JSON object.
Key | Type | Description |
id | integer | Unique identifier. |
organization_id | integer | ID of the Organization resource that owns this course. |
name | string | Course name. |
section_name | string | The name of auto-numbered sections within this course. |
description | string | Course description. |
objectives | string | Course objectives. |
in_storefront | boolean | Whether or not this course is for sale in the storefront. |
in_storefront_carousel | boolean | Whether or not this course is displayed in the storefront carousel. |
price | float | The price listed for this course in the storefront. |
duration | integer | The duration (in minutes) listed for this course in the storefront. |
email_instructor | boolean | Whether or not students can email their instructor. |
instructor_email | string | The email address that will receive emails from students to their instructor. |
can_delete | boolean | Whether or not you can delete this course. |
can_edit | boolean | Whether or not you can edit this course. |
can_export | boolean | Whether or not you can export this course. Note: This is in general. More specific permissions determine if you have access to each type of export. |
can_export_connector | boolean | Whether or not you can export this course as a connector-based SCORM package. |
can_export_static | boolean | Whether or not you can export this course as a full, static SCORM package. |
can_move | boolean | Whether or not you can move this course to a different organization. |
can_report | boolean | Whether or not you can generate reports for this course. |
can_view | boolean | Whether or not you can view the content of this course. |
If you have permission to generate reports for this course
(can_report == true
), then the following values are also included:
Key | Type | Description |
total_students_enrolled | integer | The number of students enrolled in this course. |
total_students_in_progress | integer | The number of students enrolled who have started this course, but not finished. |
total_students_completed | integer | The number of students enrolled who have viewed all pages in this course. |
Example
{
"id": 1,
"organization_id": 2,
"name": "My Course Title",
"section_name": "Section",
"description": "My course description.",
"objectives": "My course objectives.",
"in_storefront": true,
"in_storefront_carousel": false,
"price": 2.5,
"duration": 30,
"email_instructor": true,
"instructor_email": "instructor@example.com",
"can_delete": true,
"can_edit": true,
"can_export": true,
"can_export_connector": true,
"can_export_static": false,
"can_move": true,
"can_report": true,
"can_view": true,
"total_students_enrolled": 20,
"total_students_in_progress": 12,
"total_students_completed": 3
}
Page
A Page resource represents a single page within an eLearning course.
Definition
A Page resource is a JSON object.
Key | Type | Description |
id | string | A unique identifier, based on the path to the page within the course's Table of Contents. |
type | string | Always "page" for pages. |
title | title | The title of the page, as it appears in the Table of Contents. |
auto_number | boolean | Whether or not this page is automatically assigned a section number. |
file | string | The filename of the page's HTML contents, found in the course's zpackage. |
rubric | Rubric resource | The scoring rubric defined for this page. |
required_progress | integer | The amount of progress required before a student can view this page. |
required_score | float | The overall score required before a student can view this page. |
The sign of required_progress
determines how progress is compared:
Zero: There is no progress requirement.
Positive integer: The student's progress in the course must be equal to or greater than (
required_progress
) pages.Negative integer: The student's progress in the course must be equal to or greater than (current page number +
required_progress
) pages.
The sign of required_score
determines how score is compared:
Zero: There is no score requirement.
Positive number: The student must have scored at least (
required_score
) points in the entire course.Negative number: The student must have scored at least (-
required_score
× 100) percent in the entire course. For example,-0.5
means 50% is required.
Example
{
"id": "0",
"type": "page",
"title": "Page 1",
"auto_number": false,
"file": "page1.html",
"rubric": [],
"required_progress": 0,
"required_score": 0
}
Users
The User resource contains information about a single user within the znanja platform. Users are both administrators, non-administrator editor (i.e. editor, instructional designer, content creator). This access information can be found on the Membership resource. This contains useful information about the user themselves. A User resource is:
{
"first_name": "First",
"last_name": "Last",
"is_active": true,
"membership": {
"is_active": true
},
"id": 1,
"last_login": "2013-07-24T13:58:11.118370-03:00",
"email": "email@example.com",
}
Of which, everything is self-explanatory, with the exception of membership
. The membership
key shows user's relationship with this organization. Is is_active
is true
, then the user belongs to the current organization.
As passwords are hashed, we have no way to return a user's password for this call.
Searching
User resources are searched by their last_name
, first_name
, and email
fields.
Sorting
By default, User resources are sorted by name
in asc
order.
sort_by value | Description |
name | Sort users by their last name, then first name, then email address. |
email | Sort users by email addresses. |
last_login | Sort users by the date they last logged in. |
total_courses_assigned | Sort users by the number of courses in which they are enrolled. |
total_courses_in_progress | Sort users by the number of courses they have started, but not finished. |
total_courses_completed | Sort users by the number of courses in which they have viewed all pages. |
User Instructor
A User Instructor resource is a relationship between a user and an instructor directly assigned to the user.
Definition
A User Instructor resource is a JSON object.
Key | Type | Description |
id | string | A unique identifier. |
organization_id | integer | The ID of the organization associated to this user instructor. |
instructor_user_id | integer | The ID of the user who is the instructor. |
instructed_user_id | integer | The ID of the user who is being instructed by the instructor. |
date_created | Date/time string | The date and time when the user instructor was created. |
Example
{
"id": "00000000-0000-0000-0000-000000000000",
"organization_id": 1,
"instructor_user_id": 2,
"instructed_user_id": 3,
"date_created": "2000-01-02T03:04:05Z"
}
Membership
A Membership resource is a relationship between a user and an organization. This allows the user to access content assigned to them by the organization. A membership also contains several role flags which, if enabled, will grant additional permissions to the user, such as administrative access.
Administrators of the organization can modify or revoke the membership at any time. A membership also allows administrators to modify details about the user.
If a membership is not active, all permissions between the user and organization are revoked.
Definition
A Membership resource is a JSON object.
Key | Type | Description |
user_id | integer | The ID of the User resource associated to this membership. |
organization_id | integer | The ID of the Organization resource associated to this membership. |
is_admin | boolean | Whether or not the user is granted the administrator role within the organization. |
is_instructional_designer | boolean | Whether or not the user is granted the instructional designer role within the organization. |
is_creator | boolean | Whether or not the user is granted the content creator role within the organization. |
is_active | boolean | Whether or not this membership is active. If inactive, all access to the organization by the user is revoked. |
can_edit | boolean | Whether or not you can edit this membership. Note: This is in general. More specific permissions determine what you can edit. |
can_edit_api | boolean | Whether or not you can generate API credentials for this membership. |
can_edit_disable | boolean | Whether or not you can set this membership as inactive. |
can_edit_enable | boolean | Whether or not you can set this membership as active. |
can_edit_roles | boolean | Whether or not you can edit the role flags of this membership. |
can_view | boolean | Whether or not you can view details about this membership. |
can_view_api | boolean | Whether or not you can view the API credentials associated to this membership. |
Example
{
"user_id": 1,
"organization_id": 2,
"is_admin": false,
"is_instructional_designer": false,
"is_creator": false,
"is_active": true,
"can_edit": true,
"can_edit_api": true,
"can_edit_roles": false,
"can_edit_disable": false,
"can_edit_enable": false,
"can_view": true,
"can_view_api": true
}
Group
A Group resource contains information about a group belonging to some organization. A group enrolls a set of students into a set of courses and those students can be managed by a set of instructors.
Definition
A Group resource is a JSON object.
Key | Type | Description |
id | integer | A unique identifier. |
organization_id | integer | The ID of the Organization resource that owns this group. |
name | string | The name of the group. |
Example
{
"id": 1,
"organization_id": 2,
"name": "My Group"
}
Group Membership
A Group Membership resource contains information about the association between a user and a group. If such a resource exists, then the user is a member of a group either as a student or an instructor.
Definition
A Group Membership resource is a JSON object.
Key | Type | Description |
group_id | integer | The ID of a Group resource. |
user_id | integer | The ID of a User resource. |
is_instructor | boolean | Whether or not the user is an instructor of this group. |
Some endpoints may include the associated User resource in their response.
Key | Type | Description |
user | User resource | The associated user. |
Example
{
"group_id": 1,
"user_id": 2,
"is_instructor": false
}
Organizations
An Organization resource represents an organization within the znanja platform. A Organization resource is:
{ "datecreated": "2012-10-26T12:38:54.306434-04:00", "domains": ["yourcompany.znanja.com", ...], "hasstorefront": false, "hastrainingpackage": true, "id": 1, "isactive": true, "isparentorg": false, "name": "Organization A" }
Courses
POST /course
Create a new Course resource. This course will contain a default set of assets and a title page. Your user account is also automatically enrolled in the new course.
Request
The request body must be a JSON object.
Parameter | Type | Description |
name | string | The name of the course. Default: Untitled course |
Response
Status code | Description |
201 Created | The Course resource was created successfully. Body: The new Course resource. |
400 Bad Request | If the request parameters are invalid or malformed. |
403 Forbidden | If you are not permitted to create courses for your organization. |
Example
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", hash="F3wfUxCJVu21QsdUyX/Uvpa2ncGM30rIbVKaTf+IUFo=", mac="JHey+x2ql++FcRq1X/ZtAI6xwazPBHBzRh4NnDd53PM="' \
--header 'Content-Type: application/json' \
--data '{"name":"My New Course"}' \
--url https://api.znanja.com/api/hawk/v1/course
HTTP/1.1 201 Created
...
{
"id": 12345,
"name": "My New Course"
"section_name": "Section",
...
}
Pages
These endpoints implement operations for Page resources. The following markers are used in endpoint URLs:
Marker | Type | Description |
:course_id | integer | The ID of a Course resource. |
GET /course/:course_id/pages
Generate a list of pages in a course. The order of the pages is the same as the Table of Contents, without any hierarchy.
Response
Status code | Description |
200 OK | The list was retrieved successfully. Body: An array of Page resources. |
403 Forbidden | If you are not permitted to view the course. |
404 Not Found | If the course was not found. |
Example
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", mac="pMBSKE30+xPbnQH/6ezwe7Y0cfGAlfmkG8ptyDbMaYQ="' \
--url https://api.znanja.com/api/hawk/v1/course/1/pages
HTTP/1.1 200 OK
...
[
{
"id": "0",
"type": "page",
"title": "Page 1",
"auto_number": false,
"file": "page1.html",
"rubric": [],
"required_progress": 0,
"required_score": 0
},
...
]
Users
GET /users
Generate a paginated list of users who are members of your current organization.
Request
This endpoint accepts [pagination][], [search][], and [sort][] parameters.
Response
Status code | Description |
200 OK | The list was retrieved successfully. Body: An array of User resources. |
403 Forbidden | If you are not permitted to view a list of users for your organization. |
Example
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", mac="pQ1cTgg9PleK9Ni9mN6UJulML58k/VSM//TSxGx/Fd0="' \
--url https://api.znanja.com/api/hawk/v1/users
HTTP/1.1 200 OK
...
[
{
"id": 1,
"first_name": "First",
"last_name": "Last",
"membership": {
"id": 2",
...
},
...
},
...
]
GET /user/:id
Return information with the user ID :id
. :id
can either be the numeric User resource id, or the User's email address. For example;
curl -H 'Authorization: Hawk id="some-organization-identifier", ts="1374546062", nonce="TgCmTtYaYQQefY3h2Qpgk6I6", mac="CrnOYbqRWaG0BABycOFXaTXCIVsIjzb1n/oRo1S2kLA="' \
--url https://api.znanja.com/api/hawk/v1/user/1
The response is a single User resource.
This will return:
- 200 OK user is found and available
- 403 Forbidden if you do not have access to view that user's information
- 404 Not Found if the user does not exist.
PUT /user
Create a new user in your organization. The new user will be added to your organization with an active membership. Optionally, the user may be sent a notification email containing their login details.
If a user already exists with the email address you provide, then a new user will not be created and the existing user will be added to your organization instead. Either an active membership will be created or their existing membership will be set to active. However, the existing user's details will not be updated. If the notification email is enabled, they will still receive an email.
Request
Parameters | Required | Type | Description |
first_name | Yes | string | The user's first name. |
last_name | Yes | string | The user's last name. |
email | Yes | string | The user's email address. This is used when logging in and any notification emails will be sent to this address. |
password | No | string | The password the user must use when logging in. If not specified, then a random password will be generated. |
password_confirm | Conditional | string | This field is only required if a password has been specified. It must be the same as password . |
bio | No | string | The user's biography, such as a description of themself. |
locale | No | Locale string or null | The user's language. When the user is logged in, the user interface for the LMS will be translated into this language. If not specified, the default language for your organization will be used. |
expiry | No | Date/time string or null | The date and time when the user's account will expire. |
notify | No | boolean | If true , then the user will be sent a notification email containing their login details. If false or not specified, an email will not be sent. |
Response
If successful, the response body is a User resource. If an error occurs, the response body is an Error resource.
If a password was randomly generated, then the response body will include
a password
value. If you intend for the user to log in with this password and
have not enabled the notification email, then your application must communicate
the password to the user in some way. Otherwise, the user will not know their
password.
Status code | Description |
200 OK | A new user was created or an existing user was updated successfully. |
400 Bad Request | If the request parameters are invalid or malformed. |
403 Forbidden | If you are not permitted to create users. |
Example
curl -H 'Authorization: Hawk id="some-organization-identifier", ts="1374546062", nonce="VtGDBScfn9foFpc1eMh49LIE", hash="O1k77kDf5LdE4GVyJ5+BJrkL79f640all152eQJBMEM=", mac="YqAHD6E9TLKlUDB0tbz6nF+Nba778PjmJHQmExkiwos="'\
-X PUT -d "{\"first_name\":\"First\",\"last_name\":\"Last\",\"email\":\"user@example.com\",\"is_active\":true}"\
-H "Content-Type: application/json"
--url https://api.znanja.com/api/hawk/v1/user
POST /user/:id
Update a user in your organization.
Request
Marker | Type | Description |
:id | number or string | The ID or email address of the user to update. |
Parameters | Required | Type | Description |
first_name | No | string | The user's first name. |
last_name | No | string | The user's last name. |
email | No | string | The user's email address. This is used when logging in and any notification emails will be sent to this address. |
password | No | string | The password the user must use when logging in. |
password_confirm | Conditional | string | This field is only required if a password has been specified. It must be the same as password . |
Response
If successful, the response body is a User resource. If an error occurs, the response body is an Error resource.
Status code | Description |
200 OK | The user was updated successfully. |
400 Bad Request | If the request parameters are invalid or malformed. |
403 Forbidden | If you are not permitted to edit the specified user. |
Example
curl -H 'Authorization: Hawk id="some-organization-identifier", ts="1374546062", nonce="-Wwv4cjp00A7a9TdJrJcK1Op", hash="u0C5rh1pNFrkIuc22WkChljfdDff4oGGAXF/or1yX24=", mac="oGYhWpAlWKFluVi/1FMUjKUJSNdQHc3mOl5tk/vWS3o="'\
-X POST -d "{\"first_name\":\"Joe\",\"last_name\":\"User\",\"email\":\"joeuser@example.com\",\"is_active\":false}"\
-H "Content-Type: application/json" \
--url https://api.znanja.com/api/hawk/v1/user/1
DELETE /user/:id
Disable a User resource on znanja. The user ID :id
. :id
can either be the numeric User resource id, or the User's email address. Disabled Users are disabled only on your Organization, and may still be able to log in, if they are members of other Organizations, but will not be able to access your Organization. If your Organization is the Users only Organization, then the User will be disabled completely.
curl -H 'Authorization: Hawk id="some-organization-identifier", ts="1374546062", nonce="WTf3nKSCAD4mg4F-jYhSFKCS", mac="PjRzaRvwnOlpUn2fC7OQA4YRPBS71g7VVY9WdY6FyzM="' \
-X DELETE
--url https://api.znanja.com/api/hawk/v1/user/1
In response, you will get either:
- 204 No Content is the resource was disabled successfully.
- 403 Forbidden if you, or your Organization do not have permission to modify this User resource.
Additionally, if the user is already disabled at the time of this call, we will return a 204 No Content. This means, 204 No Content confirms in any situation that the user has been disabled.
PUT /user/:id
Re-enable an existing User resource and the Membership defined by the Hawk credentials you are using. If the user is completely disabled, then the User and the Membership will be re-activated, so that the user can log in, and use the LMS as they could before.
curl -H 'Authorization: Hawk id="public_api:membership:4:42", ts="1377100470.095", nonce="Rbzd8SCRbtEuz2o0xB2ggckT", hash="NVuBm+XMyya3Tq4EhpZ0cQWjVUyIA8sKnySkKDOIM4M=", mac="Pqj96u+35zV0wQX1Fm13AFPQcIlrwsraAai6SZrJ67A="' \
-X PUT \
--url https://znanja.dev:6544/api/hawk/v1/user/18
In response, you will get either:
- 200 OK and the exisitng User resource.
- 403 Forbidden if the User resource with the given
:id
can not be modified with the given Hawk credentials. - 404 Not Found if there is no available User resource found with the given
:id
.
User Instructors
POST /user/:instructed_user_id/user-instructor/:instructor_user_id
Add a user instructor to a user.
This grants the instructor permission to view reports for the instructed user.
Request
Marker | Type | Description |
:instructed_user_id | integer | The ID of the user who the instructor will instruct. |
:instructor_user_id | integer | The ID of the user who will be the instructor. |
The user IDs must be different (instructors cannot instruct themselves). The request body must be empty.
Response
If successful, the response body is a User Instructor resource. If an error occurs, the response body is an Error resource.
Status code | Description |
200 OK | The instructor was added successfully. |
400 Bad Request | If the instructor and instructed user IDs are the same. |
403 Forbidden | If you are not permitted to assign the instructor to the user. |
404 Not Found | If the instructor or user were not found or are not members of your organization. |
409 Conflict | If the instructor is already assigned to the user. |
Error code | Description |
not_found | If the instructor or user were not found or are not members of your organization. |
edit_instructor_permission | If you are not permitted to assign the instructor to any user. |
edit_instructed_permission | If you are not permitted to assign any instructor to the user. |
self_reference | If the instructor and instructed users IDs are the same. |
duplicate | If the instructor is already assigned to the user. |
Example
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", mac="ziEqaBXavJfoG7N3AMvMRGLbVTtMAfeI+8+4k2OU3ts="' \
--request POST \
--url https://api.znanja.com/api/hawk/v1/user/1/user-instructor/2
HTTP/1.1 200 OK
...
{
"id": "00000000-0000-0000-0000-000000000000",
...
}
DELETE /user/:instructed_user_id/user-instructor/:instructor_user_id
Remove a user instructor from a user.
The instructor will no longer be able to view reports for the instructed user.
Request
Marker | Type | Description |
:instructed_user_id | integer | The ID of the user who is instructed by the instructor. |
:instructor_user_id | integer | The ID of the user who is the instructor. |
The request body must be empty.
Response
If successful, the response body will be empty. If an error occurs, the response body is an Error resource.
Status code | Description |
204 No Content | The instructor was removed successfully. |
403 Forbidden | If you are not permitted to remove the instructor from the user. |
404 Not Found | If no user instructor relationship was found. |
Error code | Description |
not_found | If no user instructor relationship was found. |
Example
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", mac="+88zNoltGep5eaRo1L6WUiK1TGw2yHBpquAxFdgGB/o="' \
--request DELETE \
--url https://api.znanja.com/api/hawk/v1/user/1/user-instructor/2
HTTP/1.1 204 No Content
...
Memberships
GET /membership/:user_id/:organization_id
Return information about the membership associated to the identified user and organization.
Request
Marker | Type | Description |
:user_id | integer | An ID of a User resource. |
:organization_id | integer | An ID of an Organization resource. |
Response
Status code | Description |
200 OK | The membership was found. Body: The Membership resource. |
403 Forbidden | You do not have permission to view the membership. |
404 Not Found | A membership does not exist between the user and organization. |
Example
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", mac="/qAAwuK5rccE4YZrYmpjVzZqylcRnQcE7sdpqgDi0Lo="' \
--url https://api.znanja.com/api/hawk/v1/membership/1/2
HTTP/1.1 200 OK
...
{
"user_id": 1,
"organization_id": 2,
"is_admin": false,
...
}
PUT /membership/:user_id/:organization_id
Modify the attributes of a Membership resource associated to the identified user and organization.
Request
Marker | Type |
:user_id | integer |
:organization_id | integer |
The request body must be a JSON object.
If you are able to modify the roles for the membership
(can_edit_roles == true
), then the following parameters are accepted:
Parameter | Type |
is_admin | boolean |
is_instructional_designer | boolean |
is_creator | boolean |
If you are able to disable (can_edit_disable == true
) or enable the membership
(can_edit_enable == true
), then the following parameter is accepted:
Parameter | Type |
is_active | boolean |
You can only change is_active
to false
if you can disable the membership.
Likewise, you can only change it to true
if you can enable the membership.
Response
Status code | Description |
200 OK | The membership was modified successfully. Body: The Membership resource. |
400 Bad Request | The request is malformed, the request parameters are invalid, or you do not have permission to change certain parameters. |
403 Forbidden | You do not have permission to edit the membership. |
404 Not Found | A membership does not exist between the user and organization. |
Example
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", hash="ZAJjR8tx9guOG0EtnX/UavnB+hubAUa3UfGlbXGc6Vo=", mac="KaUFETBEBY/zAzc0SXXvMueYDGexLQQkS9G81z1yNtU="' \
--request PUT
--header 'Content-Type: application/json' \
--data '{"is_active":false}' \
--url https://api.znanja.com/api/hawk/v1/membership/1/2
HTTP/1.1 200 OK
...
{
"user_id": 1,
"organization_id": 2,
"is_active": false,
...
}
Groups
GET /groups
Generate a paginated list of groups that belong to your current organization.
Request
This endpoint accepts [pagination][], [search][], and [sort][] parameters. The
name
field will be searched. The default sort is on the name
field in asc
order.
sort_by value | Description |
name | Sort groups by name. |
Response
Status code | Description |
200 OK | The list was retrieved successfully. Body: An array of Group resources. |
403 Forbidden | If you are not permitted to view a list of groups for your organization. |
Example
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", mac="ImYSPt4hfQ2Of1f5nb67MW5xEk2ShHBPtss+DLV/dno="' \
--url https://api.znanja.com/api/hawk/v1/groups
HTTP/1.1 200 OK
...
[
{
"id": 1,
"organization_id": 2,
"name": "My group"
},
...
]
GET /group/:group_id/users
Generate a paginated list of users in a group.
Request
This endpoint accepts [pagination][], [search][], [sort][], and [filter][] parameters.
Filter key | Type | Desciption |
role | string | Filter list by either students, instructors, or available users that can be added to the group. Possible values: students , instructors , or available |
Response
Status code | Description |
200 OK | The list was retrieved successfully. Body: An array of User resources. |
403 Forbidden | If you are not permitted to view a list of users for this group. |
404 Not Found | If the group was not found. |
Example
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", mac="cxiTIKNmfqPDRrzpL59PyZeivvUWWoPhSjRh5MApgR8="' \
--url https://api.znanja.com/api/hawk/v1/group/1/users
[
{
"id": 1,
"first_name": "First",
"last_name": "Last",
...
},
...
]
Group Memberships
These endpoints implement operations for Group Membership resources. The following markers are used in endpoint URIs:
Marker | Type | Description |
:group_id | integer | The ID of a Group resource. |
:user_id | integer | The ID of a User resource. |
GET /group/:group_id/memberships
Generate a paginated list of memberships in a group.
Request
This endpoint accepts [pagination][], [search][], [sort][], and [filter][] parameters. Searching and sorting applies to the related User resource.
Filter key | Type | Description |
role | string | Filter list by either students or instructors. Possible values: students or instructors |
Response
Status code | Description |
200 OK | The list was retrieved successfully. Body: An array of Group Membership resources with associated User resources. |
403 Forbidden | If you are not permitted to view a list of memberships for the group. |
404 Not Found | If the group was not found. |
Example
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", mac="TQqnjKR/Erm+2mkXeCr+dRIYapx1FwfV3FDUf+ujBcw="' \
--url https://api.znanja.com/api/hawk/v1/group/1/memberships
HTTP/1.1 200 OK
...
[
{
"group_id": 1,
"user_id": 2,
"is_instructor": false,
"user": {
"id": 2,
"first_name": "First",
"last_name": "Last",
...
}
},
...
]
POST /group/:group_id/membership/:user_id
Add a user to a group.
This will also automatically enroll the user into all courses that exist in the group.
Request
The request body must be a Group Membership resource. The group_id
and
user_id
values must match the same values in the URL.
Response
Status code | Description |
201 Created | The Group Membership resource was created successfully. Body The new Group Membership resource with the associated User resource. |
400 Bad Request | If the request parameters are invalid or malformed. |
403 Forbidden | If you are not permitted to add the identified user to any group or to add any users to the identified group. |
404 Not Found | If the user or group was not found. |
409 Conflict | If the user is already a member of the group. |
Example
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", hash="4GlBMpikzwEtLyLYP0kTiw9umOB0EMq0KO4sV4j9ghY=", mac="KME6d4Nk54U8rxRucgXDTBRXYLAKBGOPBi1UZElFU68="' \
--header 'Content-Type: application/json' \
--data '{"group_id":1,"user_id":2,"is_instructor":true}' \
--url https://api.znanja.com/api/hawk/v1/group/1/membership/2
HTTP/1.1 201 Created
...
{
"group_id": 1,
"user_id": 2,
"is_instructor": true,
"user": {
"id": 2,
...
}
}
DELETE /group/:group_id/membership/:user_id
Remove a user from a group.
This also withdraws the user from all courses that they were enrolled in via the group, except for any courses that may still be assigned by a different group.
Response
Status code | Description |
204 No Content | The Group Membership resource was deleted successfully. |
403 Forbidden | If you are not permitted to remove users from the group. |
404 Not Found | If the user was not found, the group was not found, or the user is not a member of the group. |
Example
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", mac="Y7hJBG8Se11blDMzw7Dzs7J+pwKkgiL3UO7Jnk9Vbt8="' \
--request DELETE \
--url https://api.znanja.com/api/hawk/v1/group/1/membership/2
HTTP/1.1 204 No Content
...
Vouchers
POST /voucher/:code/redeem
Redeem a voucher either for yourself, a user in your organization, or a new user.
It is not recommended to use this API with vouchers that have a set number of allowed courses (allowing the user to select a subset of courses from the pack instead of being enrolled in all courses in the pack). Course selection is outside the scope of this API since it requires users to log into the LMS in order to access the user interface for selecting courses. Further details are described in the Response section below.
Request
Marker | Type | Description |
:code | string | The code for the voucher to redeem. |
The request body varies depending on which user you are redeeming a voucher for.
To redeem a voucher for yourself, the request body must be empty, null
, or an
empty JSON object.
To redeem a voucher for a specific user, you must specify which user either by their email address or their user ID. The user must be a member of your organization. The request body must be a JSON object containing one of the following parameters:
Parameter | Type |
email | string |
user_id | integer |
To redeem a voucher for a new user, you must specify information needed to create the user. The user will be added as an active member of your organization. The request body must be a JSON object with the following parameters:
Parameters | Required | Type |
first_name | No | string or null |
last_name | No | string or null |
email | Yes | string |
password | Yes | string |
Response
The response body is an Error resource.
If you redeem a voucher for a new user, then the response body will include
a user
resource and a redirect
path.
If you redeem a voucher that has a set number of allowed courses, then the
response body will include a redirect
path.
The redirect
path is an absolute path. To obtain the full URL, you must prefix
this path with https://
and the domain you prefer your users to use when
accessing the LMS. It has the following behavior and requirements:
If the voucher has a set number of allowed courses, then the user must be redirected in order to select which courses to redeem.
If the voucher does not have a set number of allowed courses, then redirecting is optional. The
redirect
path is determined by the organization's login redirect setting (under Settings → Homepage).If the response does not include a
redirect
path, then redirecting is optional.
Redirecting the user is outside the scope of this API since the user must be logged into the LMS in order to access it. The following are some examples on how this can be accomplished:
Your application can use single sign-on to log the user into the LMS and redirect them to the course selection.
Your application can display or email instructions to the user for logging into the LMS and then accessing a link to the course selection.
Status code | Description |
200 OK | The voucher was redeemed successfully. |
400 Bad Request | If the request parameters are invalid or malformed. |
403 Forbidden | If you are not permitted to redeem a voucher for the specified user, the specified user has already redeemed the voucher, the voucher has expired, or the voucher has reached its maximum number of redemptions. |
404 Not Found | If the voucher code or user was not found. |
Error code | Description |
invalid_json | If the request body contains invalid JSON. |
invalid_body | If the request body is not empty, null , or an object. |
not_found | If the voucher code or user was not found. |
non_member | If the user is not a member of your organization. |
create_permission | If you do not have permission to create users for the current organization. |
redeem_permission | If you do not have permission to redeem the voucher for the specified user. |
expired | If the voucher has expired. |
max_redemptions | If the voucher has reached its maximum number of redemptions. |
redeemed | If the user has already redeemed the voucher. |
invalid_user_id | If the user ID is not a number. |
long_first_name | If a new user's first name is too long. |
long_last_name | If a new user's last name is too long. |
duplicate_email | If a new user's email address is already associated with an existing user. |
long_email | If a new user's email address is too long. |
missing_email | If no email address was specified when creating a new user. |
missing_password | If no password was specified when creating a new user. |
short_password | If a new user's password is not long enough. |
Key | Optional | Type | Description |
user | Yes | User resource | The created user, if one was created. |
redirect | Yes | string | An absolute path where the user may need to be redirected to after redemption. |
Examples
Redeeming a voucher for yourself:
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", mac="bWCYhaqCEDKE6y6UuT3uALjM79wIQfRmTIpu4xk1iNI="' \
--request POST \
--url https://api.znanja.com/api/hawk/v1/voucher/EXAMPLE/redeem
HTTP/1.1 200 OK
...
{"success": true}
Redeeming a voucher for an existing user:
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", hash="9fo2J8Jrdtlox+Xft755sQoBhOZt5G0QEKRtXMb6pps=", mac="64er0u8rKhRX6bm/6qPs4x5wixiWkGEJfAvu87B6YDE="' \
--header 'Content-Type: application/json' \
--data '{"email":"user@example.com"}' \
--url https://api.znanja.com/api/hawk/v1/voucher/EXAMPLE/redeem
HTTP/1.1 200 OK
...
{"success": true}
Redeeming a voucher for a new user:
curl --header 'Authorization: Hawk id="example-id", ts="1234567890", nonce="example-nonce", hash="KS57yhipKF57f4Hf6MdZvQQBt4BDo44yiolpl0Lvb84=", mac="40q4/RYFWBetJ9hwgsBqf4sFA4yd+pOMnwiOL6FfBTI="' \
--header 'Content-Type: application/json' \
--data '{"first_name":"Test","last_name":"User","email":"user@example.com","password":"test123"}' \
--url https://api.znanja.com/api/hawk/v1/voucher/EXAMPLE/redeem
HTTP/1.1 200 OK
...
{
"success": true,
"user": { ... },
"redirect": "/lms/dashboard"
}