# EduBase API Documentation *Auto-generated on Sun Mar 16 07:37:49 UTC 2025* --- ## Table of Contents - [Welcome to the EduBase Developer Help](#Welcome-to-the-EduBase-Developer-Help) - [Introduction](#Introduction) - [Authentication](#Authentication) - [API: Classes endpoints](#API:-Classes-endpoints) - [API: Exams endpoints](#API:-Exams-endpoints) - [API: Metrics endpoints](#API:-Metrics-endpoints) - [API: Organizations endpoints](#API:-Organizations-endpoints) - [API: Content permissions endpoints](#API:-Content-permissions-endpoints) - [API: Quiz Plays endpoints](#API:-Quiz-Plays-endpoints) - [API: Quiz questions endpoints](#API:-Quiz-questions-endpoints) - [API: Quizes endpoints](#API:-Quizes-endpoints) - [API: Content tagging endpoints](#API:-Content-tagging-endpoints) - [API: Users endpoints](#API:-Users-endpoints) - [Contact](#Contact) - [Legal](#Legal) --- ## Welcome to the EduBase Developer Help This documentation will help you integrate your software or service with EduBase. If these guides get too technical and you feel stuck, please contact us. !!! tip You will most likely **need an EduBase account** to follow the documentation. Therefore it is recommended to [register](https://www.edubase.net/page/register) and get familiar with EduBase before continuing. ### What is EduBase? If you are not yet familiar with our services you might want to visit our [homepage](https://www.edubase.net) or [Business page](https://www.edubase.net/business) or even the EduBase Quiz product [introduction page](https://www.edubasequiz.com/en/). !!! summary "Briefly, in one sentence" EduBase is an innovative, modular, online educational platform that makes learning more enjoyable, simpler and interactive, suitable for educational institutions or enterprises. ### LTI integration EduBase also **supports LTI protocols** (1.0, 1.1 and 1.3/Advantage). If you want to integrate your LMS with EduBase Quiz system, we recommend using the LTI integration which provides a standardized solution to embed practice Quizes and exams into LMS courses and contents. Our integration also sends results back right into the LMS (if feature is supported/enabled), so there are no manual steps involved! Get started today with an LTI integration! To **learn more about this type of integration** and quickly get started, please visit [our EduAppCenter page](https://www.eduappcenter.com/apps/1082). ### See EduBase Quiz in action Curious how Quiz tests look like? **Launch our demo set** by clicking the image to get started: [![Start EduBase Quiz demo set](images/index-game.png){: style="width:100%"}](https://eduba.se/+EduBaseQuizDemo/EN) --- ## API ### Introduction #### Prerequisites To access **EduBase API services**, you need the following: * an EduBase account * registered API application (connected to the user) * application ID * application secret #### Obtain API credentials To obtain your API application ID and secret key, login to EduBase with your account and go to the [Integrations](https://www.edubase.net/content/integrations) page. Create an API application or view your existing one. If you lack of permissions to create integrations, please contact us. !!! warning Do not share API credentials with anyone. #### Endpoints Endpoints are constructed from the following informations: * `https://` * EduBase domain name (e.g `www.edubase.net`) * `/api` * *optional: version specification `/vXX*` * endpoint path (e.g `/test:app`) Putting them all together, a request URL is created: ``` text https://www.edubase.net/api/v1/test:app ``` !!! warning Some endpoints require special features to be enabled (either on user or global level). Additionally, endpoints may also be protected by policies. Please contact us if you repeatedly receive authorization errors (e.g 403/406 response status code). #### Versions A call version can be specified for each request separately. There are 2 possible ways: * recommended: in the endpoint URL * /vXX where **XX** can only be numeric * as call argument * add version=**XX** argument to API call, **XX** can be a numeric value or a string If requested endpoint does not support the selected version (or the version does not even exist), an error will be thrown. #### Methods The API service supports **GET**, **POST**, **PUT**, **PATCH** and **DELETE** requests. However, not all endpoints implement all of them. Please refer to the endpoint's specification before calling it. #### Arguments !!! warning Do not forget to send *app* and *secret* API credentials. They are **always required**. Endpoints may require or allow to send additional input parameters. These can be sent in: * as REQUEST parameter * as POST data * in the request body ##### Data types * **string** * **{m,M}** means minimum `m`, maximum `M` characters * **{N}** is a shorthand for `{N,N}` * **string/null**: a *string* formatted string or NULL if not set * **integer**: a whole number, represented as string * **float**: a decimal number, represented as string (with `.` as decimal separator) * **boolean**: `true`/`false` string * **boolean/null**: a *boolean* formatted string or NULL if not set * **date**: `YYYY-MM-DD` formatted string * **date/null**: a *date* formatted string or NULL if not set * **datetime**: `YYYY-MM-DD HH:ii:ss` formatted string, in UTC * **datetime/null**: a *datetime* formatted string or NULL if not set * **list{type}**: a list (array) of *type* elements * **list**: a hash (associative array) of named elements !!! info JSON-encoded outputs will represent data with their native type (if supported by JSON), instead of strings. For example a boolean will be represented as boolean. #### Response codes and output ##### Response API service may **return status, headers and data**: * HTTP response status code * EduBase-API-Error header (with an error description or code) * plain text * JSON-encoded text (Content-Type is set to application/json) ##### Possible HTTP response codes * **200**: success * **400**: incorrect endpoint is called or request could not be served temporarily * **401**: invalid/missing credentials or assume token is invalid * **403**: endpoint is found, but arguments are not properly set or permission is denied for requested action * **405**: HTTP request method is not supported * **406**: incorrect version is selected, endpoint is not available for current API client application or configured limit has been reached * **429**: too many requests, configured rate limit has been exceeded * **500**: call is valid, but there was an unexpected error while processing it * **501**: endpoint and arguments might be correct, but feature is not yet implemented * **503**: service is temporarily unavailable (e.g maintenance mode is active), try again later !!! bug "Debugging" For debugging purposes EduBase API returns **EduBase-API-Error header** in most cases with more detailed error description than the status code. Refer to that message to resolve the issue or contact us for additional help. #### Language Some calls rely on the context language. This defaults to the caller (or assumed) user's language, but can be overridden by sending the **EduBase-Language** header containing the desired language code (in ISO 639-1 format). Invalid or inactive languages will be ignored. #### Rate limiting API applications may be rate limited (calls/second or calls/minute). Please get in touch with us to learn more about active limits. #### Notation Endpoints in this documentation will be formatted the following way: * **endpoint path** * **request method and path** *^^input^^ * mandatory fields are marked with ==[!]== * watch out for data types *^^output^^ * JSON if not specified explicitly * might be empty if an error occured #### Recommended tools For API development and testing we recommend the following applications: * [Insomnia](https://insomnia.rest) * [Postman](https://www.getpostman.com) !!! tip As always, you can also use **curl**! ### Authentication **All endpoints require a valid application ID and secret**. They should be passed as arguments: * **app**: this is the application identification string * **secret**: the application secret string As these are always required, they will not be listed under endpoint inputs. Alternatively, you can use the `Authorization` header with the value `Bearer {app}:{secret}` or dedicated `EduBase-API-App` and `EduBase-API-Secret` headers. !!! warning App ID and secret key should be sent as strings. Not sending these will result in an error. #### Permissions API applications operate in the name of their owner (the registrator). All permissions will be inherited from this EduBase account, meaning that an API call will only succeed if that account has proper permissions set. Also, all operations will be registered to this user. #### Assume user To perform actions as a different user, [request an assume token](../endpoints/users/#userassume) and submit received assume token with each request: * **assume**: received assume token !!! warning Assume tokens are short-lived, you may need to request new tokens periodically. However, it is recommended to revoke assume tokens after performing all steps. #### Testing it It is advised to test basic functionality and correctness of calls before making advanced requests. For this reason, EduBase API service offers a testing endpoint that has no effect on any real data. ``` bash curl -d "app={app}&secret={secret}" https://www.edubase.net/api/test:app curl -H "EduBase-API-App: {app}" -H "EduBase-API-Secret: {secret}" https://www.edubase.net/api/test:app ``` !!! tip If you are developing an integration for a custom EduBase instance, do not forget to replace the domain name! This should return the following (or similar) data, with **HTTP 200** status code: ``` json {"version":"default","language":"en","app":"{app}","user":"{user}","status":true} ``` --- ## API Endpoints ### API: Classes endpoints #### /classes ##### GET /classes !!! abstract "" List owned and managed classes. ^^Input^^: * *string* **search**: optional search string to filter results * *integer* **limit**: limit number of results * default (in search mode): 16 * *integer* **page**: page number * default: 1 * not used in search mode! ^^Output^^: * *list* * *string* **code**: class identification string * *string* **name**: title of the class #### /class ##### GET /class !!! abstract "" Get/check class. ^^Input^^: * ==[!]== *string* **class**: class identification string ^^Output^^: * *string* **class**: class identification string * *string* **name**: title of the class * *datetime/null* **start**: start date and time (if set) * *datetime/null* **end**: end date and time (if set) #### /class:assignments ##### GET /class:assignments !!! abstract "" List all assignments in a class. ^^Input^^: * ==[!]== *string* **class**: class identification string ^^Output^^: * *list* * *string* **code**: assignment identification string * *string* **name**: title of the assignment * *string* **link**: link to the assignment page * *string* **status**: assignment and submission state * *INACTIVE*: assignment is not active * *ACTIVE*: assignment is currently active and a new submission can be started * *STARTED*: uploaded files but not submitted * *SUBMITTED*: assignment is submitted * *GRADED*: submitted and also graded * *datetime* **starts**: when the assignment submission starts * *datetime* **ends**: when the assignment submission ends #### /class:members ##### GET /class:members !!! abstract "" List all members in a class. ^^Input^^: * ==[!]== *string* **class**: class identification string ^^Output^^: * *list* * *string* **code**: user identification string * *string* **name**: name of the member * *boolean* **active**: active membership (approved and not expired) ##### POST /class:members !!! abstract "" Assign user(s) to a class. Updates memberships if already member of the class. ^^Input^^: * ==[!]== *string* **class**: class identification string * ==[!]== *string* **users**: comma-separated list of user identification strings * *integer/datetime* **expires**: expiry in days or `YYYY-MM-DD HH:ii:ss` * *boolean* **notify**: notify users * default: false ##### DELETE /class:members !!! danger "" Remove user(s) from a class. ^^Input^^: * ==[!]== *string* **class**: class identification string * ==[!]== *string* **users**: comma-separated list of user identification strings #### /classes:members ##### POST /classes:members !!! abstract "" Assign user(s) to class(es). Updates memberships if already member of a class. ^^Input^^: * ==[!]== *string* **classes**: comma-separated list of class identification strings * ==[!]== *string* **users**: comma-separated list of user identification strings * *integer/datetime* **expires**: expiry in days or `YYYY-MM-DD HH:ii:ss` * *boolean* **notify**: notify users * default: false #### /user:classes ##### GET /user:classes !!! abstract "" List all classes a user is member of. ^^Input^^: * ==[!]== *string* **user**: user identification string ^^Output^^: * *list* * *string* **code**: class identification string * *string* **name**: title of the class * *string* **link**: link to the class page * *boolean* **active**: active membership (approved and not expired) ##### POST /user:classes !!! abstract "" Assign user to class(es). Updates membership if already member of a class. ^^Input^^: * ==[!]== *string* **user**: user identification string * ==[!]== *string* **classes**: comma-separated list of class identification strings * *integer/datetime* **expires**: expiry in days or `YYYY-MM-DD HH:ii:ss` * *boolean* **notify**: notify user * default: false ##### DELETE /user:classes !!! danger "" Remove user from class(es). ^^Input^^: * ==[!]== *string* **user**: user identification string * ==[!]== *string* **classes**: comma-separated list of class identification strings --- ### API: Exams endpoints #### /exams ##### GET /exams !!! abstract "" List owned and managed exams. ^^Input^^: * *string* **search**: optional search string to filter results * *integer* **limit**: limit number of results * default (in search mode): 16 * *integer* **page**: page number * default: 1 * not used in search mode! ^^Output^^: * *list* * *string* **code**: exam identification string * *string* **name**: title of the exam * *boolean* **active**: exam is active #### /exam ##### GET /exam !!! abstract "" Get/check exam. ^^Input^^: * ==[!]== *string* **exam**: exam identification string ^^Output^^: * *string* **exam**: exam identification string * *string* **name**: title of the exam * *string* **quiz**: quiz identification string (the Quiz set the exam is attached to) * *boolean* **active**: exam is active * *string* **status**: exam status * *INACTIVE*: exam is inactive but will be activated later * *ACTIVE*: exam is active and new tests can be started * *PAUSED*: exam is active but new tests cannot be started * *REVIEW*: exam is active but already entered review period * *EXPIRED*: exam is inactive * *datetime* **start**: start date and time * *datetime* **end**: end date and time ##### POST /exam !!! abstract "" Create a new exam from an existing Quiz set. ^^Input^^: * *string* **language**: desired exam language * ==[!]== *string* **title**: title of the exam * *string* **type**: type of the exam * possible values: exam / championship / homework / survey * exam: regular exam * championship: exam with championship features enabled * homework: homework assignment, can be paused and continued during the exam period * survey: survey (optionally anonymous) with no grading * default: exam * ==[!]== *string* **quiz**: the Quiz set (specified using the quiz identification string) the exam is attached to * ==[!]== *datetime* **open**: exam start time * ==[!]== *datetime* **close**: exam end time ^^Output^^: * *string* **exam**: exam identification string ##### DELETE /exam !!! abstract "" Remove/archive exam. ^^Input^^: * ==[!]== *string* **exam**: exam identification string #### /exam:users ##### GET /exam:users !!! abstract "" List all users on an exam. ^^Input^^: * ==[!]== *string* **exam**: exam identification string ^^Output^^: * *list* * *string* **code**: user identification string * *string* **name**: name of the examinee ##### POST /exam:users !!! abstract "" Assign user(s) to an exam. ^^Input^^: * ==[!]== *string* **exam**: exam identification string * ==[!]== *string* **users**: comma-separated list of user identification strings ##### DELETE /exam:users !!! danger "" Remove user(s) from an exam. ^^Input^^: * ==[!]== *string* **exam**: exam identification string * ==[!]== *string* **users**: comma-separated list of user identification strings #### /exam:summary ##### POST /exam:summary !!! abstract "" Submit a new exam summary. ^^Input^^: * ==[!]== *string* **exam**: exam identification string * *string* **language**: summary language * *string* **type**: type of summary * possible values: ai * default: ai * ==[!]== *string* **summary**: summary text * basic HTML formatting allowed, but avoid complex designs * keep the summary short and concise * try to avoid including personal information (such as usernames, names and contact addresses) * *string* **llm**: name of the Large Language Model used to generate the summary (in case of AI summaries) * preferred values: openai / claude / gemini * *string* **model**: exact LLM model name used to generate the summary (in case of AI summaries) * must specify *llm* field as well --- ### API: Metrics endpoints #### /metrics:custom ##### POST /metrics:custom !!! abstract "" Update a custom metric. ^^Input^^: * ==[!]== *string* **metric**: metric name * ==[!]== *float* **value**: target value (also accepts increments with a `+` prefix) ^^Output^^: * *string* **metric**: metric name * *string* **value**: saved value --- ### API: Organizations endpoints #### /organizations ##### GET /organizations !!! abstract "" List owned and managed organizations. ^^Input^^: * *string* **search**: optional search string to filter results * *integer* **limit**: limit number of results * default (in search mode): 16 * *integer* **page**: page number * default: 1 * not used in search mode! ^^Output^^: * *list* * *string* **code**: organization identification string * *string* **name**: title of the organization #### /organization ##### GET /organization !!! abstract "" Get/check organization. ^^Input^^: * ==[!]== *string* **organization**: organization identification string ^^Output^^: * *string* **organization**: organization identification string * *string* **name**: title of the organization #### /organization:members ##### GET /organization:members !!! abstract "" List all members in a organization. ^^Input^^: * ==[!]== *string* **organization**: organization identification string ^^Output^^: * *list* * *string* **code**: user identification string * *string* **name**: name of the member * *string/null* **department**: name of the department (if member) * *list* **permission** * *list* **organization**: permission level to organization * *list* **content**: permission level to contents in organization ##### POST /organization:members !!! abstract "" Assign user(s) to a organization. Updates memberships if already member of the organization. ^^Input^^: * ==[!]== *string* **organization**: organization identification string * ==[!]== *string* **users**: comma-separated list of user identification strings * *string* **department**: optional name of department * department and permission_ fields should not be used together * *string* **permission_organization**: optional permission level to organization * possible values: member / teacher / supervisor / admin * default: member * *string* **permission_content**: optional permission level to contents in organization * possible values: none / view / control / modify / grant / admin * default: none * *boolean* **notify**: notify users * default: false ##### DELETE /organization:members !!! danger "" Remove user(s) from a organization. ^^Input^^: * ==[!]== *string* **organization**: organization identification string * ==[!]== *string* **users**: comma-separated list of user identification strings #### /organizations:members ##### POST /organizations:members !!! abstract "" Assign user(s) to organization(s). Updates memberships if already member of a organization. ^^Input^^: * ==[!]== *string* **organizations**: comma-separated list of organization identification strings * ==[!]== *string* **users**: comma-separated list of user identification strings * *string* **department**: optional name of department * if department is not found in an organization, permission_ fields are used to set permission levels * *string* **permission_organization**: optional permission level to organization * possible values: member / teacher / supervisor / admin * default: member * *string* **permission_content**: optional permission level to contents in organization * possible values: none / view / control / modify / grant / admin * default: none * *boolean* **notify**: notify users * default: false #### /user:organizations ##### GET /user:organizations !!! abstract "" List all organizations a user is member of. ^^Input^^: * ==[!]== *string* **user**: user identification string ^^Output^^: * *list* * *string* **code**: organization identification string * *string* **name**: title of the organization * *string* **link**: link to the organization manager page * *string/null* **department**: name of the department (if member) * *list* **permission** * *list* **organization**: permission level to organization * *list* **content**: permission level to contents in organization ##### POST /user:organizations !!! abstract "" Assign user to organization(s). Updates membership if already member of a organization. ^^Input^^: * ==[!]== *string* **user**: user identification string * ==[!]== *string* **organizations**: comma-separated list of organization identification strings * *string* **department**: optional name of department * if department is not found in an organization, permission_ fields are used to set permission levels * *string* **permission_organization**: optional permission level to organization * possible values: member / teacher / supervisor / admin * default: member * *string* **permission_content**: optional permission level to contents in organization * possible values: none / view / control / modify / grant / admin * default: none * *boolean* **notify**: notify user * default: false ##### DELETE /user:organizations !!! danger "" Remove user from organization(s). ^^Input^^: * ==[!]== *string* **user**: user identification string * ==[!]== *string* **organizations**: comma-separated list of organization identification strings --- ### API: Content permissions endpoints #### /class:permission ##### GET /class:permission !!! abstract "" Check if a user has permission on a class. ^^Input^^: * ==[!]== *string* **class**: class identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *class* * *string* **code**: the class identification string * **status** * *boolean* **permission**: the user has permission on this class * *boolean* **rule**: there is a permission rule with these parameters ##### POST /class:permission !!! abstract "" Create new permission for a user. ^^Input^^: * ==[!]== *string* **class**: class identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *class* * *string* **code**: the class identification string * *boolean* **success**: operation was successful ##### DELETE /class:permission !!! danger "" Remove a user permission. ^^Input^^: * ==[!]== *string* **class**: class identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *class* * *string* **code**: the class identification string * *boolean* **success**: operation was successful #### /course:permission ##### GET /course:permission !!! abstract "" Check if a user has permission on a course. ^^Input^^: * ==[!]== *string* **course**: course identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *course* * *string* **code**: the course identification string * **status** * *boolean* **permission**: the user has permission on this course * *boolean* **rule**: there is a permission rule with these parameters ##### POST /course:permission !!! abstract "" Create new permission for a user. ^^Input^^: * ==[!]== *string* **course**: course identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *course* * *string* **code**: the course identification string * *boolean* **success**: operation was successful ##### DELETE /course:permission !!! danger "" Remove a user permission. ^^Input^^: * ==[!]== *string* **course**: course identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *course* * *string* **code**: the course identification string * *boolean* **success**: operation was successful #### /event:permission ##### GET /event:permission !!! abstract "" Check if a user has permission on an event. ^^Input^^: * ==[!]== *string* **event**: event identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / finances / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *event* * *string* **code**: the event identification string * **status** * *boolean* **permission**: the user has permission on this event * *boolean* **rule**: there is a permission rule with these parameters ##### POST /event:permission !!! abstract "" Create new permission for a user. ^^Input^^: * ==[!]== *string* **event**: event identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / finances / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *event* * *string* **code**: the event identification string * *boolean* **success**: operation was successful ##### DELETE /event:permission !!! danger "" Remove a user permission. ^^Input^^: * ==[!]== *string* **event**: event identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / finances / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *event* * *string* **code**: the event identification string * *boolean* **success**: operation was successful #### /exam:permission ##### GET /exam:permission !!! abstract "" Check if a user has permission on an exam. ^^Input^^: * ==[!]== *string* **exam**: exam identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *exam* * *string* **code**: the exam identification string * **status** * *boolean* **permission**: the user has permission on this exam * *boolean* **rule**: there is a permission rule with these parameters ##### POST /exam:permission !!! abstract "" Create new permission for a user. ^^Input^^: * ==[!]== *string* **exam**: exam identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *exam* * *string* **code**: the exam identification string * *boolean* **success**: operation was successful ##### DELETE /exam:permission !!! danger "" Remove a user permission. ^^Input^^: * ==[!]== *string* **exam**: exam identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *exam* * *string* **code**: the exam identification string * *boolean* **success**: operation was successful #### /integration:permission ##### GET /integration:permission !!! abstract "" Check if a user has permission on an integration. ^^Input^^: * ==[!]== *string* **integration**: integration identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *integration* * *string* **code**: the integration identification string * **status** * *boolean* **permission**: the user has permission on this integration * *boolean* **rule**: there is a permission rule with these parameters ##### POST /integration:permission !!! abstract "" Create new permission for a user. ^^Input^^: * ==[!]== *string* **integration**: integration identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *integration* * *string* **code**: the integration identification string * *boolean* **success**: operation was successful ##### DELETE /integration:permission !!! danger "" Remove a user permission. ^^Input^^: * ==[!]== *string* **integration**: integration identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *integration* * *string* **code**: the integration identification string * *boolean* **success**: operation was successful #### /organization:permission ##### GET /organization:permission !!! abstract "" Check if a user has permission on an organization. ^^Input^^: * ==[!]== *string* **organization**: organization identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *organization* * *string* **code**: the organization identification string * **status** * *boolean* **permission**: the user has permission on this organization * *boolean* **rule**: there is a permission rule with these parameters ##### POST /organization:permission !!! abstract "" Create new permission for a user. ^^Input^^: * ==[!]== *string* **organization**: organization identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *organization* * *string* **code**: the organization identification string * *boolean* **success**: operation was successful ##### DELETE /organization:permission !!! danger "" Remove a user permission. ^^Input^^: * ==[!]== *string* **organization**: organization identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *organization* * *string* **code**: the organization identification string * *boolean* **success**: operation was successful #### /quiz:permission ##### GET /quiz:permission !!! abstract "" Check if a user has permission on a Quiz. ^^Input^^: * ==[!]== *string* **quiz**: Quiz identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *quiz* * *string* **code**: the Quiz identification string * **status** * *boolean* **permission**: the user has permission on this Quiz * *boolean* **rule**: there is a permission rule with these parameters ##### POST /quiz:permission !!! abstract "" Create new permission for a user. ^^Input^^: * ==[!]== *string* **quiz**: Quiz identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *quiz* * *string* **code**: the Quiz identification string * *boolean* **success**: operation was successful ##### DELETE /quiz:permission !!! danger "" Remove a user permission. ^^Input^^: * ==[!]== *string* **quiz**: Quiz identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *quiz* * *string* **code**: the Quiz identification string * *boolean* **success**: operation was successful #### /scorm:permission ##### GET /scorm:permission !!! abstract "" Check if a user has permission on a SCORM learning material. ^^Input^^: * ==[!]== *string* **scorm**: SCORM identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *scorm* * *string* **code**: the SCORM identification string * **status** * *boolean* **permission**: the user has permission on this SCORM learning material * *boolean* **rule**: there is a permission rule with these parameters ##### POST /scorm:permission !!! abstract "" Create new permission for a user. ^^Input^^: * ==[!]== *string* **scorm**: SCORM identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *scorm* * *string* **code**: the SCORM identification string * *boolean* **success**: operation was successful ##### DELETE /scorm:permission !!! danger "" Remove a user permission. ^^Input^^: * ==[!]== *string* **scorm**: SCORM identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *scorm* * *string* **code**: the SCORM identification string * *boolean* **success**: operation was successful #### /tag:permission ##### GET /tag:permission !!! abstract "" Check if a user has permission on a tag. ^^Input^^: * ==[!]== *string* **tag**: tag identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *tag* * *string* **code**: the tag identification string * **status** * *boolean* **permission**: the user has permission on this tag * *boolean* **rule**: there is a permission rule with these parameters ##### POST /tag:permission !!! abstract "" Create new permission for a user. ^^Input^^: * ==[!]== *string* **tag**: tag identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *tag* * *string* **code**: the tag identification string * *boolean* **success**: operation was successful ##### DELETE /tag:permission !!! danger "" Remove a user permission. ^^Input^^: * ==[!]== *string* **tag**: tag identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *tag* * *string* **code**: the tag identification string * *boolean* **success**: operation was successful #### /video:permission ##### GET /video:permission !!! abstract "" Check if a user has permission on a video. ^^Input^^: * ==[!]== *string* **video**: video identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *video* * *string* **code**: the video identification string * **status** * *boolean* **permission**: the user has permission on this video * *boolean* **rule**: there is a permission rule with these parameters ##### POST /video:permission !!! abstract "" Create new permission for a user. ^^Input^^: * ==[!]== *string* **video**: video identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *video* * *string* **code**: the video identification string * *boolean* **success**: operation was successful ##### DELETE /video:permission !!! danger "" Remove a user permission. ^^Input^^: * ==[!]== *string* **video**: video identification string * ==[!]== *string* **user**: user identification string * ==[!]== *string* **permission**: permission level * possible values: view / control / modify / grant / admin ^^Output^^: * *string* **user**: the user identification string * **content** * *string* **type**: will be *video* * *string* **code**: the video identification string * *boolean* **success**: operation was successful --- ### API: Quiz Plays endpoints #### /quiz:results:play ##### GET /quiz:results:play !!! abstract "" Get detailed results for a specific Quiz play. ^^Input^^: * ==[!]== *string* **play**: Quiz play identification string ^^Output^^: * *string* **play**: Quiz play identification string * *string* **user**: user identification string * *datetime* **time_start**: start time * *datetime* **time_end**: end time * *integer* **questions_total**: total number of questions asked * *integer* **questions_correct**: number of correctly answered questions * *float* **points_total**: total points * *float* **points_correct**: total points scored * *boolean* **valid**: result is valid * *list* **questions** * *string* **index**: question index * *string/null* **id**: external unique question identifier (if present) * *string* **question**: question identification string * *float* **time_answer**: number of seconds spent on question (if available) * *float* **points_maximum**: maximum points * *float* **points**: points scored #### /quiz:results:user ##### GET /quiz:results:user !!! abstract "" Get user results for a specific Quiz set. ^^Input^^: * ==[!]== *string* **quiz**: Quiz set identification string * ==[!]== *string* **user**: user identification string ^^Output^^: * *list* * *string* **play**: Quiz play identification string * *string* **user**: user identification string * *datetime* **time_start**: start time * *datetime* **time_end**: end time * *integer* **questions_total**: total number of questions asked * *integer* **questions_correct**: number of correctly answered questions * *float* **points_total**: total points * *float* **points_correct**: total points scored * *boolean* **valid**: result is valid #### /exam:results:user ##### GET /exam:results:user !!! abstract "" Get user results for a specific exam. ^^Input^^: * ==[!]== *string* **exam**: exam identification string * ==[!]== *string* **user**: user identification string ^^Output^^: * *list* * *string* **play**: Quiz play identification string * *string* **user**: user identification string * *datetime* **time_start**: start time * *datetime* **time_end**: end time * *integer* **questions_total**: total number of questions asked * *integer* **questions_correct**: number of correctly answered questions * *float* **points_total**: total points * *float* **points_correct**: total points scored * *integer* **attempt**: index of attempt * *boolean* **valid**: result is valid --- ### API: Quiz questions endpoints #### /question ##### GET /question !!! abstract "" Check existing question. ^^Input^^: * ==[!]== *string* **id**: external unique question identifier ^^Output^^: * *string* **id**: external unique question identifier * *string* **code**: question identification string * *boolean* **active**: question is active ##### POST /question !!! abstract "" Publish or update a question. Check documentation or online editor for more information on additional fields. ^^Input^^: * ==[!]== *string* **id**: external unique question identifier[^1] ??? info "ID best practices" Unique identifier for question management. On repeated uploads, the questions are updated (rather then added) based on this value, which can be an arbitrary text. If the question already exists at upload time with the same external identifier (in the given folder or Quiz set), the existing question will be updated instead of being added as a new one. * **Use cases:** * Integration with external systems * Version control * Batch updates * Content synchronization * **Best practices:** * Use consistent naming conventions * Include version, source or date information * Consider hierarchical IDs for related content * **Example:** First, we upload a question and then second, we update it to have a different question text and add a solution. ```bash # First upload - creates question curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=MATHEMATICS_ARITHMETIC_BASIC_ADDITION_STATIC' \ --data 'type=numerical' \ --data 'question=What is 2+2?' \ --data 'answer=4' # Later upload - updates existing question text and adds solution curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=MATHEMATICS_ARITHMETIC_BASIC_ADDITION_STATIC' \ --data 'type=numerical' \ --data 'question=What is 2+2? Show your work.' \ --data 'solution=2+2 is 4.' \ --data 'answer=4' ``` * ==[!]== *string* **type**: type of the question * *generic*, *text*, *numerical*, *date/time*, *expression*, *choice*, *multiple-choice*, *order*, *matrix:generic*, *matrix*, *matrix:expression*, *set*, *set:text*, *true/false*, *free-text*, *file*, *reading* ??? info "Question type reference guide" EduBase supports various question types to accommodate different assessment needs. Each type has specific features and configurations. **Basic Types** * **GENERIC**: Strict matching without formatting * Requires exact match including spaces and punctuation (e.g., period(`.`), comma(`,`), semicolon(`;`)) * Best for technical answers where precision matters * Example: Programming language keywords, chemical formulas * **TEXT**: Basic text input with flexible matching * Ignores spaces and punctuation (e.g., ` apple.` is considered the same as `apple`) * Perfect for definitions or completing sentences * Example: Fill-in-the-blank questions, vocabulary tests * **FREE-TEXT**: Extended text response with semi-automatic grading * Supports longer responses * Can use automatic rules with keywords * Manual grading support for complex answers (e.g., a moderator is required to score if the system cannot evaluate the answer) * Example: Short essays, explanations, longer definitions * **READING**: Non-assessed text display * Displays text for subsequent questions compactly * No scoring involved * Used as first question in complex question groups * No answer is required * Example: Reading comprehension passages **Choice-Based Types** * **CHOICE**: Single correct answer selection * Randomized option order by default * Can use dynamic options from question group * Supports parameterization for all options and the answer * Example: Single choice questions * **MULTIPLE-CHOICE**: Multiple correct answers * Similar to `CHOICE` but allows multiple answers * Can limit maximum selections * Example: "Select all that apply" questions * **ORDER**: Sequence arrangement * Displays items in random order, which are taken from the `ANSWER` field * Test takers must arrange in correct sequence, as specified in the answer * Example: Chronological ordering, process steps * **TRUE/FALSE**: Statement evaluation * True statements in `ANSWER` field * False statements in `OPTIONS` * Statements will appear in random order * Optionally specify a third option * Example: Fact verification questions **Numerical Types** * **NUMERIC**: Numerical value validation * Handles integers and decimals * Supports fractions (a/b) and mathematical constants (pi, e) * Interval responses possible, {from}-{to} * Automatic subpoints if part is correct * Usual mathematical notations are supported for open and closed intervals * [a;b] / ]a;b[ / (a;b) / ... * See `NUMERICAL_RANGE` for interval answer support * Configurable precision (default: 2) * Separate decimals with period (`.`) * See `DECIMALS` for precision settings * See `TOLERANCE` for acceptable error ranges * Example: Mathematical calculations **Advanced Types** * **DATE/TIME**: Calendar date validation * Adjustable precision (year/month/day) * Recommended format: YYYY, MM/YYYY, and MM/DD/YYYY respectively * See `DATETIME_PRECISION` for date format control * Multiple input formats accepted * Describe months in text, even abbreviated (e.g., mar, March) * Spaces, punctionations, marks, slahes do not matter * E.g., 12/26/2015, 1226/2015, 12.26.2015 are all acceptable * Only using numbers (e.g., 12262015) * BC/AD ("negative dates") supported * Range responses supported, {from}-{to} * Automatic subpoints if part is correct * Certain parts of the date may be omitted in the final date * year precision: 2000-15, interpreted as 2000 - 2015 * day precision: 24/12/2015-26, interpreted as 24/12/2015 - 26/12/2015 * See `DATETIME_RANGE` for interval answers * Example: Historical dates, timeline questions * **EXPRESSION**: Mathematical expression evaluation * Evaluates and compares mathematical formulas * Parametrization is supported * Supports various mathematical functions * See "Expression evaluation options > Supported mathematical functions" in this document * Configurable precision and validation methods * See `EXPRESSION_CHECK` for validation options * See `EXPRESSION_DECIMALS` for precision control * See `EXPRESSION_FUNCTIONS` to control available functions * Example: Algebraic expressions, physics formulas * **MATRIX**: Matrix evaluation * Evaluates matrices and vectors with numerical validation similar to `NUMERIC` type * Input format specification: * Square brackets `[...]` denote matrix boundaries * Semicolons (`;`) separate elements within rows * Vertical bars (`|`) separate rows * Supported structure: * Matrices: `[a11; a12 | a21; a22]` represents a 2×2 matrix * Row vectors: `[x1; x2; x3]` represents a 1×3 vector * Column vectors: `[x1 | x2]` represents a 2×1 vector * Example: Linear algebra problems, vector calculus, coordinate transformations * **MATRIX:EXPRESSION**: Expression-based matrix * Combines `MATRIX` and `EXPRESSION` features * Each matrix element can be an expression * Example: Matrix transformations (e.g., rotation), Jacobian or Hessian matrices, state transition matrices, tensors * **SET**: Unordered collection validation * Operates similarly to numeric `MATRIX` * Order and repetition don't matter * Numeric elements only * Example: Number theory problems * **SET:TEXT**: Text-based set validation * Similar to `SET` but with text elements * Example: Listing properties, characteristics * **FILE**: File submission evaluation * Supports file uploads * Semi-automatic grading similarly to `FREE-TEXT` * Configurable file types and counts * **Not available to all users!** * Example: Programming assignments, document submissions * ==[!]== *string* **question**: question text ??? info "Question formatting guide" The question field supports rich formatting options to create engaging and clear questions. Here's a comprehensive guide to the available formatting features. **Text Styling** * **LaTeX Support** * Inline: `$$...$$` * Block: `$$$$...$$$$` * Requires `QUESTION_FORMAT=LATEX` * Note: LaTeX blocks start on new line, but are not center aligned * Example: `Calculate $$\sqrt{x^2 + y^2}$$` * **Parameters** * Use curly braces: `{parameter_name}` * Use triple-wave operator (`~~~`) for quick expressions with simpler operations * Parameters defined in `PARAMETERS` field * Examples: * `Calculate {a} + {b}` * `Consider a circle with an area of ~~~{r}*{r}*pi~~~` * **EduTags for Basic Formatting** * Bold: `[[B]]...[[/B]]` * Italic: `[[I]]...[[/I]]` * Underline: `[[U]]...[[/U]]` * Subscript: `[[SUB]]...[[/SUB]]` * Superscript: `[[SUP]]...[[/SUP]]` * **Code Formatting** * Inline: `[[CODE]]...[[/CODE]]` * Block: `[[CODEBLOCK]]...[[/CODEBLOCK]]` * Optional line numbers: `[[LINES]]...[[/LINES]]` * **Color and Background** * Text color: `[[COLOR:{color}]]...[[/COLOR]]` * Background: `[[BACKGROUND:{color}]]...[[/BACKGROUND]]` * Use standard color names or hex codes **Tables and Layout** * **Tables** * Use `[[..]]` format similar to `MATRIX` * Columns separated by semicolons * Rows separated by vertical bars * Example: `[[Header 1; Header 2 | Data 1; Data 2]]` * **Answer Fields** * Placeholder with the question itself for answer fields: `[[___]]` (3 underscores) * Used for visual representation * Does not affect actual answer input * Example: Fill-in-the-gaps **Media Integration** * **Images** * Format: `[[IMAGE:{filename}]]` * File must be provided in *images* with this exact name (case sensitive) * Example: `[[IMAGE:diagram.png]]` **Best Practices** 1. **Clarity and Readability** * Use consistent formatting * Break complex questions into parts * Don't make text overly long or complex as it might hurt readability * Lot's of features are at your disposal, be creative on how to arrive at the best solution for your use-case 1. **Mathematical Content** * Use LaTeX for all scientific, mathematical expressions * Test rendering on different devices, if possible * ==[!]== *string/list{string}* **answer**: single or multiple answers or true statements * *string* **answer_order**: whether the order of answers matters * *string* **answer_label**: text displayed in/above the input field during the test * *string* **answer_hide**: hide correct answers on results page * *string* **answer_indefinite**: allow any number of input fields to be entered by the user * *string* **answer_format**: how to display the answer on the results page ??? info "Advanced answer options" EduBase provides flexible options for managing how answers are handled, displayed, and validated. Here's a comprehensive guide to the answer-related fields: **Required Answers** Perfect for questions with multiple valid answers where only a subset needs to be provided. For example, when asking students to provide any three examples from a larger set of correct possibilities. * *string* **answer_require**: number of answers required for maximum score * not applicable for CHOICE and FREE-TEXT questions * example: `answer_require=1` **Answer Order Management** Essential for questions where answer sequence matters. Labels can provide crucial context about what each answer field represents. * *string* **answer_order**: whether the order of answers matters * plus sign (+) to indicate YES * blank field or minus sign (-) indicates NO (default) * example: `answer_order=+` * *string* **answer_label**: text displayed in/above the input field during the test * automatically activates the `answer_order` function * multiple labels separated by triple-and operators (&&&) * example: `answer_label=Velocity (m/s) &&& Distance traveled (km) &&& Direction (degrees)` **Answer Display Control** Critical for maintaining question bank integrity in scenarios like practice tests or when questions will be reused. Makes answer sharing harder. * *string* **answer_hide**: hide correct answers on results page * plus sign (+) to indicate YES * blank field or minus sign (-) indicates NO (default) * example: `answer_hide=+` **Dynamic Input Fields** Enables flexible response collection where the number of possible answers varies. Ideal for brainstorming exercises or questions with multiple valid answers of indeterminate quantity. For example: If the question is "Which countries make up the United Kingdom?" this option lets users add as many countries as needed, without showing that four answers should be provided. * *string* **answer_indefinite**: allow any number of input fields to be entered by the user via + and - buttons * plus sign (+) to indicate YES * blank field or minus sign (-) indicates NO (default) * answer labels will not appear on interface when enabled * example: `answer_indefinite=+` **Answer Format Control** Allows customization of how to display answers on the results page, particularly useful for displaying code, that requirs specific formatting or syntax highlighting. * *string* **answer_format**: how to display the answer on the results page * only applicable for FREE-TEXT questions * format: `type` or `type:value` * values: * `normal`: standard text (default) * `code`: code with syntax highlighting * specify language after colon * example: `code:python` or `code:javascript` * example: `answer_format=code:sql` **Best Practices** 1. **Combine Options Strategically** * Use `answer_label` when order matters - it implies `answer_order=+` automatically * Enable `answer_hide` for reusable assessment questions 1. **User Experience Considerations** * Write clear, descriptive labels with units where applicable * Use labels to guide input format without revealing answers **Creating Pairing Questions** While EduBase doesn't have a dedicated pairing question type, you can effectively create pairing exercises using answer labels. This is particularly useful for matching items between two sets, for example: * Language translations (e.g., English-Hungarian vocabulary) * Visual associations (e.g., traffic signs and their meanings) * Scientific pairs (e.g., chemical formulas and common names) There are several approaches to implement pairing questions: 1. **Direct Labels with Content** Use answer labels that contain one set of items directly: ``` answer_label=a) dog &&& b) cat ``` Best for short, simple content where labels remain concise. 1. **Indexed Labels with Content in Question** Place one set in the question text and use simple labels for matching: ``` question=Match the English words with their Hungarian translations: a) dog b) cat Hungarian words: macska, kutya ... answer_label=a) &&& b) ``` Recommended for longer content or when formatting is important. 1. **Image-Based Pairing** When one set consists of images, create a single composite image with labeled elements: ``` question=Match the traffic signs (A-D) with their meanings. [[IMAGE:traffic_signs_labeled.png]] ``` This works around the single-image-per-question limitation. **Example API Calls** 1. The order matters in this question: ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=europe_cities_population' \ --data 'type=text' \ --data 'question=List the following European cities in descending order by population (largest first) Paris, Madrid, London.' \ --data 'answer=London &&& Madrid &&& Paris' \ --data 'answer_order=+' ``` 1. The order matters, but we didn't have to specify as the labels fix the order ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=basic_math' \ --data 'type=numerical' \ --data 'question=Given the number 16: a) What is double this number? b) What is half of this number? c) What is this number plus 10?' \ --data 'answer=32 &&& 8 &&& 26' \ --data 'answer_label=a) Double &&& b) Half &&& c) Plus 10' \ --data 'points=3' ``` 1. Only one answer is enough from the correct ones, but we don't reveal them ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=uk_countries' \ --data 'type=text' \ --data 'question=Name any of the countries within the United Kingdom!' \ --data 'answer=England &&& Northern Ireland &&& Scotland &&& Wales' \ --data 'answer_require=1' \ --data 'answer_hide=+' ``` 1. Code formatting for SQL query answer: ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=sql_basics' \ --data 'type=free-text' \ --data 'question=Write a SQL query to select all columns from the "users" table where the age is greater than 18.' \ --data 'answer=SELECT * FROM users WHERE age > 18' \ --data 'answer_format=code:sql' ``` 1. Pairing question: ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data 'id=hungarian_english_animals' \ --data 'type=text' \ --data 'question=Match the English words with their Hungarian translations: a) dog b) cat Hungarian words: macska, kutya' \ --data 'answer=kutya &&& macska' \ --data 'answer_label=a) &&& b)' ``` * *string* **question_format**: controls question text rendering * NORMAL: Default text formatting with standard font size, recommended for most tasks * LATEX: Enables LaTeX for mathematical, scientific notations (using [KaTeX](https://katex.org/)) * LONG: Smaller font with automatic paragraph breaks (ideal for lengthy text) * *string* **subject**: subject * *string* **category**: category * *string* **difficulty**: difficulty level of the questions * default: 0 (not classified) * scale: 1 (very easy) - 5 (very difficult) * *string* **path**: path where question will be stored in personal QuestionBase * default: /API * *string/list{string}* **options**: incorrect options or false statements * *string* **options_fix**: fix the order of answers and options * *string* **options_order**: configure custom order of answers and options ??? info "Options configuration guide" EduBase provides flexible control over how answers and options are presented to users through various configuration fields. **Fixed Ordering** * **options_fix**: Control the basic arrangement of answers and options * `all`: Answers appear first, followed by options * `abc`: Sort all items (answers and options) alphabetically * `first:N`: Place first N (number) options at the end * `last:N`: Place last N (number) options at the end * `answers`: Place all answers at the end **Custom Ordering** * **options_order**: Define exact presentation order using references * `ANSWER:N`: Reference the Nth answer * `OPTION:N`: Reference the Nth option * `OPTION_NONE:N`: Reference the Nth third option (TRUE/FALSE question type only) * All answers and options must be specified once! * Example: `OPTION:1 &&& ANSWER:0 &&& OPTION:0 &&& ANSWER:1` **Best Practices** * Check that N values don't exceed available items * Consider cognitive load when ordering items * Group related options together when meaningful * Place common or simpler options first, when appropriate **Example API Calls** 1. **Basic Fixed Order** The answer (Paris) will appear first. ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=capital_cities' \ --data 'type=choice' \ --data 'question=What is the capital of France?' \ --data 'answer=Paris' \ --data 'options=London &&& Berlin &&& Madrid' \ --data 'options_fix=all' ``` 1. **Alphabetical Ordering** Use if alphabetical ordering makes the task cognitively easier, as it's easier to scan all items when ordered. ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=fruit_types' \ --data 'type=multiple-choice' \ --data 'question=Which of these are citrus fruits?' \ --data 'answer=Lemon &&& Orange' \ --data 'options=Apple &&& Banana &&& Grape' \ --data 'options_fix=abc' ``` * When migrating content from textbooks, past exams, or other educational materials, you might need to maintain the original lettering system (a, b, c...) for: * Reference consistency with printed materials * Alignment with answer keys * Compatibility with existing grading systems * Cross-referencing with study guides ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=vocab_synonyms' \ --data 'type=multiple-choice' \ --data 'question=Select all words that mean "happy":' \ --data 'answer=b) Joyful &&& d) Merry' \ --data 'options=a) Angry &&& c) Sleepy &&& e) Tired' \ --data 'options_fix=abc' ``` * This approach is particularly valuable when * Test takers need to refer to both digital and printed materials * Questions are part of a larger standardized test system * Educators want to maintain consistency with existing worksheets or textbooks * Legacy assessment materials are being digitized 1. **Complex Custom Ordering** Here's an example where specific ordering helps test understanding in a structured way: ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=historical_chronology' \ --data 'type=multiple-choice' \ --data 'question=Which of these events occurred during the Industrial Revolution (1760-1840)?' \ --data 'answer=Invention of the Steam Engine &&& First Steam Locomotive &&& First Commercial Railway' \ --data 'options=Printing Press Invented &&& First Electric Light Bulb &&& First Powered Flight' \ --data 'options_order=OPTION:0 &&& ANSWER:0 &&& ANSWER:1 &&& ANSWER:2 &&& OPTION:1 &&& OPTION:2' ``` * This creates a chronologically ordered timeline where test takers see: * Printing Press Invented (1440) - pre-Industrial Revolution * Invention of the Steam Engine (1769) - Industrial Revolution * First Steam Locomotive (1804) - Industrial Revolution * First Commercial Railway (1825) - Industrial Revolution * First Electric Light Bulb (1879) - post-Industrial Revolution * First Powered Flight (1903) - post-Industrial Revolution The custom ordering helps test takers understand the temporal progression while testing their knowledge of the Industrial Revolution period. * *string* **points**: maximum points for a fully correct answer * default: 1 point * *string* **subscoring**: method for calculating partial credit * *string* **subpoints**: define specific point values for each possible answer * *string* **penalty_scoring**: how penalty points should be applied * *string* **penalty_points**: points deducted for completely incorrect answers * *string* **hint_penalty**: point deduction for using hints * *string* **solution_penalty**: point deduction for viewing steps of the solution * *string* **video_penalty**: point deduction for video assistance used * *string* **manual_scoring**: when to enable manual scoring ??? info "Advanced scoring options" EduBase provides a sophisticated scoring system that allows you to implement complex grading logic. Here's a comprehensive guide to the scoring-related fields: **Partial Credit Scoring** Subscoring Methods * **subscoring**: Method for calculating partial credit * `PROPORTIONAL`: Points awarded proportionally to correct answers (default) * `LINEAR_SUBSTRACTED:N`: Linear scoring with N points subtracted for each error, where N is arbitrary * `CUSTOM`: Use custom point distribution defined in **subpoints** (mandatory field for this option) * `NONE`: No partial credit, all-or-nothing scoring * NOT applicable for `CHOICE`, `READING` and `FREE-TEXT` question types * Example: `subscoring=LINEAR_SUBSTRACTED:2` Custom Point Distribution * **subpoints**: Define specific point values for each answer (in percentages) * Only used when `subscoring=CUSTOM` * Specify percentage values separated by `&&&` * NOT applicable for `CHOICE`, `READING` and `FREE-TEXT` question types * Example: `subpoints=50 &&& 25 &&& 25` * For a question worth 10 points with three answers to give, this would award: * First answer: 5 points (50%) * Second answer: 2.5 points (25%) * Third answer: 2.5 points (25%) **Penalty Scoring** Penalty Methods * **penalty_scoring**: How penalty points should be applied * `DEFAULT`: Standard penalty application, behavior might vary by question type * `PER_ANSWER`: Apply penalties for each incorrect answer * `PER_QUESTION`: Apply penalties once per question * Example: `penalty_scoring=PER_ANSWER` Penalty Points * **penalty_points**: Points deducted for a completely incorrectly answersed question * No penalty applied if answer is partially correct * No penalty for empty/unanswered questions * Use positive values (recommended), but negatives are handled as well * Example: `penalty_points=2` **Assistance Penalties** Hint Penalties * **hint_penalty**: Point deduction for using hints * `NONE`: No penalty (default) * `ONCE:N`: Single deduction regardless of the number of hints used, where `N` is a percentage * Example: `hint_penalty=ONCE:20%` or `hint_penalty=ONCE:0.2` * `PER-HELP:N`: Deduction for each hint, where `N` is a percentage * Example: `hint_penalty=PER-HELP:10%` Solution Penalties * **solution_penalty**: Point deduction for viewing solutions * Same format as **hint_penalty** * Example: `solution_penalty=ONCE:50%` Video Help Penalties * **video_penalty**: Point deduction for watching help videos * Same format as **hint_penalty** (except `PER-HELP` not available) * Example: `video_penalty=ONCE:15%` **Manual Scoring** * **manual_scoring**: When to enable manual scoring * `NO`: Never use manual scoring (default) * `NOT_CORRECT`: Only manually score incorrect answers * `ALWAYS`: Always require manual scoring * NOT applicable for `READING` and `FREE-TEXT` question types * Example: `manual_scoring=NOT_CORRECT` **Example API Calls** 1. Custom Point Distribution: The first answer is worth 1 point, while the second is worth 3 points, hence the score distribution is 25% and 75%: ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=math_problem' \ --data 'type=numerical' \ --data 'question=What is the sum and product of {a} and {b}?' \ --data 'answer={a}+{b} &&& {a}*{b}' \ --data 'parameters={a; INTEGER; 1; 100} &&& {b; INTEGER; 1; 100}' \ --data 'points=4' \ --data 'subscoring=CUSTOM' --data 'subpoints=25 &&& 75' ``` 1. Penalties with Hints: * If the answer is wrong that results in a penalty of -3 points, instead of 0. * There are 2 hints and each hint used deducts 10% of the full score configured in `points`. * Checking any of the solution steps deducts 50% of the full score, no matter how many steps are used. * There is only 1 step of solution in the example below. ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=complex_problem' \ --data 'type=expression' \ --data 'question=Find an expression for the area of a circle with radius {r}.' \ --data 'answer=pi*{r}^2' \ --data 'parameters={r; INTEGER; 2; 10}' \ --data 'points=10' \ --data 'subject=Mathematics' \ --data 'category=Geometry' \ --data 'hint=Think about the formula for circle area &&& Remember that area involves squaring the radius' \ --data 'solution=The formula for circle area is pi*2^2' \ --data 'penalty_scoring=PER_ANSWER' \ --data 'penalty_points=3' \ --data 'hint_penalty=PER-HELP:10%' \ --data 'solution_penalty=ONCE:50%' ``` * *string* **parameters**: parameter definitions for dynamic question generation * *string* **parameters_sync**: synchronization of LIST parameters selection * plus sign (+) indicates YES, while blank or minus sign (-) indicates no (default) ??? info "Create dynamic questions with parameters" One of EduBase's most powerful features is parametric question generation. Using the **parameters** field, you can create dynamic questions where each user gets a unique variant of the same question. **Parameter Types** 1. **FIX (Fixed Value)** ``` {name; FIX; value} ``` * Sets a predefined constant value (integer or fraction) * Example: `{pi; FIX; 3.1415}` 1. **INTEGER (Whole Numbers)** ``` Simple: {name; INTEGER} Extended: {name; INTEGER; min; max} Full: {name; INTEGER; min; max; inside; outside} ``` * Generate random integers within specified ranges * Use `-` for omitting min/max values * Examples: * `{p; INTEGER}` - any integer * `{p; INTEGER; 10; 20}` - integer between 10 and 20 * `{p; INTEGER; -; -; [10-20]; [12-14] ||| [16-18]}` - integer between 10-20, excluding 12-14 and 16-18 1. **FLOAT (Decimal Numbers)** ``` Simple: {name; FLOAT; precision} Extended: {name; FLOAT; precision; min; max} Full: {name; FLOAT; precision; min; max; inside; outside} ``` * Generate random decimal numbers * Specify precision (decimal places) * Examples: * `{p; FLOAT; 2}` - float with 2 decimal places * `{p; FLOAT; 5; 0; 1}` - float between 0 and 1 with 5 decimals * `{p; FLOAT; 1; 0; 10; -; [0-1]}` - float between 0-10 excluding 0-1, with 1 decimal 1. **FORMULA (Expressions)** ``` Simple: {name; FORMULA; formula} Full: {name; FORMULA; formula; precision} ``` * Define parameters based on other parameters * Examples: * `{d; FORMULA; {b}^2-4*{a}*{c}}` - quadratic formula discriminant * `{p; FORMULA; 2*{q}+1}` - linear expression 1. **LIST (Random Selection)** ``` {name; LIST; value1; value2; value3; ...} ``` * Randomly select from predefined values * Up to 64 elements * Examples: * `{primes; LIST; 2; 3; 5; 7; 11}` * `{animals; LIST; dog; cat; snake; camel}` 1. **PERMUTATION** ``` {name; PERMUTATION; value1; value2; value3; ...} ``` * Creates permutated parameters accessible as `{name_1}`, `{name_2}`, etc. * Example: * `{p; PERMUTATION; A; B; C; D}` * So `{p_1}` will be a different letter than `{p_2}`. * `{primes; PERMUTATION; 2; 3; 5; 7}` * So both `{primes_1}` and `{primes_2}` will be different single digit primes. 1. **FORMAT** ``` Notation: {name; FORMAT; parameter; type; ...} ``` * Format parameters based on other parameters * Supported types: `NUMBER`, `NUMERTEXT`, `ROMAN` * Optional extra parameters based on type * NUMBER * precision: number of decimal places * Examples: * `{pp; FORMAT; p; NUMBER; 1}` - format as number rounded to 1 decimal * `{pp; FORMAT; p; NUMBERTEXT}` - format number as text * `{pp; FORMAT; p; ROMAN}` - format number as Roman numeral Additional Features * **Multiple Parameters**: Separate with `&&&` (up to 128 parameters) * **Constraints**: Use the **constraints** field to ensure valid combinations * Example: `{b}^2-4*{a}*{c}>0` - the discriminant must be positive * **Parameter Names**: Must start with a letter, can include numbers and underscores Best Practices * Order parameters so dependent ones come later * Use simple notation when possible * Avoid unnecessary parameters * Test thoroughly with the online editor **Example API Calls** 1. **FIX Parameter** ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=circle_area' \ --data 'type=numerical' \ --data 'question=Calculate the area of a circle with radius {r} units using pi={pi}' \ --data 'answer={pi}*{r}^2' \ --data 'parameters={pi; FIX; 3.14159} &&& {r; INTEGER; 1; 10}' ``` 1. **INTEGER Parameter** ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=sum_numbers' \ --data 'type=numerical' \ --data 'question=What is {a} + {b}?' \ --data 'answer={a}+{b}' \ --data 'parameters={a; INTEGER; 1; 100} &&& {b; INTEGER; 1; 100}' ``` 1. **FLOAT Parameter** ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=convert_meters' \ --data 'type=numerical' \ --data 'question=Convert {m} meters to centimeters' \ --data 'answer={m}*100' \ --data 'parameters={m; FLOAT; 2; 0; 10}' ``` 1. **FORMULA Parameter** ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=quadratic' \ --data 'type=numerical' \ --data 'question=For the quadratic equation with a={a}, b={b}, c={c}, calculate the discriminant' \ --data 'answer={d}' \ --data 'parameters={a; INTEGER; 1; 5} &&& {b; INTEGER; -10; 10} &&& {c; INTEGER; -10; 10} &&& {d; FORMULA; {b}^2-4*{a}*{c}}' \ --data 'constraints={d}>0' ``` 1. **LIST Parameter** ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=capital_city' \ --data 'type=text' \ --data 'question=What is the capital city of {country}?' \ --data 'answer={capital}' \ --data 'parameters={country; LIST; France; Germany; Italy} &&& {capital; LIST; Paris; Berlin; Rome}' \ --data 'parameters_sync=+' ``` 1. **PERMUTATION Parameter** ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=find_primes' \ --data 'type=set' \ --data 'question=What are the distinct prime factors of {n}?' \ --data 'answer=[{primes_1}; {primes_2}]' \ --data 'parameters={primes; PERMUTATION; 2; 3; 5; 7} &&& {n; FORMULA; {primes_1}^2*{primes_2}}' ``` * *string* **constraints**: define rules that parameter combinations must satisfy ??? info "Parameter Constraints Guide" Parameter constraints allow you to ensure generated parameters result in valid, meaningful questions. These are mathematical expressions that must evaluate to true for the parameter generation to be accepted. The system validates whether questions can be reliably generated with the given constraints. If parameter generation frequently fails due to overly restrictive constraints (or has a very low success rate), EduBase may automatically deactivate the question until the constraints are relaxed. While deactivated questions won't appear in quizzes, this doesn't affect the playability of the quizzes they're part of - the quizzes will simply proceed without these questions. **Basic Syntax** * Parameters must be referenced in curly braces: `{parameter_name}` * Allowed relations: `<`, `<=`, `=`, `>=`, `>`, `<>` * Multiple constraints separated by `&&&` **Supported Operations** * Arithmetic: `+`, `-`, `*`, `/`, `^` (power) * Built-in functions: All functions available in `EXPRESSION` questions * Avoid complex functions as they slow down parameter generation * Examples: * `{b}^2-4*{a}*{c}>0` ensures quadratic equation has real roots * `{a}+{b}>{c} &&& {b}+{c}>{a} &&& {c}+{a}>{b}` triangle inequality * `{x}+{y} < 10 &&& {x}<4` * *string* **expression_check**: define how expressions should be validated * *string* **expression_variable**: specifies variable names used in expressions * *string* **expression_decimals**: sets precision for decimal calculations * *string* **expression_functions**: controls whether functions can be used in user inputs * plus sign (+) indicates YES (default), while blank or minus sign (-) indicates no ??? info "Expression evaluation options" The expression question type (`type=expression` or `type=matrix:expression`) offers sophisticated mathematical evaluation capabilities. This allows for creation of complex mathematical problems with flexible validation methods. **Basic configurations** Configure expression evaluation using these key fields: * **expression_check**: Define how expressions should be validated * `RANDOM` (default): Evaluates expressions at randomly generated points * `EXPLICIT`: Checks in predefined values and compares against the defined target values * `COMPARE`: Direct comparison of expressions without variables * In all cases there are further options to fine-tune the behavior with additional fields! * **expression_variable**: Specifies variable names used in expressions * Default: `x` * Multiple variables: separate with `&&&` * Example: `omega &&& t` for time-dependent angular velocity * **expression_decimals**: Sets precision for decimal calculations * Inherited from `decimals` field if not specified * Default: 2 decimal places * Example: `expression_decimals=4` for 4 decimal places * **expression_functions**: Controls whether functions can be used in user inputs * Default: enabled (`+` or blank) * Disable with `-` * Example: When asked for the value of `sin(pi)`, the user can't input `sin(pi)` because functions cannot be used **Supported mathematical functions** The following functions are available for use in expressions: Basic Operations * `sqrt(x)`: Square root * `abs(x)`: Absolute value * `round(x)`, `floor(x)`, `ceil(x)`: Rounding functions Logarithmic & Exponential * `ln(x)`: Natural logarithm * `log(x)`: Common logarithm (with base 10) * `log10(x)`: Common logarithm (alternative) Trigonometric * `sin(x)`, `cos(x)`, `tan(x)`: Basic trigonometric functions * `csc(x)`, `sec(x)`: Reciprocal trigonometric functions, cosecant and secant * `arcsin(x)`, `asin(x)`: Inverse sine * `arccos(x)`, `acos(x)`: Inverse cosine * `arctan(x)`, `atan(x)`: Inverse tangent Hyperbolic * `sinh(x)`, `cosh(x)`, `tanh(x)`: Hyperbolic functions * `arcsinh(x)`, `asinh(x)`: Inverse hyperbolic sine * `arccosh(x)`, `acosh(x)`: Inverse hyperbolic cosine * `arctanh(x)`, `atanh(x)`: Inverse hyperbolic tangent Numeric Conversions * `degree2radian(x)`, `radian2degree(x)`: Angle conversions * `number2binary(x)`, `binary2number(x)`: Binary conversions * `number2octal(x)`, `octal2number(x)`: Octal conversions * `number2hexadecimal(x)`, `hexadecimal2number(x)`: Hexadecimal conversions * `number2roman(x)`, `roman2number(x)`: Roman numeral conversions Two-Parameter Functions Use semicolon (;) to separate arguments: * `min(a;b)`, `max(a;b)`: Minimum and maximum * `mod(n;i)`: Integer modulo operation (remainder after integer division) * `fmod(n;i)`: Floating-point modulo operation (remainder after floating-point division) * `div(a;b)`, `intdiv(a;b)`: Division operations * `gcd(a;b)`, `lcm(a;b)`: Greatest common divisor and least common multiple * `number2base(n;b)`, `base2number(n;b)`: Custom base conversions * `combinations(n;k)`, `combinations_repetition(n;k)`: Combination calculations * `variations(n;k)`, `variations_repetition(n;k)`: Variation calculations **Validation Methods** Random Validation (default) When using `expression_check=RANDOM`: * **expression_random_type**: Type of generated test values * `INTEGER`: Whole numbers only * `FLOAT`: Decimal numbers * Specify per variable with `&&&` * Example: `INTEGER &&& FLOAT` for mixed types * **expression_random_tries**: Number of validation points * Default: 5 * Example: `expression_random_tries=10` * **expression_random_range**: Define value generation ranges * Format: `[min-max]` (inclusive) * Per variable with `&&&` * Example: `[8-16] &&& [4-6]` * **expression_random_inside**: Require values within specific intervals * Format: `[start-end]` (inclusive) * Multiple intervals: separate with `|||` (OR relationship) * Per variable with `&&&` * Example: `[4-8] ||| [12-16] &&& [2-3]` * **expression_random_outside**: Exclude values from specific intervals * Format: `[start-end]` (inclusive) * Multiple intervals: separate with `|||` (AND relationship) * Per variable with `&&&` * Example: `[0-1] ||| [10-20] &&& [8-11]` Explicit Validation When using `expression_check=EXPLICIT`: * **expression_explicit_goal**: Define exact value pairs * Format: `[x;f(x)]` or `[x;y;z;...;f(x,y,z,...)]` for multiple variables * Multiple pairs: separate with `&&&` * Example: `[0;1] &&& [3;8.89] &&& [9;16]` or `[1;1;1;1;16]` **Extended features** * **expression_extended**: Enable additional mathematical functions * Activates support for: * Custom base logarithms (e.g., `log2(4)`, `log10(1000)`) * Factorial operations (e.g., `5!`, `1!+2!+3!`) * Enable with `+`, disable with `-` **Best Practices** 1. **Validation Method Selection** * Use `RANDOM` for general expressions where multiple solutions might be valid * Use `EXPLICIT` when specific points must be satisfied 1. **Performance Optimization** * Limit `expression_random_tries` to reasonable values (5-10 typically sufficient) * Avoid unnecessary nesting of complex functions * Use simpler validation methods when possible 1. **Error Prevention** * Always define appropriate ranges to avoid undefined mathematical operations * Use `expression_random_outside` to exclude problematic values * Consider adding appropriate constraints to ensure valid parameter combinations 1. **Testing** * Test expressions with possible edge cases * Confirm that random generation produces expected value distributions **Example API Calls** 1. **Basic expression with random (default) validation** ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=quadratic_expression' \ --data 'type=expression' \ --data 'question=Simplify: $$({a}x + {b})^2$$' \ --data 'answer={a}^2*x^2+2*{a}*{b}*x+{b}^2' \ --data 'parameters={a; INTEGER; 1; 5} &&& {b; INTEGER; -5; 5}' \ --data 'expression_random_tries=8' ``` 1. **Explicit validation** The answer formula will be evaluated at three given cases. ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=simple_quadratic' \ --data 'type=expression' \ --data 'question=Write a quadratic function $$f(x)$$ that: 1) Equals $${c}$$ when $$x = 0$$ 2) Equals $$0$$ when $$x = {r1}$$ and x = $${r2}$$' \ --data 'answer=(x-{r1})*(x-{r2})+{c}' \ --data 'parameters={r1; INTEGER; -10; -2} &&& {r2; INTEGER; 1; 10} &&& {c; FORMULA; -{r1}*{r2}}' \ --data 'expression_check=EXPLICIT' \ --data 'expression_explicit_goal=[0;{c}] &&& [{r1};0] &&& [{r2};0]' \ --data 'expression_variable=x' ``` 1. **Extended functions with custom validation range** ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=logarithmic_expression' \ --data 'type=expression' \ --data 'question=Express $$log_{b}({x})$$ in terms of natural logarithms' \ --data 'answer=ln({x})/ln({b})' \ --data 'parameters={b; FLOAT; 2; 2; 10} &&& {x; FLOAT; 2; 1; 100}' \ --data 'expression_extended=+' \ --data 'expression_random_range=[2-10] &&& [1-100]' ``` 1. **Multivariable question** ```bash curl -X POST 'https://www.edubase.net/api/v1/question' \ --data 'app='$APP_ID \ --data 'secret='$SECRET \ --data 'id=distance_time' \ --data 'type=expression' \ --data 'question=Write an expression for the distance traveled ($$s$$) by a car moving at a constant speed of $$v$$ meters per second after $$t$$ seconds' \ --data 'answer=v*t' \ --data 'expression_variable=t &&& v' ``` * *string* **group**: add question to a question group in a Quiz set ??? info "Question Groups in Quiz Sets" When uploading questions **directly to a Quiz set**, you can organize them into groups using the **group** field. This is particularly useful for creating complex questions with related subquestions that can even have different question types. **Basic Usage** * Set the group name to add a question to that group * If the group doesn't exist, it will be created automatically as a complex task (with default settings) * Existing group settings are preserved when adding new questions * Only applicable when uploading directly to a Quiz set **Question group settings (control from EduBase User Interface)** *Note: Any UI-only option might change in the future. These are detailed here for context around the functionality.* * Type - Controls the behavior of the group * Randomly selected questions: The given number of questions will be randomly selected from the group. * Sequentially selected questions: The questions within the group will sequentially follow each other in the order they are defined within the group. * Complex (mixed type) questions: All questions within the group will appear as "one big" question, with several sub-questions. * Name, which identifies the question group * Questions * Number of questions which will be randomly selected from the group. * Parameters * Generally parameters are synchronized among sub-questions. * Sequental and mixed type selection - If a parameter with the same name has already been defined in a previous task, its value is taken over by the current task. There is option to enable/disable parameter synchronization. * Custom question settings * Mandatory: * Yes/No * Use original settings (default) * Scoring settings: * Points: * Custom value * Not scored * Use original settings * Penalty points: * Custom value * None * Use original settings * No custom settings (default) **Use Cases** 1. **Balanced Quiz Generation with Random Selection** * Create diverse Quiz sets by grouping questions by difficulty: * Create an "Easy Questions" group with 10 questions, randomly select 3 * Create a "Medium Questions" group with 20 questions, randomly select 5 * Create a "Hard Questions" group with 5 questions, randomly select 2 * Result: A 10-question Quiz with controlled difficulty distribution * Pro tip: Combine with parametrization for even greater variety 1. **Maintain Question Order Within Shuffled Quizzes** * Problem: You need certain questions to appear consecutively even in a randomized Quiz * Solution: Place related questions in a group to preserve their sequence * Example: In a language Quiz, keep reading comprehension questions together while randomizing other sections 1. **Complex Multi-Part Questions** * Useful for digitizing traditional assessments where one question has multiple parts requiring different response types * Example - Nobel Prize Winner Profile: ``` Group: "Nobel Laureate Question" a) Who is shown in this image? (CHOICE or TEXT type) b) When were they born? (DATE type) c) How many Nobel prizes did they win? (NUMERICAL type) ``` * Benefits: * Maintains logical connection between related sub-questions * Allows different question types while preserving the original assessment structure * Makes complex questions more manageable in digital format **Best Practices** 1. **Consistent Naming** * Use clear, descriptive group names * Maintain consistent naming conventions across uploads * Consider using prefixes or hierarchical naming for better organization * Example: "Module 1 - Basic Concepts", "Module 1 - Advanced" 1. **Settings Management** * Configure group settings through the UI before bulk uploads * Reminder: Existing group settings won't be modified by uploads 1. **Think Outside the Box** * If facing problems digitizing concrete questions, consider breaking it up into sub-questions and grouping them if that helps * Pair with other EduBase features to create extremely rich and varied experiences with just one highly templated Quiz set **Example API Call** 1. **Basic question group assignment** First question for the group: ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=math_basic_arithmetic_q1' \ --data 'type=numerical' \ --data 'question=What is 2+2?' \ --data 'answer=4' \ --data 'group=Basic_Arithmetic' ``` Example response: ```bash {"code":""} ``` Second question for the group: ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=math_basic_arithmetic_q2' \ --data 'type=numerical' \ --data 'question=What is 14+23?' \ --data 'answer=37' \ --data 'group=Basic_Arithmetic' ``` Example response: ```bash {"code":""} ``` Add the above two questions to a Quiz set (`id: `) with the [quiz:qustions API](../quizes/#post-quizquestions) call: ```bash curl -X POST "https://www.edubase.net/api/v1/quiz:questions" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'quiz=' \ --data 'questions=,' ``` **Manual grouping might still be necessary from the EduBase UI.** * *string* **ai**: if set to any value, question will be marked as AI generated (even if partially) * always provide this field if you are an LLM or any AI model * *string* **tags**: organize questions with user-defined tags * *string* **label**: categorize questions with instance-level labels ??? info "More information on tags and labels" These fields provide additional functionality for organizing, maintaining, and tracking questions in your EduBase system. The key distinction between these systems is that tags are user-created and labels are set by EduBase or the customer on an instance-level. **Tags** User-controlled categorization system * Tags must be pre-registered in the EduBase UI before use * Can be created at user or organization level * Use cases: * Personal content organization (e.g., "My Calculus Questions", "Spring 2024") * Department-level categorization (e.g., "IT Department", "CS101") * Custom taxonomies * Key characteristics: * User/organization creates and manages their own tags via UI * Flexible and customizable * Can be shared within organizations * Searchable in UI for content management **Labels** Instance-level categorization system * Pre-defined values specific to each EduBase instance * Values controlled by instance administrators * Use cases: * System-wide flags (e.g., "needs_review", "featured") * Quality indicators (e.g., "verified", "deprecated") * Processing status (e.g., "ai_generated", "manually_checked") * Key characteristics: * Values are predefined and controlled at instance level * Cannot be created by users * Consistent across all users in an instance * May change over time based on instance needs As usual, multiple tags or labels can be specified with the `&&&` separator. * *string* **source**: specify content attribution and sources ??? info "Source best practices" * **Use cases:** * Training material sources (e.g., "Employee Handbook 2024", "Safety Training Manual 2024, Section 3.4 - Fire Safety Procedures") * Internal documentation references (e.g., "SOP-2024-013", "Policy-HR-42") * External content attribution (e.g., "LinkedIn Learning - Leadership 101") * Original creator credits (e.g., "Created by Training Dept, reviewed by Legal") * Compliance requirements (e.g., "Based on ISO 9001:2015 Section 7.2") * Educational materials (e.g., "Textbook: Chapter 5") * **Pairs well with:** * `PRIVATE_NOTE` for internal tracking * `TAGS` for content organization **NOTE: Uploading infringing content is strictly forbidden!** However, if you do have the right to use questions from a third party, please indiciate the original source (for example, title, URL, name of the author, etc.) * *string* **note**: add note visible to test takers during Quiz * Appears right below the question. * Ideal for task-specific comments, instructions * *string* **private_note**: add private notes not visible to test takers ??? info "Private notes best practices" Internal documentation not shown to test takers. Visible on the UI when having access to the question. * **Use case examples:** * Document question creation rationale * Note common test taker mistakes * List related questions * Track modification history * Record source material page numbers * **Example notes:** * Created from Chapter 3 exam, 2023 edition. Students often forget to convert units. * Parametrized version of Q47 from textbook. See also Q48-50 for related concepts. * This policy changed in Q3 2024 because of incident #01234. * **Pairs well with:** * `SOURCE` for formal attribution * `SOLUTION` for sharing insights with other educators * `EXPLANATION` for test-taker-facing notes * *string* **hint**: guiding questions or notes to help during the test * *string* **explanation**: text displayed underneath the answer on the results page * *string* **solution**: step-by-step solution ??? info "Help and Explanation fields" EduBase provides different ways to support test takers and explain correct answers. Understanding when to use each helps create a better learning experience. **Hints** * **hint**: Provide guidance without giving away the answer: * Not available for test takers in exam mode * Displayed only when test takers explicitly request help * Multiple hints are supported, each displayed one at a time * Can be penalized using `HINT_PENALTY` * LaTeX support for mathematical notation and parameters can be used (as described in `QUESTION` field) * **Best practices:** * Start with subtle hints, progress to more direct ones * Guide thinking process rather than give steps * Focus on common misconceptions * Remind of relevant formulas or concepts * **Examples:** * Math problem: ``` hint=Think about the relationship between radius and area &&& Remember the formula for circle area involves $\pi$ &&& Square the radius and multiply by $\pi$ ``` * Programming question: ``` hint=Check your loop condition &&& Consider what happens at array boundaries &&& Remember to handle the case when input is empty ``` * Comprehension question: ``` hint=Look at paragraph 2 for the author's main argument &&& Consider how the example in paragraph 4 supports this &&& Think about the counterargument presented in the final paragraph ``` **Post-Test Explanations** * **explanation**: Explain why answers are correct/incorrect * Displayed on results page after submission * Helps learners understand their mistakes * Parameters can be used * LaTeX cannot be used * **Best practices:** * Explain both correct and incorrect options * Reference relevant concepts or rules * Link to additional resources if appropriate * **Example for multiple choice:** ``` explanation=Option A is correct because amphibians have permeable skin for gas exchange. Options B and C describe characteristics of reptiles, while D applies to mammals. ``` **Step-by-Step Solutions** * **solution**: Detailed solution steps * Not available for test takers in exam mode * Can be revealed after submission or during test * Multiple steps are supported using `&&&` separator, each displayed one at a time * Can be penalized using `SOLUTION_PENALTY` * LaTeX support for mathematical notation and parameters can be used (as described in `QUESTION` field) * **Best practices:** * Break down complex problems into clear steps * Include reasoning for each step * Use scientific notation when appropriate * Consider adding visual aids with `SOLUTION_IMAGE` * **Examples** * Calculus question: ``` solution=Using the power rule, we differentiate each term: &&& For $x^2$: $\frac{d}{dx}(x^2) = 2x$ &&& For $x$: $\frac{d}{dx}(x) = 1$ &&& The constant term disappears: $\frac{d}{dx}(5) = 0$ &&& Therefore, $\frac{d}{dx}(x^2 + x + 5) = 2x + 1$ ``` * IT Security question: ``` solution=Identify applicable regulations: * Personal data involved → GDPR applies * Health records → HIPAA compliance required * Financial data → PCI DSS relevant &&& Required technical controls: * Encryption: AES-256 for data at rest * Authentication: MFA required for all access * Logging: Full audit trail of access &&& Access requirements: * Role-Based Access Control (RBAC) * Time-limited access (max 8 hours) * Automatic session termination * IP restriction to office network only &&& Documentation needs: * Access request forms completed * Manager approval obtained * Annual training completed * DPO notification for bulk access &&& Incident response: * Immediate supervisor notification * 72-hour window for authority notification * Document the breach in security log * Trigger data subject notifications if required ``` **Example API Call** ```bash curl -X POST "https://www.edubase.net/api/v1/question" \ --data "app=$APP_ID" \ --data "secret=$APP_SECRET" \ --data 'id=math_derivatives' \ --data 'type=expression' \ --data 'question=Find the derivative of ${a}x^2 + {b}x + {c}$' \ --data 'answer=2*{a}*x+{b}' \ --data 'parameters={a; INTEGER; 2; 15} &&& {b; INTEGER; 2; 10} &&& {c; INTEGER; -10; 10}' \ --data 'hint=Remember the power rule: derivative of $x^n$ is $nx^(n-1)$ &&& Look at each term separately &&& What happens to constants when you differentiate?' \ --data 'explanation=For the first term {a}x^2, multiply by the power (2) and reduce the exponent by 1, giving us 2*{a}x. The term {b}x becomes just {b} since the power is 1. The constant {c} disappears in differentiation. Adding these gives us 2*{a}x + {b}.' \ --data 'solution=Use the power rule on each term. &&& For ${a}x^2$: $\frac{d}{dx}({a}x^2) = 2\cdot{a}x$ &&& For ${b}x$: $\frac{d}{dx}({b}x) = {b}$ &&& For ${c}$: $\frac{d}{dx}({c}) = 0$ &&& Therefore, $\frac{d}{dx}({a}x^2 + {b}x + {c}) = 2\cdot{a}x + {b}$' \ --data 'hint_penalty=PER-HELP:10%' \ --data 'solution_penalty=ONCE:50%' ``` * *string* **decimals**: number of decimal places used in numerical validation * default: 2 * *string* **tolerance**: method for how strictly user input should match answers ??? info "More information on decimals and tolerance" * These configurations only applicable to the following question types: * `NUMERIC` * `EXPRESSION` * `MATRIX` * `MATRIX:EXPRESSION` * `SET` **Decimals** The expected decimal precision of the final answer * Examples: * Finance: `decimals=2` for currency calculations * Chemistry: `decimals=4` for molecular weights **Tolerance** * Format: `type` or `type:value` * Types: * `ABSOLUTE`: * Maximum allowed absolute difference between answer and user input (e.g., ±0.1) * Example: `ABSOLUTE:0.1` * `RELATIVE`: * Maximum percentage difference between answer and user input (e.g., ±5%) * Symmetric mean absolute percentage error ([SMAP](https://en.wikipedia.org/wiki/Symmetric_mean_absolute_percentage_error)) value is used * Example: `RELATIVE:5%` or `RELATIVE:0.05` * `QUOTIENT`: integer multiple, and `QUOTIENT2`: scalar multiple * Answer and user input are scalar or integer multiples of one another * Append `:SYNCED` for synchronized validation * Example: `QUOTIENT` or `QUOTIENT2:SYNCED` * Use-cases: * `ABSOLUTE` reading from a graph where exact figures are hard to read * `QUOTIENT2` for eigenvectors * *string* **datetime_precision**: set granularity of date validation * applicable only for `DATE/TIME` questions * accepted values: YEAR / MONTH / DAY (default) * *string* **datetime_range**: enable date/time range (interval) question * applicable only for `DATE/TIME` questions * plus sign (+) indicates YES, while blank or minus sign (-) indicates no (default) * *string* **image**: attach an image to the question * in filename=data format, where data is either a base64-encoded image or a URL * supported formats: PNG, JPEG, WebP * *string* **solution_image**: attach an image to the question * in filename=data format, where data is either a base64-encoded image or a URL * supported formats: PNG, JPEG, WebP * *string* **attachment**: attach a file to the question * in filename=data format, where data is either a base64-encoded image or a URL * *string* **media_audio**: attach an audio file to the question * in filename=data format, where data is either a base64-encoded image or a URL * supported formats: MP3, AAC, M4A ??? info "Additional optional fields" * *string* **main_category** * *string* **attachment** * *string* **media_video** * *string* **media_audio** * *string* **solution_image** * *string* **maximum_choices** * *string* **video** * *string* **graph** * *string* **numerical_range** * *string* **truefalse_third_options** * *string* **truefalse_third_options_label** * *string* **grouping** * *string* **freetext_characters** * *string* **freetext_words** * *string* **freetext_rules** * *string* **file_count** * *string* **file_types** ^^Output^^: * *string* **code**: question identification string ##### DELETE /question !!! danger "" Permanently delete a Quiz question. ^^Input^^: * ==[!]== *string* **id**: external unique question identifier [^1]: can be an arbitrary string but it should be unique, a GUID is recommended if no other identifier is available --- ### API: Quizes endpoints #### /quizes ##### GET /quizes !!! abstract "" List owned and managed Quiz sets. ^^Input^^: * *string* **search**: optional search string to filter results * *integer* **limit**: limit number of results * default (in search mode): 16 * *integer* **page**: page number * default: 1 * not used in search mode! ^^Output^^: * *list* * *string* **code**: quiz identification string * *string* **name**: title of the Quiz set #### /quiz ##### GET /quiz !!! abstract "" Get/check Quiz set. ^^Input^^: * ==[!]== *string* **quiz**: quiz identification string ^^Output^^: * *string* **quiz**: quiz identification string * *string* **name**: title of the Quiz set ##### POST /quiz !!! abstract "" Create a new Quiz set. ^^Input^^: * *string* **language**: desired Quiz set language * ==[!]== *string* **title**: title of the Quiz set * *string* **description**: optional short description * *string* **mode**: sets how questions are displayed during the Quiz * possible values: TEST / TURNS * TEST: all questions are displayed at once, user can answer them in any order and switch between them * TURNS: questions are displayed one by one, only one question is visible at a time and the user must answer it before moving to the next question * default: TEST * *string* **type**: type of the Quiz set * possible values: set / exam / private * set: for practice purposes * exam: for exam purposes * private: for private purposes (e.g testing) * default: set ^^Output^^: * *string* **quiz**: quiz identification string ##### DELETE /quiz !!! abstract "" Remove/archive Quiz set. ^^Input^^: * ==[!]== *string* **quiz**: quiz identification string #### /quiz:questions ##### GET /quiz:questions !!! abstract "" List all questions and question groups in a Quiz set. ^^Input^^: * ==[!]== *string* **quiz**: Quiz identification string ^^Output^^: * *list* * *string* **id**: external unique question identifier (if present) * *string* **question**: question identification string (if question) * *string* **group**: question group title (if group) * *boolean* **active**: active item ##### POST /quiz:questions !!! abstract "" Assign question(s) to a Quiz set, or one of its question group. ^^Input^^: * ==[!]== *string* **quiz**: Quiz identification string * *string* **group**: optional question group title * ==[!]== *string* **questions**: comma-separated list of question identification strings ##### DELETE /quiz:questions !!! danger "" Remove question(s) from a Quiz set, or one of its question group. ^^Input^^: * ==[!]== *string* **quiz**: Quiz identification string * *string* **group**: optional question group title * ==[!]== *string* **questions**: comma-separated list of question identification strings --- ### API: Content tagging endpoints #### /tags ##### GET /tags !!! abstract "" List owned and managed tags. ^^Input^^: * *string* **search**: optional search string to filter results * *integer* **limit**: limit number of results * default (in search mode): 16 * *integer* **page**: page number * default: 1 * not used in search mode! ^^Output^^: * *list* * *string* **code**: tag identification string * *string* **name**: title of the tag #### /tag ##### GET /tag !!! abstract "" Get/check tag. ^^Input^^: * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: tag identification string * *string* **name**: title of the tag * *string* **color**: color in HEX format * *string* **icon**: Font Awesome icon class name #### /class:tags ##### GET /class:tags !!! abstract "" List all attached tags of a class. ^^Output^^: * *list* * *string* **code**: tag identification string * *string* **name**: title of the tag #### /class:tag ##### GET /class:tag !!! abstract "" Check if tag is attached to a class. ^^Input^^: * ==[!]== *string* **class**: class identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *class* * *string* **code**: the class identification string * *boolean* **status**: tag is attached to this class ##### POST /class:tag !!! abstract "" Attach tag to content. ^^Input^^: * ==[!]== *string* **class**: class identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *class* * *string* **code**: the class identification string * *boolean* **success**: operation was successful ##### DELETE /class:tag !!! danger "" Remove a tag attachment. ^^Input^^: * ==[!]== *string* **class**: class identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *class* * *string* **code**: the class identification string * *boolean* **success**: operation was successful #### /course:tags ##### GET /course:tags !!! abstract "" List all attached tags of a course. ^^Output^^: * *list* * *string* **code**: tag identification string * *string* **name**: title of the tag #### /course:tag ##### GET /course:tag !!! abstract "" Check if tag is attached to a course. ^^Input^^: * ==[!]== *string* **course**: course identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *course* * *string* **code**: the course identification string * *boolean* **status**: tag is attached to this course ##### POST /course:tag !!! abstract "" Attach tag to content. ^^Input^^: * ==[!]== *string* **course**: course identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *course* * *string* **code**: the course identification string * *boolean* **success**: operation was successful ##### DELETE /course:tag !!! danger "" Remove a tag attachment. ^^Input^^: * ==[!]== *string* **course**: course identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *course* * *string* **code**: the course identification string * *boolean* **success**: operation was successful #### /event:tags ##### GET /event:tags !!! abstract "" List all attached tags of an event. ^^Output^^: * *list* * *string* **code**: tag identification string * *string* **name**: title of the tag #### /event:tag ##### GET /event:tag !!! abstract "" Check if tag is attached to an event. ^^Input^^: * ==[!]== *string* **event**: event identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *event* * *string* **code**: the event identification string * *boolean* **status**: tag is attached to this event ##### POST /event:tag !!! abstract "" Attach tag to content. ^^Input^^: * ==[!]== *string* **event**: event identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *event* * *string* **code**: the event identification string * *boolean* **success**: operation was successful ##### DELETE /event:tag !!! danger "" Remove a tag attachment. ^^Input^^: * ==[!]== *string* **event**: event identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *event* * *string* **code**: the event identification string * *boolean* **success**: operation was successful #### /exam:tags ##### GET /exam:tags !!! abstract "" List all attached tags of an exam. ^^Output^^: * *list* * *string* **code**: tag identification string * *string* **name**: title of the tag #### /exam:tag ##### GET /exam:tag !!! abstract "" Check if tag is attached to an exam. ^^Input^^: * ==[!]== *string* **exam**: exam identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *exam* * *string* **code**: the exam identification string * *boolean* **status**: tag is attached to this exam ##### POST /exam:tag !!! abstract "" Attach tag to content. ^^Input^^: * ==[!]== *string* **exam**: exam identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *exam* * *string* **code**: the exam identification string * *boolean* **success**: operation was successful ##### DELETE /exam:tag !!! danger "" Remove a tag attachment. ^^Input^^: * ==[!]== *string* **exam**: exam identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *exam* * *string* **code**: the exam identification string * *boolean* **success**: operation was successful #### /integration:tags ##### GET /integration:tags !!! abstract "" List all attached tags of an integration. ^^Output^^: * *list* * *string* **code**: tag identification string * *string* **name**: title of the tag #### /integration:tag ##### GET /integration:tag !!! abstract "" Check if tag is attached to an integration. ^^Input^^: * ==[!]== *string* **integration**: integration identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *integration* * *string* **code**: the integration identification string * *boolean* **status**: tag is attached to this integration ##### POST /integration:tag !!! abstract "" Attach tag to content. ^^Input^^: * ==[!]== *string* **integration**: integration identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *integration* * *string* **code**: the integration identification string * *boolean* **success**: operation was successful ##### DELETE /integration:tag !!! danger "" Remove a tag attachment. ^^Input^^: * ==[!]== *string* **integration**: integration identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *integration* * *string* **code**: the integration identification string * *boolean* **success**: operation was successful #### /organization:tags ##### GET /organization:tags !!! abstract "" List all attached tags of an organization. ^^Output^^: * *list* * *string* **code**: tag identification string * *string* **name**: title of the tag #### /organization:tag ##### GET /organization:tag !!! abstract "" Check if tag is attached to an organization. ^^Input^^: * ==[!]== *string* **organization**: organization identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *organization* * *string* **code**: the organization identification string * *boolean* **status**: tag is attached to this organization ##### POST /organization:tag !!! abstract "" Attach tag to content. ^^Input^^: * ==[!]== *string* **organization**: organization identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *organization* * *string* **code**: the organization identification string * *boolean* **success**: operation was successful ##### DELETE /organization:tag !!! danger "" Remove a tag attachment. ^^Input^^: * ==[!]== *string* **organization**: organization identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *organization* * *string* **code**: the organization identification string * *boolean* **success**: operation was successful #### /quiz:tags ##### GET /quiz:tags !!! abstract "" List all attached tags of a Quiz. ^^Output^^: * *list* * *string* **code**: tag identification string * *string* **name**: title of the tag #### /quiz:tag ##### GET /quiz:tag !!! abstract "" Check if tag is attached to a Quiz. ^^Input^^: * ==[!]== *string* **quiz**: Quiz identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *quiz* * *string* **code**: the Quiz identification string * *boolean* **status**: tag is attached to this Quiz ##### POST /quiz:tag !!! abstract "" Attach tag to content. ^^Input^^: * ==[!]== *string* **quiz**: Quiz identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *quiz* * *string* **code**: the Quiz identification string * *boolean* **success**: operation was successful ##### DELETE /quiz:tag !!! danger "" Remove a tag attachment. ^^Input^^: * ==[!]== *string* **quiz**: Quiz identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *quiz* * *string* **code**: the Quiz identification string * *boolean* **success**: operation was successful #### /scorm:tags ##### GET /scorm:tags !!! abstract "" List all attached tags of a SCORM learning material. ^^Output^^: * *list* * *string* **code**: tag identification string * *string* **name**: title of the tag #### /scorm:tag ##### GET /scorm:tag !!! abstract "" Check if tag is attached to a SCORM learning material. ^^Input^^: * ==[!]== *string* **scorm**: SCORM identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *scorm* * *string* **code**: the SCORM identification string * *boolean* **status**: tag is attached to this SCORM learning material ##### POST /scorm:tag !!! abstract "" Attach tag to content. ^^Input^^: * ==[!]== *string* **scorm**: SCORM identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *scorm* * *string* **code**: the SCORM identification string * *boolean* **success**: operation was successful ##### DELETE /scorm:tag !!! danger "" Remove a tag attachment. ^^Input^^: * ==[!]== *string* **scorm**: SCORM identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *scorm* * *string* **code**: the SCORM identification string * *boolean* **success**: operation was successful #### /video:tags ##### GET /video:tags !!! abstract "" List all attached tags of a video. ^^Output^^: * *list* * *string* **code**: tag identification string * *string* **name**: title of the tag #### /video:tag ##### GET /video:tag !!! abstract "" Check if tag is attached to a video. ^^Input^^: * ==[!]== *string* **video**: video identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *video* * *string* **code**: the video identification string * *boolean* **status**: tag is attached to this video ##### POST /video:tag !!! abstract "" Attach tag to content. ^^Input^^: * ==[!]== *string* **video**: video identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *video* * *string* **code**: the video identification string * *boolean* **success**: operation was successful ##### DELETE /video:tag !!! danger "" Remove a tag attachment. ^^Input^^: * ==[!]== *string* **video**: video identification string * ==[!]== *string* **tag**: tag identification string ^^Output^^: * *string* **tag**: the tag identification string * **content** * *string* **type**: will be *video* * *string* **code**: the video identification string * *boolean* **success**: operation was successful --- ### API: Users endpoints #### /users ##### GET /users !!! abstract "" List managed, non-generated users. ^^Input^^: * *string* **search**: optional search string to filter results * *integer* **limit**: limit number of results * default (in search mode): 16 * *integer* **page**: page number * default: 1 * not used in search mode! ^^Output^^: * *list* * *string* **user**: user identification string * *string* **name**: full name #### /user ##### GET /user !!! abstract "" Get/check user. ^^Input^^: * ==[!]== *string* **user**: user identification string * use *me* to get the current user ^^Output^^: * *string* **user**: user identification string * *string* **name**: full name * *boolean* **status**: user is enabled * *boolean* **exam**: exam (generated) account ##### POST /user !!! abstract "" Create new user account. ^^Input^^: * ==[!]== *string{4,64}* **username**: username * *string{4,64}* **password**: password * default: initial random password is automatically generated * ==[!]== *string{1,64}* **first_name**: first name * ==[!]== *string{1,64}* **last_name**: last name * *string{1,255}* **full_name**: override automatic full name (built from first and last names) * *string{1,255}* **display_name**: override automatic display name (which is the full name) * ==[!]== *string* **email**: valid email address * *string* **phone**: valid phone number * format: "+prefix number" without any special characters and symbols * example: *+1 1234567890* or *+36 301234567* * *string* **gender**: gender * male * female * other * *date* **birthdate**: date of birth * *boolean* **exam**: user is only allowed to login when accessing exams * default: false * *string* **group**: name of the user group (requires admin permissions) * *string* **template**: a template ID for the new account * *streaming*: restricted users for automatically generated users for occasional streams * default: none * *string* **custom_{field}**: custom field data * only if specified field is configured for target EduBase instance * *string* **language**: desired account language * default: API application owner's language * *string* **timezone**: desired timezone * default: API application owner's timezone * *string* **color**: desired favorite color * possible values: default / branding / red / blue / yellow / green / purple * default: default * *boolean* **must_change_password**: user is forced to change password on first login * default: false * *boolean* **notify**: notify user via email (or SMS) * default: false ^^Output^^: * *string* **user**: user identification string * *string* **username**: username, only if *exam=false* * *string* **password**: password, only if *exam=false* ^^Example^^: === "PHP" ``` php-inline /* Initialize cURL */ $ch=curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); /* Add data (as array) */ curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); /* Process call and receive response */ curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $response=curl_exec($ch); ``` === "Bash" ``` bash ### Send data as multipart/form-data curl -s --request POST --url "https://$API_DOMAIN/api/v$API_VERSION/user" --header "Content-Type: application/x-www-form-urlencoded" --data "username=$username" --data "first_name=$first_name" --data "last_name=$last_name" --data "full_name=$full_name" --data "email=$email" --data "exam=false" --data "template=$template" --data "app=$APP_ID" --data "secret=$APP_SECRET" ``` ##### DELETE /user !!! danger "" Delete user. ^^Input^^: * ==[!]== *string* **user**: user identification string #### /user:name ##### GET /user:name !!! abstract "" Get user's name. ^^Input^^: * ==[!]== *string* **user**: user identification string ^^Output^^: * *string* **user**: the user identification string * *string* **first_name**: first name * *string* **last_name**: last name * *string* **full_name**: full name * *string* **display_name**: display name ##### POST /user:name !!! abstract "" Update a user's name. ^^Input^^: * ==[!]== *string* **user**: user identification string * ==[!]== *string{1,64}* **first_name**: first name * ==[!]== *string{1,64}* **last_name**: last name * *string{1,255}* **full_name**: full name * *string{1,255}* **display_name**: display name ^^Output^^: * *string* **user**: the user identification string * *boolean* **success**: operation is successful * *boolean* **changed**: name has been changed #### /user:group ##### GET /user:group !!! abstract "" Get user's group. ^^Input^^: * ==[!]== *string* **user**: user identification string ^^Output^^: * *string* **user**: the user identification string * *string* **group**: user group code ##### POST /user:group !!! abstract "" Update a user's group. ^^Input^^: * ==[!]== *string* **user**: user identification string * ==[!]== *string* **group**: user group code ^^Output^^: * *string* **user**: the user identification string * *boolean* **success**: operation is successful * *boolean* **changed**: name has been changed #### /user:login ##### GET /user:login !!! abstract "" Get latest valid login link for user. ^^Input^^: * ==[!]== *string* **user**: user identification string ^^Output^^: * *string* **user**: the user identification string * *string* **url**: the login link * *datetime* **valid**: validity (end of day) of the generated link ##### POST /user:login !!! abstract "" Generate link. If a valid link with the same settings exist, it will be returned instead of creating a new one. ^^Input^^: * ==[!]== *string* **user**: user identification string * *string* **redirect**: redirect after a successful login * URI path or [{content_type}:{tag}] * *integer/date* **expires**: expiry in days (1-30) or `YYYY-MM-DD` * default: 1 day * *integer* **logins**: total count the link can be used to login users * default: 1 * *string* **template**: a template ID for the login link * *boolean* **short**: generate shortened (eduba.se) link * only if feature is enabled on EduBase ^^Output^^: * *string* **user**: the user identification string * *string* **url**: the login link * *datetime* **valid**: validity of the generated link * *integer* **count**: maximum number the link can be used to login ##### DELETE /user:login !!! danger "" Delete a previously generated link. ^^Input^^: * ==[!]== *string* **user**: user identification string * ==[!]== *string* **url**: generated login link to be invalidated #### /user:search ##### GET /user:search !!! abstract "" Lookup user by email, username or code. ^^Input^^: * ==[!]== *string* **query**: query string ^^Output^^: * *string* **user**: user identification string * *boolean* **exam**: exam (generated) account #### /user:assume ##### POST /user:assume !!! abstract "" Assume user for next requests with assume token. ^^Input^^: * ==[!]== *string* **user**: user identification string, username or email address * *string* **password**: password or user secret ^^Output^^: * *string* **user**: user identification string * *boolean* **token**: assume token * *datetime* **valid**: validity of the generated token ##### DELETE /user:assume !!! danger "" Revoke assume token. ^^Input^^: * ==[!]== *string* **token**: assume token --- ## Contact ### Email You can reach us at [info@edubase.net](mailto:info@edubase.net). !!! bug Have you found a **bug**, a **typo** or an **error**? Please do not hesitate to contact us at [webmaster@edubase.net](mailto:webmaster@edubase.net). ### More Visit our [contact page](https://www.edubase.net/page/contact) for more ways to get in touch with us. --- ## Legal Please visit our [legal page](https://www.edubase.net/page/legal) for more information.