{"activeVersionTag":"latest","latestAvailableVersionTag":"latest","collection":{"info":{"_postman_id":"89a0bb0d-6e9b-402a-8982-ec3cc4376420","name":"Engageli API","description":"# Changes\n\nApplicable for current production versions:\n\n1. v3.1.57-20260521\n    \n2. v3.1.58-20260803\n    \n\n## Classes API\n\nThis documentation now covers some new API endpoints for the Classes API, available from Engageli 3.1.56.\n\n- PATCH method to update a class configuration, including adding users to the roster, or changing their roster details (role, active/inactive status etc).\n    \n- POST method to a new endpoint to delete users from a roster. Note, this is analogous to deleting a user from a class roster in the portal, and will not only remove the user's access to the classroom, but will delete all their attendance and engagement data too. If you only want to prohibit access, please use the PATCH method instead, and change their status to `inactive`.\n    \n\n## Engagement Events\n\nFrom Engageli 3.1.56 there are some additional values to be seen for type in the data returned by the Engagement Events API, relating to the new Polls, Quizzes and Sprints (aka Rallyo) features:\n\n- `pollSet` is an event type that relates to the Poll feature.\n    \n- `quizSet` is an event type that relates to the Quiz feature.\n    \n- `quizSprint` is an event type that relates to the Sprint (aka Rallyo) feature.\n    \n\nEach set contains one or more questions which when launched will result in `poll` events. The sets contain IDs that allow you to link the set to the individual `poll` events.\n\n# Using the Engageli API\n\nEngageli provides a set of robust APIs to retrieve configuration and usage data for your classes and class sessions. This data includes user and course identifiers from your LMS (if configured), eliminating the need for transforms and enabling the creation of comprehensive reports and dashboards.\n\nEngageli APIs support full or baseline data loads as well as incremental requests for recent updates, which makes them ideal for regular calls to keep a full copy of data in your data warehouse, allowing you to provide custom reports or drive business processes using Engageli data. All API endpoints are secured and accessed using standard REST API methods over HTTPS, returning JSON responses.\n\n## Configuration Variables\n\nThis collection describes the APIs available in Engageli. To use these, you will need to obtain details from your Engageli Partner Success Manager for:\n\n- API Key to store in `your_api_key`. This is a basic authentication token which is used with the `token` endpoint to retrieve a JWT token to use as a Bearer token for all other API endpoints.\n    \n- Host to store in `host`. This forms the base of your API URLs.\n    \n- Sandbox to store in `sandbox`. This is used to build the path to your API URLs and is usually the same value as the start of your Engageli hostname.\n    \n\nThe final variable in the collection is `jwt` and this is populated dynamically by the output of the **Access Token** endpoint. This is a JWT with validity of 1 hour and is used as a Bearer token to authorize all other Engageli API endpoints.\n\n## Response Status Codes\n\nSuccessful responses from the APIs will have a HTTP 200 status response.\n\nNon-successful responses from the APIs may include the following:\n\n- 400 Bad Request. Check the parameters you provided, or the body of your request. It is likely you didn't follow the rules detailed for each API below.\n    \n- 401 Unauthorized. This is typically seen if you try to use your API key instead of a fetched JWT to authenticate your request to the APIs. Or, if you use a JWT that has passed its 1 hour lifespan.\n    \n- 429 Rate Limit Exceeded. As detailed below, this is returned when you make too many API calls within any 1 minute period. You will need to pause for a minute before retrying. Try to manage the rate you send your requests out.\n    \n- 500 Internal Server Error. If you encounter this, please contact Engageli Support at [support@engageli.com](https://mailto:support@engageli.com)\n    \n- 502 Bad Gateway. This should be a temporary issue and you may wish to retry, but if the issue persists please contact Engageli Support at [support@engageli.com](https://mailto:support@engageli.com)\n    \n- 503 Service Unavailable. This may be caused by you making too many concurrent requests to an Engageli API. Otherwise, this should be a temporary issue and you may wish to retry, but if the issue persists please contact Engageli Support at [support@engageli.com](https://mailto:support@engageli.com)\n    \n\n## Rate Limits and Concurrency\n\nThe API endpoints do have concurrency and rate limits, but they have been designed in such a way as to support bulk export and pagination, meaning that for typical incremental calls you will not need to run concurrent calls to the same endpoint because the next call will require the `nextToken` pagination token from the current request. Independent requests may run concurrently, subject to the endpoint-specific and instance-wide limits below.\n\nThe APIs are highly performant and can provide the data you need quickly and reliably through the use of precompiled reports and incremental/delta parameters.\n\n1. Each product instance will support up to 60 API requests per minute across all API keys. Exceeding this count will result in a 429 status response.\n    \n2. The Event Stream endpoint supports up to 2 concurrent requests across the product instance. Exceeding this concurrency will result in a 503 status response. For the typical use case, a response is required to obtain the nextToken needed to get the next page of data, reducing the need for concurrent calls.\n    \n3. The Attendance endpoint supports up to 25 concurrent requests across the product instance. Exceeding this concurrency will result in a 503 status response. For the typical use case, concurrent use may occur where you need to re-fetch whole attendance records for classes where their attendance model has been recalculated, so be sure to design to control the concurrency of these requests.\n    \n\n## Dates and Times\n\nWhen sending datetime parameters to, or receiving datetime values from Engageli endpoints, note that all our timestamps are in UTC timezone, to millisecond accuracy. We provide timestamps as strings in the format `YYYY-MM-DDThh:mm:ss.sssZ`, e.g. `2024-07-22T12:52:33.482Z`. For best compatibility, please provide your datetime parameters as strings in any of the following formats, and we will interpret them as shown.\n\n| **Format** | **Example** | **Interpretation** |\n| --- | --- | --- |\n| `YYYY-MM-DD` | `2024-07-22` | `2024-07-22T00:00:00.000Z` |\n| `YYYY-MM-DDThh:mm:ss` | `2024-07-22T12:52:33` | `2024-07-22T12:52:33.000Z` |\n| `YYYY-MM-DDThh:mm:ss.sss` | `2024-07-22T12:52:33.482` | `2024-07-22T12:52:33.482Z` |\n| `YYYY-MM-DDThh:mm:ss.sssZ` | `2024-07-22T12:52:33.482Z` | `2024-07-22T12:52:33.482Z` |\n\n- Where a timestamp is provided for a rangeStart URL parameter, this is treated as an inclusive boundary, i.e. for timestamps equal to or greater than the parameter.\n    \n- Where a timestamp is provided for a rangeEnd URL parameter, this is treated as an exclusive boundary, i.e. for timestamps less than the parameter.\n    \n\n## Pagination\n\nEngageli APIs that return large quantities of data will use a cursor-based pagination approach. If more data is available that can be included in a response, the response will include a root-level field called `nextToken` and its value should be passed as a URL parameter on an additional API call **with all other parameters unchanged**. `nextToken` will be absent on API responses where there is no additional page of data to return.\n\nThe `nextToken` value instructs the Engageli API to carry on sending data from the point at which the previous page stopped, so it's vital all the other parameters (e.g. rangeStart) are unchanged. The token does not expire, but because it is typically used in pulling of incremental data, it makes sense to use it immediately to finish the retrieval of data.\n\nBecause this is a cursor based pagination method, the results are not pre-cached and the Engageli API will pick up results from that point onwards, as they exist when the subsequent API call is made. If an item that was due to be on the next page is deleted before the next page is requested, then it will not appear in the next page's data.\n\n| **API** | **Maximum Response Page Size** |\n| --- | --- |\n| Live Session Reports (engagements/live) | 20 objects in the data array |\n| Playback Session Reports (engagements/playback) | 500 objects in the data array |\n| Lectures | 5,000 objects in the data array |\n| Attendance | 2,000 objects in the data array |\n| Engagement Events | 100,000 objects in the data array |\n| Classes | 1,000 objects in the data array |\n\nNote, for multi-stack implementations, the APIs will paginate after returning one sub-stack's data. e.g. with 3 sub-stacks you will get at least three pages of data in a response, and the pages will not necessarily reach the maximum limits shown above. Where there are more results for a single sub-stack than can be returned in one page, you will receive that sub-stack's data across more than one page, and then the API will page again to continue with the next sub-stack's data. If you just follow the `nextToken`, you will receive all the data.\n\n## Base Load of Data\n\nEngageli's APIs are designed to be used in an incremental way, being polled regularly for new or updated data. However, we understand that as part of an integration project you may need to perform a base load of historical data covering weeks, months or even years of usage.\n\nFor best performance in base load situations, we recommend you segment your historical date range and make API calls for each segment separately. This will ensure the APIs return data as quickly as possible, allowing you to continue with your project. This is often best done programmatically for ease of management.\n\nWe recommend the following maximum date range segment sizes for each data API, although for some customers we may advise different limits:\n\n| **API** | **Recommended date range segment size limit** |\n| --- | --- |\n| Live Session Reports | 30 days |\n| Playback Session Reports | 7 days |\n| Lectures | n/a |\n| Attendance | 30 days |\n| Engagement Events | 1 hour (API will not allow more than this) |\n| Classes | n/a |\n\n## User Information\n\nWhere user information is included in responses, please be aware that some fields such as name, can be updated by your source systems such as the Learning Management System, and Engageli may hold out of date information if a sync has not recently taken place. We include identifiers such as `lmsUserId` that indicate the unique record in your source system, to allow you to join to your source data.\n\n# Understanding Engageli Data\n\nThere are several objects used in the responses from this API. Here is a brief description of what each represents.\n\n| **Object** | **Description** |\n| --- | --- |\n| `class` | The Engageli class is a persistent space where presence and engagement activity is generated. The class supports one `meeting` at a time in the instructor-led Live Classroom, but the class can then be reused for other meetings at other times. The Playback Room for the class supports concurrent and separate student-initiated use. Access to the class is controlled by means of membership on the `roster`, or possession of a current guest token. |\n| `roster` | Each class has a roster which is a list of users authorized to access the class, along with their permitted role. We also provide details of which LMS course placed them on the roster, if applicable. |\n| `lmsInfo` | Each class has details of its LTI 1.3 links with LMS courses. A class may have no link, one link, or more than one link. Where links exist, each may be responsible for adding and managing users on the class `roster`. Where more than one link attempts to manage a user, the most recent link to sync with the class will take ownership of that user. |\n| `meeting` | A meeting is a timebound instance of a Live Classroom or a Playback Room for a class. Each meeting is linked to only one class and has start and end timestamps. |\n| `schedule` | A class may optionally have one or more schedules set, which can limit the visibility of Live Classroom attendance and engagement analytics in the Engageli Portal UI, as well as in the response from the Attendance API endpoint. Where a schedule exists, there will be a nested array of events that indicate what time periods will be shown. |\n| `lecture` | The reporting unit within the Attendance API endpoint response is a lecture, which generally maps to meetings, that is a timebound period in the Live Classroom. In order to support a wide range of use cases for attendance reporting, the lecture object can also represent a subset, or a group, of meetings. A lecture can also provide reporting for playback attendance against a video file that has been uploaded to appear alongside the list of Live Classroom recordings. |\n\nThis Entity Relationship Diagram explains how the various data objects seen in the API responses relate to each other, which you may find helpful when designing schemas to hold the data in your systems. Click the image below to see a larger version.\n\n<img src=\"https://content.pstmn.io/0ea02fa0-bb3d-45f0-8c58-e783f04c32e8/RW5nYWdlbGkgVjIgQVBJIEVSRC5wbmc=\">\n\n## User Roles\n\nEvery user is listed in the User Management screen within the Admin Portal. Here they have a defined `Default Role` which is what they will be rostered with initially when being added to a class in the portal UI, although that roster role can be changed before being saved.\n\nWhen a user is rostered to a classroom, they have a `Roster Role` which determines which `Session Role` they may join a live class with. The mappings are as follows:\n\n| **Roster Role** | **Allowed Session Role(s)** |\n| --- | --- |\n| `prof` (`Instructor` in the UI) | `coInstructor` (`Instructor` in the UI) or `TA` |\n| `TA` | `TA` |\n| `student` (`Learner` in the UI) | `student` (`Learner` in the UI) |\n\n## Similar fields\n\nThere are a number of fields titled \"version\" or similar throughout this documentation, so for clarity they are summarized here with differences explained.\n\n| **Field** | **Location** | **Meaning** |\n| --- | --- | --- |\n| `version` | Data response root | API response/schema version |\n| `versions` | Class object | Class compatibility metadata |\n| `progressVersion` | Lecture/attendance record | Attendance recalculation version |","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","isPublicCollection":false,"owner":"17080638","team":4165482,"collectionId":"89a0bb0d-6e9b-402a-8982-ec3cc4376420","publishedId":"2sB3WpPzmu","public":true,"publicUrl":"https://documenter-api.postman.tech/view/17080638/2sB3WpPzmu","privateUrl":"https://go.postman.co/documentation/17080638-89a0bb0d-6e9b-402a-8982-ec3cc4376420","customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"documentationLayout":"classic-double-column","customisation":{"metaTags":[{"name":"description","value":""},{"name":"title","value":""}],"appearance":{"default":"light","themes":[{"name":"dark","logo":null,"colors":{"top-bar":"212121","right-sidebar":"303030","highlight":"FF6C37"}},{"name":"light","logo":null,"colors":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"}}]}},"version":"8.12.6","publishDate":"2025-10-31T13:22:17.000Z","activeVersionTag":"latest","documentationTheme":"light","metaTags":{"title":"","description":""},"logos":{"logoLight":null,"logoDark":null}},"statusCode":200},"environments":[],"user":{"authenticated":false,"permissions":{"publish":false}},"run":{"button":{"js":"https://run.pstmn.io/button.js","css":"https://run.pstmn.io/button.css"}},"web":"https://www.getpostman.com/","team":{"logo":"https://res.cloudinary.com/postman/image/upload/t_team_logo_pubdoc/v1/team/e9345b3f5311b47d73e6ecd690fc9ef9779a318cbe35138e19c8b7e5e53d9e92","favicon":""},"isEnvFetchError":false,"languages":"[{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"HttpClient\"},{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"RestSharp\"},{\"key\":\"curl\",\"label\":\"cURL\",\"variant\":\"cURL\"},{\"key\":\"dart\",\"label\":\"Dart\",\"variant\":\"http\"},{\"key\":\"go\",\"label\":\"Go\",\"variant\":\"Native\"},{\"key\":\"http\",\"label\":\"HTTP\",\"variant\":\"HTTP\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"OkHttp\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"Unirest\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"Fetch\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"jQuery\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"XHR\"},{\"key\":\"c\",\"label\":\"C\",\"variant\":\"libcurl\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Axios\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Native\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Request\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Unirest\"},{\"key\":\"objective-c\",\"label\":\"Objective-C\",\"variant\":\"NSURLSession\"},{\"key\":\"ocaml\",\"label\":\"OCaml\",\"variant\":\"Cohttp\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"cURL\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"Guzzle\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"HTTP_Request2\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"pecl_http\"},{\"key\":\"powershell\",\"label\":\"PowerShell\",\"variant\":\"RestMethod\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"http.client\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"Requests\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"httr\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"RCurl\"},{\"key\":\"ruby\",\"label\":\"Ruby\",\"variant\":\"Net::HTTP\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"Httpie\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"wget\"},{\"key\":\"swift\",\"label\":\"Swift\",\"variant\":\"URLSession\"}]","languageSettings":[{"key":"csharp","label":"C#","variant":"HttpClient"},{"key":"csharp","label":"C#","variant":"RestSharp"},{"key":"curl","label":"cURL","variant":"cURL"},{"key":"dart","label":"Dart","variant":"http"},{"key":"go","label":"Go","variant":"Native"},{"key":"http","label":"HTTP","variant":"HTTP"},{"key":"java","label":"Java","variant":"OkHttp"},{"key":"java","label":"Java","variant":"Unirest"},{"key":"javascript","label":"JavaScript","variant":"Fetch"},{"key":"javascript","label":"JavaScript","variant":"jQuery"},{"key":"javascript","label":"JavaScript","variant":"XHR"},{"key":"c","label":"C","variant":"libcurl"},{"key":"nodejs","label":"NodeJs","variant":"Axios"},{"key":"nodejs","label":"NodeJs","variant":"Native"},{"key":"nodejs","label":"NodeJs","variant":"Request"},{"key":"nodejs","label":"NodeJs","variant":"Unirest"},{"key":"objective-c","label":"Objective-C","variant":"NSURLSession"},{"key":"ocaml","label":"OCaml","variant":"Cohttp"},{"key":"php","label":"PHP","variant":"cURL"},{"key":"php","label":"PHP","variant":"Guzzle"},{"key":"php","label":"PHP","variant":"HTTP_Request2"},{"key":"php","label":"PHP","variant":"pecl_http"},{"key":"powershell","label":"PowerShell","variant":"RestMethod"},{"key":"python","label":"Python","variant":"http.client"},{"key":"python","label":"Python","variant":"Requests"},{"key":"r","label":"R","variant":"httr"},{"key":"r","label":"R","variant":"RCurl"},{"key":"ruby","label":"Ruby","variant":"Net::HTTP"},{"key":"shell","label":"Shell","variant":"Httpie"},{"key":"shell","label":"Shell","variant":"wget"},{"key":"swift","label":"Swift","variant":"URLSession"}],"languageOptions":[{"label":"C# - HttpClient","value":"csharp - HttpClient - C#"},{"label":"C# - RestSharp","value":"csharp - RestSharp - C#"},{"label":"cURL - cURL","value":"curl - cURL - cURL"},{"label":"Dart - http","value":"dart - http - Dart"},{"label":"Go - Native","value":"go - Native - Go"},{"label":"HTTP - HTTP","value":"http - HTTP - HTTP"},{"label":"Java - OkHttp","value":"java - OkHttp - Java"},{"label":"Java - Unirest","value":"java - Unirest - Java"},{"label":"JavaScript - Fetch","value":"javascript - Fetch - JavaScript"},{"label":"JavaScript - jQuery","value":"javascript - jQuery - JavaScript"},{"label":"JavaScript - XHR","value":"javascript - XHR - JavaScript"},{"label":"C - libcurl","value":"c - libcurl - C"},{"label":"NodeJs - Axios","value":"nodejs - Axios - NodeJs"},{"label":"NodeJs - Native","value":"nodejs - Native - NodeJs"},{"label":"NodeJs - Request","value":"nodejs - Request - NodeJs"},{"label":"NodeJs - Unirest","value":"nodejs - Unirest - NodeJs"},{"label":"Objective-C - NSURLSession","value":"objective-c - NSURLSession - Objective-C"},{"label":"OCaml - Cohttp","value":"ocaml - Cohttp - OCaml"},{"label":"PHP - cURL","value":"php - cURL - PHP"},{"label":"PHP - Guzzle","value":"php - Guzzle - PHP"},{"label":"PHP - HTTP_Request2","value":"php - HTTP_Request2 - PHP"},{"label":"PHP - pecl_http","value":"php - pecl_http - PHP"},{"label":"PowerShell - RestMethod","value":"powershell - RestMethod - PowerShell"},{"label":"Python - http.client","value":"python - http.client - Python"},{"label":"Python - Requests","value":"python - Requests - Python"},{"label":"R - httr","value":"r - httr - R"},{"label":"R - RCurl","value":"r - RCurl - R"},{"label":"Ruby - Net::HTTP","value":"ruby - Net::HTTP - Ruby"},{"label":"Shell - Httpie","value":"shell - Httpie - Shell"},{"label":"Shell - wget","value":"shell - wget - Shell"},{"label":"Swift - URLSession","value":"swift - URLSession - Swift"}],"layoutOptions":[{"value":"classic-single-column","label":"Single Column"},{"value":"classic-double-column","label":"Double Column"}],"versionOptions":[],"environmentOptions":[{"value":"0","label":"No Environment"}],"canonicalUrl":"https://documenter.gw.postman.com/view/metadata/2sB3WpPzmu"}