From 0f9809abdac3802e1dd60592b4eb335bfff6bba8 Mon Sep 17 00:00:00 2001 From: Sebastian Silva <44152511+OneComputerGuy@users.noreply.github.com> Date: Mon, 7 Sep 2026 14:31:07 -0500 Subject: [PATCH 1/2] Added UEF changes, enabled RSS, minor docs fixes --- .../lti/1.3/01-register-an-application.md | 20 +-- .../proctoring/01-getting-started.md | 3 +- .../rest-apis/hands-on/attendance.md | 91 ++++++------ .../rest-apis/hands-on/calendar-api.md | 49 ++++--- .../sandbox-envs/ami-config/system-access.md | 2 +- .../01-uef-changes.md | 131 ++++++++++++++++++ .../02-recommended-changes.md | 58 ++++++++ .../03-id-changes.md | 94 +++++++++++++ .../04-changelog.md | 1 + .../01-getting-started.md | 0 .../02-how-it-works.md | 4 +- .../03-requirements-for-uef.md | 6 +- .../04-authenticating-to-uef.md | 38 ++--- .../Tutorials/01-lti-to-uef-tutorial.md | 0 .../Tutorials/02-past-devcons.md | 0 .../03-communication_page_lvl_analytics-id.md | 0 .../Tutorials/04-lti_launch_context_added.md | 0 .../Tutorials/05-tutorials-course-leftnav.md | 0 docs/community/getting-involved.md | 6 +- .../developer-portal/dev-portal-start-here.md | 5 +- docs/partners/blackboard-app-catalog-faq.md | 2 +- docusaurus.config.js | 15 +- sidebar.js | 2 +- src/Components/BBButton/BBButton.module.css | 2 +- src/css/custom.css | 25 ++++ src/pages/contributions.jsx | 66 --------- src/pages/contributions.module.css | 17 --- src/services/apiContributions.js | 16 --- static/img/rss.svg | 1 + widgets/newDocs.json | 12 +- 30 files changed, 443 insertions(+), 223 deletions(-) create mode 100644 docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/01-uef-changes.md create mode 100644 docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/02-recommended-changes.md create mode 100644 docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/03-id-changes.md create mode 100644 docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/04-changelog.md rename docs/blackboard/uef/{ => Start Developing for UEF}/01-getting-started.md (100%) rename docs/blackboard/uef/{ => Start Developing for UEF}/02-how-it-works.md (97%) rename docs/blackboard/uef/{ => Start Developing for UEF}/03-requirements-for-uef.md (95%) rename docs/blackboard/uef/{ => Start Developing for UEF}/04-authenticating-to-uef.md (93%) rename docs/blackboard/uef/{ => Start Developing for UEF}/Tutorials/01-lti-to-uef-tutorial.md (100%) rename docs/blackboard/uef/{ => Start Developing for UEF}/Tutorials/02-past-devcons.md (100%) rename docs/blackboard/uef/{ => Start Developing for UEF}/Tutorials/03-communication_page_lvl_analytics-id.md (100%) rename docs/blackboard/uef/{ => Start Developing for UEF}/Tutorials/04-lti_launch_context_added.md (100%) rename docs/blackboard/uef/{ => Start Developing for UEF}/Tutorials/05-tutorials-course-leftnav.md (100%) delete mode 100644 src/pages/contributions.jsx delete mode 100644 src/pages/contributions.module.css delete mode 100644 src/services/apiContributions.js create mode 100644 static/img/rss.svg diff --git a/docs/blackboard/lti/1.3/01-register-an-application.md b/docs/blackboard/lti/1.3/01-register-an-application.md index 0ef4f62a9..73edf469e 100644 --- a/docs/blackboard/lti/1.3/01-register-an-application.md +++ b/docs/blackboard/lti/1.3/01-register-an-application.md @@ -1,8 +1,8 @@ --- title: Registering a new LTI application id: register-an-application -published: '' -edited: '' +published: "" +edited: "" author: Scott Hurrey --- @@ -60,14 +60,14 @@ You will also receive an application key and secret. These are your credentials In Learn the way an LTI tool is surfaced in the user interface (UI) is through the definition of one or more `Placements`. An application developer can define these placements so a Learn admin doesn't have to. There are currently six types of placements you can create: -| Type | Description | Options | -| -------------- | ----------------------------------------------------------------------------------------------------------- | -------------------- | -| Deep Linking | Supports [LTI Deep Linking](https://www.imsglobal.org/spec/lti-dl/v2p0) to get content in outline or editor | Allow student access | -| Course Content | Can be placed in the course outline or editor | Can be graded | -| Course | Appears in Ultra Books & Tools, Original Tools | Allow student access | -| System | Appears in Ultra Base Nav Tools, Original Institution module | | -| Admin | Appears in Admin Tools module | | -| UEF | Special type for extending the Ultra UI; see [UEF docs](../../uef/01-getting-started.md) | | +| Type | Description | Options | +| -------------- | ----------------------------------------------------------------------------------------------------------------------- | -------------------- | +| Deep Linking | Supports [LTI Deep Linking](https://www.imsglobal.org/spec/lti-dl/v2p0) to get content in outline or editor | Allow student access | +| Course Content | Can be placed in the course outline or editor | Can be graded | +| Course | Appears in Ultra Books & Tools, Original Tools | Allow student access | +| System | Appears in Ultra Base Nav Tools, Original Institution module | | +| Admin | Appears in Admin Tools module | | +| UEF | Special type for extending the Ultra UI; see [UEF docs](../../uef/Start%20Developing%20for%20UEF/01-getting-started.md) | | ### Placement properties diff --git a/docs/blackboard/proctoring/01-getting-started.md b/docs/blackboard/proctoring/01-getting-started.md index b6ba988f6..54f8c875c 100644 --- a/docs/blackboard/proctoring/01-getting-started.md +++ b/docs/blackboard/proctoring/01-getting-started.md @@ -49,7 +49,7 @@ Two types of LTI placements will need to be created to successfully integrates a id: rest_apis-premium-apis-uef-getting_started id: rest_apis-premium-apis-uef-getting_started -This placement will be the primary means of communication between your application and Ultra Extension Framework. Ultra Extension Framework will be used to render the settings of each proctoring service inside the assessment settings of Ultra. Once your application is authorized with Ultra Extension Framework, your app will be able to use the API to register as a proctoring service and provide HTML to display. [See for more information](../uef/01-getting-started.md) about UEF including tutorials on how to get started. +This placement will be the primary means of communication between your application and Ultra Extension Framework. Ultra Extension Framework will be used to render the settings of each proctoring service inside the assessment settings of Ultra. Once your application is authorized with Ultra Extension Framework, your app will be able to use the API to register as a proctoring service and provide HTML to display. [See for more information](../uef/Start%20Developing%20for%20UEF/01-getting-started.md) about UEF including tutorials on how to get started. ##### Create new Ultra Extension placement: @@ -217,7 +217,6 @@ Pre-requisites: ![](/assets/img/proctoring/Aspose.Words.aaa5fe5c-6d33-4e17-8ca7-9a778984b297.010.png) One of the following may be true: - - Ultra Extension placement has not been created or is set to unavailable - Authorization with Ultra Extension Framework failed - Error in your JS script Ultra Extension Framework is calling diff --git a/docs/blackboard/rest-apis/hands-on/attendance.md b/docs/blackboard/rest-apis/hands-on/attendance.md index 8aee6cf30..e6c291a6a 100644 --- a/docs/blackboard/rest-apis/hands-on/attendance.md +++ b/docs/blackboard/rest-apis/hands-on/attendance.md @@ -3,8 +3,8 @@ title: Using Attendance APIs id: attendance categories: Learn REST APIS Attendance author: Davey Herrera -published: '2022-10-21' -edited: '' +published: "2022-10-21" +edited: "" --- > Tested Using Blackboard LMS Release 3900.50.0-rel.21+840a19d @@ -73,11 +73,9 @@ Hopefully this last image is helpful, if you have any questions, please contact > A very important note to keep in mind: As of the date of creation of this document, If you create an attendance meeting using the REST API, the attendance status CANNOT be modified using the GUI, it can ONLY be modified using REST API. This does not apply to meetings created in the GUI, you can modify those using either the GUI or the REST API. -### Meeting related endpoints +## Meeting related endpoints -#### One by one operations with meetings - -#### Creating a meeting +### Creating a meeting When you use the GUI, you can click on the "Overall" button and click then on the "Plus (+) button next to the current meeting (or overall score). @@ -85,7 +83,7 @@ When you use the GUI, you can click on the "Overall" button and click then on th When you create a new column, it automatically takes in today's date as the column name. Then you will be able to mark the student's attendance status: -```json +``````json ["Present", "Absent", "Late", "Excused"] ` @@ -93,7 +91,7 @@ you can learn even more about attendance here: https://help.blackboard.com/Learn Now, when creating one using REST API is quite simple use: -- **POST** `/learn/api/public/v1/courses/{courseId}/meetings +- **POST** `/learn/api/public/v1/courses/\{courseId\}/meetings And in the body: @@ -106,11 +104,11 @@ And in the body: "end": "2022-10-18T18:25:47.416Z", "externalLink": "This optional field can be an url" } -``` +`````` When the api is successful, it returns 200: -`````json +```json { "id": 465, "courseId": "_912_1", @@ -120,13 +118,13 @@ When the api is successful, it returns 200: "end": "2022-10-18T18:25:47.416Z", "externalLink": "https//google.com" } -` +``` And this is how a meeting created using our API looks like and its parts: ![A new meeting created using REST API](../../../../static/assets/img/docs-site_attendance-7.png) -#### Returning a meeting +### Returning a meeting We already know how to create a meeting, and in the same process we are seeing all the meetings, it is possible to get the same data on the api using @@ -144,15 +142,15 @@ When 200: "end": "2022-10-18T18:25:47.416Z", "externalLink": "https//google.com" } -` +``` -#### Mapping the results +### Mapping the results Here is a mapping of the results returned by the API and what we have in the GUI. ![Values returned by the API mapped to the GUI](../../../../static/assets/img/docs-site_attendance-8.png) -#### Updating a meeting +### Updating a meeting - **PATCH** `/learn/api/public/v1/courses/:courseId/meetings/:meetingId` @@ -167,21 +165,21 @@ Using the same body as POST "end": "2022-10-18T18:25:47.416Z", "externalLink": "This optional field can be an url" } -` +``` -#### Deleting a meeting +### Deleting a meeting This endpoint deletes a meeting - **DELETE** `/learn/api/public/v1/courses/:courseId/meetings/:meetingId` -#### Batch operations with Meetings +### Batch operations with Meetings You can perform batch operations with meetings as well, however those are limited to Read and delete, meaning you can either read ALL the meetings in a course or you can remove ALL the meetings in a course. The delete all meetings in a course is a VERY powerful endpoint, use it carefully! -#### Return all meetings in a course +### Return all meetings in a course -- **GET** `/learn/api/public/v1/courses/{courseId}/meetings` +- **GET** `/learn/api/public/v1/courses/\{courseId\}/meetings` Returns 200 @@ -241,19 +239,17 @@ Returns 200 } ] } -` +``` -#### Remove all meetings from the course +### Remove all meetings from the course -- **DELETE** `/learn/api/public/v1/courses/{courseId}/meetings +- **DELETE** `/learn/api/public/v1/courses/\{courseId\}/meetings When it is successful returns 204 -### User related endpoints - -#### one by one operations +## User related endpoints -#### Creating an attendance record for one user in one meeting +### Creating an attendance record for one user in one meeting We have this meeting that we need to add attendance records to: @@ -269,13 +265,13 @@ Body "status": "Present", "userId": "_15104_1" } -` +``` when it is successful, it returns 201, it looks like this in the GUI: ![A meeting in Ultra course view with an attendance record](../../../../static/assets/img/docs-site_attendance-10.png) -#### Returning an Attendance record for one user in one meeting +### Returning an Attendance record for one user in one meeting - **GET** `/learn/api/public/v1/courses/:courseId/meetings/:meetingId`/users/:userId` @@ -286,11 +282,11 @@ when it is successful, it returns 201, it looks like this in the GUI: "userId": "_15104_1", "status": "Present" } -` +``` This basically returns the same information found in the previous image. -#### Updating an attendance record for one user in one meeting +### Updating an attendance record for one user in one meeting - **PATCH** `/learn/api/public/v1/courses/:courseId/meetings/:meetingId`/users/:userId` @@ -302,11 +298,11 @@ Body "userId": "_15104_1", "status": "Excused" } -` +``` Returns when 200: -```json +````json { "id": 760, "meetingId": "465", @@ -317,7 +313,7 @@ Returns when 200: ![A meeting in Ultra course view with an attendance record updated](../../../../static/assets/img/docs-site_attendance-11.png) -#### Deleting an attendance record for one user in one meeting +### Deleting an attendance record for one user in one meeting - **DELETE** `/learn/api/public/v1/courses/:courseId/meetings/:meetingId`/users/:userId` @@ -325,9 +321,9 @@ When successful, returns 204 NO CONTENT ![A meeting in Ultra course view with an attendance record removed](../../../../static/assets/img/docs-site_attendance-12.png) -#### Batch operations +### Batch operations -#### Creating attendance status for all users in one meeting +### Creating attendance status for all users in one meeting Even though the endpoint documentation marks user_id and meeting_id as mandatory fields (in the body), you only need to send in the body the status like this: @@ -335,12 +331,12 @@ Even though the endpoint documentation marks user_id and meeting_id as mandatory { "status": "Excused" } -` +```` This basically updates all students' attendance status to the same for **ALL OF THEM.** ![A meeting in Ultra course view all users with the same attendance status](../../../../static/assets/img/docs-site_attendance-13.png) -#### Return ALL users and their attendance status to one meeting +### Return ALL users and their attendance status to one meeting ![A meeting in Ultra course view with all students attendance marked](../../../../static/assets/img/docs-site_attendance-14.png) @@ -365,9 +361,9 @@ When 200 returns: } ] } -` +``` -#### Return ALL attendance status of one user to all meetings in one course +### Return ALL attendance status of one user to all meetings in one course Now, let's say you want to have all the attendance records of one user, with this endpoint, you will get all the attendance status if all the available meetings for one specific user @@ -436,9 +432,9 @@ When 200, returns: } ] } -` +``` -#### Removing all attendance records in a meeting +### Removing all attendance records in a meeting - **DELETE** `/learn/api/public/v1/courses/:courseId/meetings/:meetingId`/users @@ -448,21 +444,20 @@ When completed, returns 204 NO CONTENT: ![A meeting in Ultra course view all the meetings and attendance for one user marked with their status](../../../../static/assets/img/docs-site_attendance-17.png) -#### Removing all attendance records in one course for one user +### Removing all attendance records in one course for one user This endpoint is very powerful, be careful when using it since it will remove ALL attendance records of a specific user in a course. -- **DELETE** /learn/api/public/v1/courses/{courseId}/meetings/users/{userId}` +- **DELETE** /learn/api/public/v1/courses/\{courseId\}/meetings/users/\{userId\}` When successful, returns 204 NO CONTENT. -#### Remove all attendance records in ALL COURSES for one user +### Remove all attendance records in ALL COURSES for one user This endpoint is very powerful, be careful when using it since it will remove ALL attendance records of a specific user in ALL courses -- **DELETE** /learn/api/public/v1/courses/{courseId}/meetings/users/{userId}` +- **DELETE** /learn/api/public/v1/courses/\{courseId\}/meetings/users/\{userId\}` -#### CSV Export endpoint +### CSV Export endpoint Unfortunately at the moment of writing, this endpoint is not working properly so, I am unable to tell you how it works, however, once this is fixed I will update this, for now, the GUI is the best place to get the information. -``` diff --git a/docs/blackboard/rest-apis/hands-on/calendar-api.md b/docs/blackboard/rest-apis/hands-on/calendar-api.md index d9dbdfc7c..184ec4cd9 100644 --- a/docs/blackboard/rest-apis/hands-on/calendar-api.md +++ b/docs/blackboard/rest-apis/hands-on/calendar-api.md @@ -1,16 +1,19 @@ --- -title: 'Working with Calendar APIs' +title: "Working with Calendar APIs" id: calendar-apis categories: Learn REST Working-with APIs Calendar -published: '2022-10-03' -edited: '2023-10-20' +published: "2022-10-03" +edited: "2023-10-20" author: Davey Herrera, Mark O'Neil --- -> Tested with Blackboard LMS version 3900.48.0 -> +:::info +Tested with Blackboard LMS version 3900.48.0 + > Note: non-3LO capabilities available in Blackboard LMS version 3900.78.0 +::: + ## Topic Learn provides an internal calendar system for Institutional, Course, and Personal calendar items. Learn Public REST APIs for this calendar system allow external integrations to manage Institutional and Course Calendars. For Personal calendars use of three-legged-oauth (3LO) is required. @@ -622,11 +625,11 @@ As with Update you must know the calendarItem Id of the calendarItem you wish to **Success** 204 No content -## A Sidebar on ISO-8601, UTC, and REST APIs +### A Sidebar on ISO-8601, UTC, and REST APIs Public REST APIs always return ISO 8601 UTC Zulu time zone formatted date/time data. To properly manage conversion to your time zone to display and use dates in your requests it is important to understand the relationship between UTC and the ISO 8601 date-time format and how the REST APIs handle date/times. -### In brief: +### In brief - All Learn instances store date-times in the database as localized server time – which may or may not be the consumers time zone – this is why… - All REST APIs return date-times in UTC Zulu format and as such developers need to adjust to the appropriate time zone for their UI. @@ -712,26 +715,30 @@ Calendar entitlements required per endpoint are listed in the calendar API docum Note: Please review our General REST API Best Practices which are outlined in our [REST API Best Practices](/docs/blackboard/rest-apis/best-practices.md) guide. -1. Never, use GET /learn/api/public/v1/calendars/items in a non-3LO capacity! +### Never, use GET /learn/api/public/v1/calendars/items in a non-3LO capacity! + +3LO always limits calendar data to what a specific user may view. Non-3LO use of the calendar endpoints is more data inclusive. While safe to use as a 3LO authenticated user, using the /calendars/items endpoint as a non-3LO user will attempt to dump the entire calendar db for the the specified timebox (maximum of 14 week’s worth for every course). THIS WILL POTENTIALLY IMPAIR SYSTEM PERFORMANCE. DO NOT DO THIS! + +### Target your requests based on calendarType and Ids + +Always target your requests based on the Id of the target course and use calendarTypes to limit the scope of the request. Failure to do so may have negative performance impact. + +Use calendarType, calendarItem, or courseId as required to manage the impacted data set. -> 3LO always limits calendar data to what a specific user may view. Non-3LO use of the calendar endpoints is more data inclusive. While safe to use as a 3LO authenticated user, using the /calendars/items endpoint as a non-3LO user will attempt to dump the entire calendar db for the the specified timebox (maximum of 14 week’s worth for every course). THIS WILL POTENTIALLY IMPAIR SYSTEM PERFORMANCE. DO NOT DO THIS! +### Timebox your requests -2. Target your requests based on calendarType and Ids +Always timebox your requests. Failure to do so may have negative performance impact. By default all requests are timeboxed to 14 weeks ahead of the date/time of the request. -> Always target your requests based on the Id of the target course and use calendarTypes to limit the scope of the request. Failure to do so may have negative performance impact. +Use the since and until parameters to timebox your requests: -> Use calendarType, calendarItem, or courseId as required to manage the impacted data set. +**Since** -3. Timebox your requests +Query parameter: `string($date-time)`: Specifies only calendar items after the 'since' date (inclusive) are to be returned. Maximum of 16 weeks after the 'since' date will be returned. ISO-8601 date-time format is expected: -> Always timebox your requests. Failure to do so may have negative performance impact. By default all requests are timeboxed to 14 weeks ahead of the date/time of the request. +`[yyyy-MM-dd | yyyyMMdd][T(hh:mm[:ss[.sss]] | hhmm[ss[.sss]])]?[Z | [+-]hh:mm]]` -> Use the since and until parameters to timebox your requests: +**Until** -| **since** | | -| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | ------------------- | ------------ | -| Query parameter: `string($date-time)` | Specifies only calendar items after the 'since' date (inclusive) are to be returned. Maximum of 16 weeks after the 'since' date will be returned. ISO-8601 date-time format is expected: `[yyyy-MM-dd | yyyyMMdd][T(hh:mm[:ss[.sss]] | hhmm[ss[.sss]])]?[Z | [+-]hh:mm]]` | +Query parameter: `string($date-time)` | Specifies only calendar items before the 'until' date (inclusive) are to be returned. Maximum of 16 weeks prior to the 'until' date will be returned. ISO-8601 date-time format is expected: -| **until** | | -| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | ------------------- | ------------ | -| Query parameter: `string($date-time)` | Specifies only calendar items before the 'until' date (inclusive) are to be returned. Maximum of 16 weeks prior to the 'until' date will be returned. ISO-8601 date-time format is expected: `[yyyy-MM-dd | yyyyMMdd][T(hh:mm[:ss[.sss]] | hhmm[ss[.sss]])]?[Z | [+-]hh:mm]]` | +`[yyyy-MM-dd | yyyyMMdd][T(hh:mm[:ss[.sss]] | hhmm[ss[.sss]])]?[Z | [+-]hh:mm]]` diff --git a/docs/blackboard/sandbox-envs/ami-config/system-access.md b/docs/blackboard/sandbox-envs/ami-config/system-access.md index 92ce0b082..56ded5252 100644 --- a/docs/blackboard/sandbox-envs/ami-config/system-access.md +++ b/docs/blackboard/sandbox-envs/ami-config/system-access.md @@ -126,4 +126,4 @@ You can find additional information about our integration methods here: - REST API: [About Blackboard REST APIs](/docs/blackboard/rest-apis/apis-intro.md) - LTI: [Getting started with LTI](/docs/blackboard/lti/welcome) -- Ultra Extension Framework (UEF) [What is UEF](/docs/blackboard/uef/01-getting-started.md) +- Ultra Extension Framework (UEF) [What is UEF](/docs/blackboard/uef/Start%20Developing%20for%20UEF/01-getting-started.md) diff --git a/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/01-uef-changes.md b/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/01-uef-changes.md new file mode 100644 index 000000000..cd8619bd9 --- /dev/null +++ b/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/01-uef-changes.md @@ -0,0 +1,131 @@ +--- +title: "Navigation, Route, and URL Changes" +id: uef-changes-new-version +sidebar_position: 1 +edited: "2026-09-01" +--- + +# Navigation, Route, and URL Changes Affecting UEF and LTI Integrations + +Following changes to Blackboard LMS' system navigation, work deployed on the releases currently available in Test servers converted a number of course-level peek panels into full pages. This has changed internal route/state names, some URL paths, and some query parameters. In this document we will go over the changes that will be introduced and how to adjust your integration code. + +## The UEF route and launch events + +Ultra navigation through the UEF route event. Two route event types are emitted: + +| Event | Fires | +| -------------- | --------------------------------------- | +| route | After a navigation transition completes | +| route:changing | Before a navigation transition beings | + +Each carries the following payload: + +```json +{ + "type": "event:event", + "eventType": "route", // or 'route:changing' + "routeName": "", + "routeData": { + // route parameters for the destination + "isLaunchedInNewWindow": false + } +} +``` + +### RouteName is not a stable contract + +The `routeName` value delivered by the Route event can change in any release. It is a description of Ultra's internal navigation state, not a versioned identifier. State names encode real structure — parent/child relationships that determine what Ultra renders — so when that structure changes, the names change with it. This is a property of the routing system, not a naming convention we can hold fixed. + +Integrations that key behavior off routeName should expect to revisit that logic at navigation milestones. +Where a supported alternative exists, prefer it: see !!INTERNAL DOC LINK TO SECTION 8.1!! + +1. `routeName` reflects the whole parent state chain. A change anywhere in that chain changes the value, even when the specific page you care about is untouched. Both parent segments and leaf names changed in this release — see !!INTERNAL DOC LINK TO SECTION 8.1!! for what that means for string matching. +2. `routeData` carries the route parameters. If you need the course or content id, read it from routeData rather than parsing routeName or the URL. `routeData` was not affected by these changes. It should be used instead of parsing of URLs. + +### A worked example + +The same navigation — a student clicking Start Attempt on a proctored assessment: + +#### Before + +```json +{ + "type": "event:event", + "eventType": "route", + "routeName": "base.courses.peek.course.outline.peek.lti.launch-frame", + "routeData": { + "coursesOrOrganizations": "courses", + "courseId": "_302_1", + "toolHref": "https://…/execute/blti/launchPlacement?handle=…&course_id=_302_1&content_id=…", + "isLaunchedInNewWindow": false + } +} +``` + +#### After + +```json +{ + "type": "event:event", + "eventType": "route", + "routeName": "course.lti-launch-frame", + "routeData": { + "coursesOrOrganizations": "courses", + "courseId": "_302_1", + "toolHref": "https://…/execute/blti/launchPlacement?handle=…&course_id=_302_1&content_id=…", + "contentId": "_1086_1", + "isLaunchedInNewWindow": false + } +} +``` + +### The route event does not see every LTI launch + +If you use the route event to detect that an LTI tool has launched, be aware that it only covers launches that cause a navigation. A separate subscription exists for launches that do not: + +| Subscription | Fires for | +| ------------ | ------------------------------------------------------------------------------- | +| route | Same-window launches inside Ultra - These navigate, so a route event is emitted | +| lti:launch | Launches that occur without a route change | + +`lti:launch` is emitted in two cases: when Ultra launches a tool in a new window (no navigation happens, so +there is no route event), and when a UEF-hosted LTI launch component renders its iframe. Its payload is: + +```json +{ + "type": "event:event", + "eventType": "lti:launch", + "launchData": { + "courseId": "_555_1", + "coursesOrOrganizations": "courses", // or 'organizations' + "isLaunchedInNewWindow": true, // false for the UEF component case + "toolHref": "" + } +} +``` + +If you need to observe LTI launches reliably, subscribe to both route and `lti:launch`. An integration +watching only route events will silently miss new-window launches. As with `routeData`, `launchData` carries +the identifiers you need — `courseId` and `toolHref` — so this path does not require route-name matching +either. + +## Hardcoded Learn URL links + +Constructed or hardcoded Learn URLs are not a supported integration mechanism and their stability is not guaranteed across releases + +For returning the user to Learn after your tool finishes, use the `return_url` Learn provides in the LTI launch. It is supplied in the `launch_presentation` claim for LTI 1.3, or as `launch_presentation_return_url` for LTI 1.1. Redirect the user there when your tool is done; Learn recognizes it and routes the user to the right place. You never need to know or construct an Ultra URL. + +This return URL is provided on all launch types, proctoring launches included. It takes the form: + +``` +https:///webapps/blackboard/execute/blti/launchReturn?course_id=&content_id=&toGC=&nonce= +``` + +Two things follow from that shape: + +- It already carries `course_id` and `content_id`. You do not need to track them separately in order to return the user to the right place. +- Append to this URL — do not rebuild it. It carries a nonce and other parameters Learn requires. Preserve the query string you were given and add your own parameters to it. + +:::danger courseId and course_id +URL Paths and query parameters are not meant to be parsed, and are unstable each release. +::: diff --git a/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/02-recommended-changes.md b/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/02-recommended-changes.md new file mode 100644 index 000000000..1a6da544f --- /dev/null +++ b/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/02-recommended-changes.md @@ -0,0 +1,58 @@ +--- +title: "Recommended Integration Practices" +id: uef-recommended-practices +sidebar_position: 2 +edited: "2026-09-01" +--- + +# Recommended integration practices + +Following these recommendations means future navigation changes should not break your integration. + +## Matching routeName safely + +If you must match on `routeName`, never compare the full string for equality. Parent segments change; matching the leaf suffix you actually care about is significantly more durable: + +```js +// Fragile — breaks whenever any parent state changes +if (routeName === "course.outline.peek.assessment.ims-proctoring") { + /* ... */ +} +// More durable — survives parent state changes +if (routeName.endsWith(".peek.assessment.ims-proctoring")) { + /* ... */ +} +``` + +Be aware of the limit of this technique. Suffix matching protects you when only the parent chain changes. It does not protect you when the leaf name itself changes. + +Suffix matching reduces your exposure; it does not eliminate it. Any logic keyed off `routeName` remains subject to change. Where one of the mechanisms below covers your use case, use it instead of route matching. + +When validating against a new release, assert that your route matches still fire. Checking only for errors will not detect this class of break. + +## Use `ultra_return_loc` to control the return + +If your goal is to control where Ultra navigates after an LTI launch returns, there is a supported parameter for exactly this. Do not infer it from route names. Include `ultra_return_loc` on the LTI launch return URL: + +| Value | Returns to | +| -------------- | ---------------------------------------------------- | +| launch_attempt | Proctored assessment attempt (taking the assessment) | +| assessment | Assessment overview | + +### Supporting parameters + +`content_id` for both; plus `course_id`, `password`, and `returnToProctoringToolOnEndAssessment` for `launch_attempt`. + +## Read route parameters from routeData, not from names or URLs + +The UEF route event's routeData object carries the route parameters. Prefer it over parsing routeName or the URL. + +## Subscribe to both `route` and `lti:launch` + +If you need to know when an LTI tool has launched, the `route` event alone is not sufficient — it only fires for launches that navigate. New-window launches emit `lti:launch` instead, and an integration watching only route events will never see them. + +Subscribe to both, and read the identifiers you need from `routeData` and `launchData` respectively. See **_[The UEF route and launch events](./01-uef-changes.md#the-uef-route-and-launch-events)_** document for more information. + +## Do not build or hardcode Learn URLs + +As seen in **_[Hardcoded Learn URL Links](./01-uef-changes.md#hardcoded-learn-url-links)_**, Constructed Learn URLs are not a supported integration mechanism and are not guaranteed stable across releases. diff --git a/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/03-id-changes.md b/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/03-id-changes.md new file mode 100644 index 000000000..efc7289a5 --- /dev/null +++ b/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/03-id-changes.md @@ -0,0 +1,94 @@ +--- +title: "List of ID changes" +id: id-changes +sidebar_position: 3 +edited: "2026-09-01" +--- + +The following tables corresponds to the IDs that changed/will be changed in the next release: + +## Course-level (l1) pages + +| Previous (4000.19.0 and prior) | Current (4000.21.0 and up) | +| ------------------------------------------------- | ---------------------------------------------------- | +| `course.outline` | `course.l1.outline` | +| `course.achievements` | `course.l1.achievements` | +| `course.analytics` | `course.l1.analytics` | +| `course.analytics.question-analysis` | `course.l1.analytics.question-analysis` | +| `course.analytics.course-activity` | `course.l1.analytics.course-activity` | +| `course.analytics.reports` | `course.l1.analytics.reports` | +| `course.analytics.scorm.reports` | `course.l1.analytics.scorm.reports` | +| `course.analytics.course-reports` | `course.l1.analytics.course-reports` | +| `course.announcements` | `course.l1.announcements` | +| `course.calendar` | `course.l1.calendar` | +| `course.classic` | `course.l1.classic` | +| `course.classic.outline` | `course.l1.classic.outline` | +| `course.classic.outline.ultra-course-self-enroll` | `course.l1.classic.outline.ultra-course-self-enroll` | +| `course.engagement` | `course.l1.engagement` | +| `course.grades` | `course.l1.grades` | +| `course.groups` | `course.l1.groups` | +| `course.groups-student` | `course.l1.groups-student` | +| `course.messages` | `course.l1.messages` | + +## LTI launch routes + +| Previous (4000.19.0 and prior) | Current (4000.21.0 and up) | +| ------------------------------ | -------------------------- | +| `lti.launch` | `course.lti-launch` | +| `lti.launch-frame` | `course.lti-launch-frame` | +| `lti.launch-peek` | `course.lti-launch-peek` | + +### LTI Tags unchanged + +- `lti.launch-frame-system` +- `lti.launch-frame-embedded` +- `lti.launch-cloud-create` +- `content-manage.edit.lti` +- `content-manage.edit.placement` +- `cloud-document.edit` + +## Assessment and Proctoring routes + +| Previous (4000.19.0 and prior) | Current (4000.21.0 and up) | +| ----------------------------------------------------------------------- | -------------------------------------------------------------- | +| `assessment.overview` | `course.assessment-l2.overview` | +| `assessment.external-overview` | `course.assessment-l2.external-overview` | +| `assessment.overview.attempt` | `course.assessment-l2.attempt.view` | +| `assessment.overview.attempt.review` | `assessment.attempt.review` | +| `assessment.overview.attempt.review.assessment-submission-feedback-tab` | `assessment.attempt.review.assessment-submission-feedback-tab` | +| `assessment.overview.attempt.review.inline-rubric` | `assessment.attempt.review.inline-rubric` | +| `assessment.overview.attempt.review.originality-tab` | `assessment.attempt.review.originality-tab` | +| `assessment.overview.multiple-attempt` | `assessment.multiple-attempt` | + +## Other Course routes + +| Area | Previous (4000.19.0 and prior) | Current (4000.21.0 and up) | +| ----------- | ----------------------------------------- | ------------------------------------------------------------------ | +| Discussions | `discussion` | `course.discussion` | +| Discussions | `discussion.view-with.grading` | `course.discussion.with-grading` | +| Discussions | `discussion.view` | **REMOVED** | +| Journals | `journal` | `course.journal` | +| Journals | `journal.view` | `course.journal.view` | +| Journals | `journal.view.with-participation` | **REMOVED (with all its children)** | +| SCORM | `scorm-overview` | `course.scorm-overview` | +| SCORM | `scorm-launch-frame` | `course.scorm-launch-frame` | +| SCORM | `scorm-overview.student` | `scorm-single-attempt` | +| SCORM | `scorm-overview.student.multiple-attempt` | `scorm-multiple-attempt` | +| SCORM | `scorm-overview.student.attempt` | **REMOVED** | +| SCORM | `gradebook-item.scorm-submissions` | `course.gradebook-item-l2.gradebook-item-parent.scorm-submissions` | +| Gradebook | `gradebook-item.assessment` | `course.gradebook-item-l2.gradebook-item-parent.assessment` | +| Content | `content-manage.video` | `course.content-manage.create.video` | +| Content | `content-navigator-transition-full` | `course.content-navigator-transition-full` | +| Content | `content-navigator-placeholder` | `course.content-navigator-placeholder` | +| Files | `preview-file` | `course.content-manage.edit.preview-file` | + +## URL Path and Query parameters + +| Route | Previous (4000.19.0 and prior) | Current (4000.21.0 and up) | +| ---------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- | +| LTI Launch | `/launch?courseId&contentId&linkRef&linkType&linkContentId` | `/lti/launch?contentId&linkRef&linkType&linkContentId` | +| LTI launch frame | `/launchFrame?toolHref&toolTitle&contentId&linkContentId` | `/lti/launchFrame?toolHref&toolTitle&contentId&linkContentId` | +| LTI launch peek | `/launchPeek?toolHref&courseId&contentId` | `/lti/launchPeek?toolHref&contentId` | +| Document | `/document/:id?courseId&view&state&linkContentId` | `/document/:id?view&state&linkContentId` | +| SCORM overview | `/scorm/overview/\{contentId\}?courseId&linkContentId` | `/scorm/overview/\{contentId\}?linkContentId` | +| Discussion | `/\{contentId\}?courseId&parentId&position&positionBefore&positionAfter&selectedMessageId` | `/discussion/\{contentId\}?parentId&position&positionBefore&positionAfter&selectedMessageId` | diff --git a/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/04-changelog.md b/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/04-changelog.md new file mode 100644 index 000000000..948cf947f --- /dev/null +++ b/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/04-changelog.md @@ -0,0 +1 @@ +| diff --git a/docs/blackboard/uef/01-getting-started.md b/docs/blackboard/uef/Start Developing for UEF/01-getting-started.md similarity index 100% rename from docs/blackboard/uef/01-getting-started.md rename to docs/blackboard/uef/Start Developing for UEF/01-getting-started.md diff --git a/docs/blackboard/uef/02-how-it-works.md b/docs/blackboard/uef/Start Developing for UEF/02-how-it-works.md similarity index 97% rename from docs/blackboard/uef/02-how-it-works.md rename to docs/blackboard/uef/Start Developing for UEF/02-how-it-works.md index 298cd471b..8f0a3f6ef 100644 --- a/docs/blackboard/uef/02-how-it-works.md +++ b/docs/blackboard/uef/Start Developing for UEF/02-how-it-works.md @@ -21,13 +21,13 @@ By definition, the UEF integration triggers and performs the LTI call when the u ### LTI block -This block follow the same process for an LTI Message Flow described by the Core LTI 1.3 specifications, this will verify that the integration is allowed to perform operations within the Blackboard LMS server and will review if the user is allowed to launch the integration. Below is a brief overview of the LTI flow, for more information about this, flow please refer to [LTI Message Launch Flow](../lti/1.3/core/01-core-launch.md): +This block follow the same process for an LTI Message Flow described by the Core LTI 1.3 specifications, this will verify that the integration is allowed to perform operations within the Blackboard LMS server and will review if the user is allowed to launch the integration. Below is a brief overview of the LTI flow, for more information about this, flow please refer to [LTI Message Launch Flow](../../lti/1.3/core/01-core-launch.md): ![Diagram of the flow used by Core LTI 1.3](/assets/img/uef-lti-flow.png) ### REST API block -Once the LTI step is completed and Learn has sent to your tool the JWT token containing all the information about the user and context, you need to redirect the request to the REST API authentication endpoint to start a 3-Legged OAuth flow which will give you a bearer token tailored to the user's privileges and entitlements. This process follows the standard 3-Legged OAuth flow described below, for more information about this flow, please refer to [3-Legged OAuth](../rest-apis/getting-started/3lo.md) +Once the LTI step is completed and Learn has sent to your tool the JWT token containing all the information about the user and context, you need to redirect the request to the REST API authentication endpoint to start a 3-Legged OAuth flow which will give you a bearer token tailored to the user's privileges and entitlements. This process follows the standard 3-Legged OAuth flow described below, for more information about this flow, please refer to [3-Legged OAuth](../../rest-apis/getting-started/3lo.md) ![Diagram of the flow used by REST API using 3LO](/assets/img/uef-rest-flow.png) diff --git a/docs/blackboard/uef/03-requirements-for-uef.md b/docs/blackboard/uef/Start Developing for UEF/03-requirements-for-uef.md similarity index 95% rename from docs/blackboard/uef/03-requirements-for-uef.md rename to docs/blackboard/uef/Start Developing for UEF/03-requirements-for-uef.md index 4cceabdb4..c45fdc442 100644 --- a/docs/blackboard/uef/03-requirements-for-uef.md +++ b/docs/blackboard/uef/Start Developing for UEF/03-requirements-for-uef.md @@ -1,8 +1,8 @@ --- -title: 'Before you start developing for UEF' +title: "Before you start developing for UEF" id: uef-requirements sidebar_position: 3 -edited: '2024-10-11' +edited: "2024-10-11" --- Before you can start working and developing for UEF, you will need to make sure a few things are in order. @@ -19,7 +19,7 @@ In the ticket, include the email used to register the application in the Develop ## Register a new application or use an existing one -To use our framework, you need to create or use an existing application, created through the Developer Portal, including all the information for an LTI 1.3 application. If you need information about the registration process, you can follow our document [Registering and Managing a REST or LTI Application](../../developer-portal/creating-rest-or-lti-application.md) +To use our framework, you need to create or use an existing application, created through the Developer Portal, including all the information for an LTI 1.3 application. If you need information about the registration process, you can follow our document [Registering and Managing a REST or LTI Application](../../../developer-portal/creating-rest-or-lti-application.md) ## UEF placement diff --git a/docs/blackboard/uef/04-authenticating-to-uef.md b/docs/blackboard/uef/Start Developing for UEF/04-authenticating-to-uef.md similarity index 93% rename from docs/blackboard/uef/04-authenticating-to-uef.md rename to docs/blackboard/uef/Start Developing for UEF/04-authenticating-to-uef.md index a95580e31..d985fd2c4 100644 --- a/docs/blackboard/uef/04-authenticating-to-uef.md +++ b/docs/blackboard/uef/Start Developing for UEF/04-authenticating-to-uef.md @@ -1,8 +1,8 @@ --- -title: 'Authenticating to UEF' +title: "Authenticating to UEF" id: uef-authentication sidebar_position: 4 -edited: '2024-10-11' +edited: "2024-10-11" --- Now that you have the knowledge of how UEF works, the first thing you need to do is authenticate to it. When you respond to the authentication request (after finishing the REST API block from the previous section) with an HTML file that contains the JS file, you will have to do the steps outlined below to authenticate and create the communication channel between Ultra and your file. @@ -22,16 +22,16 @@ To let Ultra know about your integration, you can post a browser-wide message (u ```javascript window.parent.postMessage( { - type: 'integration-hello', + type: "integration-hello", }, - `{learn-domain}/*` + `{learn-domain}/*`, ); ``` You also need to register an Event Listener for messages, which will allow you to listen for the initial syncronization message from Ultra. The listener can be defined like this: ```javascript -addEventListener('message', (incomingMessage) => { +addEventListener("message", (incomingMessage) => { // Your code here }); ``` @@ -56,24 +56,24 @@ Now that we have a dedicated message channel to communicate with Ultra, we can a ```javascript incomingMessage.ports[0].postMessage({ - type: 'authorization:authorize', - token: 'token_received_from_3LO', + type: "authorization:authorize", + token: "token_received_from_3LO", }); ``` _(Building on top of the previous event listener added for messages)_ ```javascript -addEventListener('message', (incomingMNessage) => { +addEventListener("message", (incomingMNessage) => { // Validates if the origin of the message is indeed the learn server you're expecting - if (incomingMessage.origin !== '{learn_domain}') return; + if (incomingMessage.origin !== "{learn_domain}") return; // Registers the integration - if (incomingMessage.data.type === 'integration:hello') { + if (incomingMessage.data.type === "integration:hello") { // Sends the user oAuth token to be able to properly work with UEF and render information based on the user's roles incomingMessage.ports[0].postMessage({ - type: 'authorization:authorize', - token: 'token_received_from_3LO', + type: "authorization:authorize", + token: "token_received_from_3LO", }); } }); @@ -110,14 +110,14 @@ from here you can review what events you need and then, subscribe to them sendin ```javascript incomingMessage.ports[0].postMessage({ - type: 'event:subscribe', + type: "event:subscribe", subscriptions: [ - 'click', - 'hover', - 'route', - 'portal:new', - 'portal:remove', - 'lti:launch', + "click", + "hover", + "route", + "portal:new", + "portal:remove", + "lti:launch", ], }); ``` diff --git a/docs/blackboard/uef/Tutorials/01-lti-to-uef-tutorial.md b/docs/blackboard/uef/Start Developing for UEF/Tutorials/01-lti-to-uef-tutorial.md similarity index 100% rename from docs/blackboard/uef/Tutorials/01-lti-to-uef-tutorial.md rename to docs/blackboard/uef/Start Developing for UEF/Tutorials/01-lti-to-uef-tutorial.md diff --git a/docs/blackboard/uef/Tutorials/02-past-devcons.md b/docs/blackboard/uef/Start Developing for UEF/Tutorials/02-past-devcons.md similarity index 100% rename from docs/blackboard/uef/Tutorials/02-past-devcons.md rename to docs/blackboard/uef/Start Developing for UEF/Tutorials/02-past-devcons.md diff --git a/docs/blackboard/uef/Tutorials/03-communication_page_lvl_analytics-id.md b/docs/blackboard/uef/Start Developing for UEF/Tutorials/03-communication_page_lvl_analytics-id.md similarity index 100% rename from docs/blackboard/uef/Tutorials/03-communication_page_lvl_analytics-id.md rename to docs/blackboard/uef/Start Developing for UEF/Tutorials/03-communication_page_lvl_analytics-id.md diff --git a/docs/blackboard/uef/Tutorials/04-lti_launch_context_added.md b/docs/blackboard/uef/Start Developing for UEF/Tutorials/04-lti_launch_context_added.md similarity index 100% rename from docs/blackboard/uef/Tutorials/04-lti_launch_context_added.md rename to docs/blackboard/uef/Start Developing for UEF/Tutorials/04-lti_launch_context_added.md diff --git a/docs/blackboard/uef/Tutorials/05-tutorials-course-leftnav.md b/docs/blackboard/uef/Start Developing for UEF/Tutorials/05-tutorials-course-leftnav.md similarity index 100% rename from docs/blackboard/uef/Tutorials/05-tutorials-course-leftnav.md rename to docs/blackboard/uef/Start Developing for UEF/Tutorials/05-tutorials-course-leftnav.md diff --git a/docs/community/getting-involved.md b/docs/community/getting-involved.md index 924827069..a9c99cacb 100644 --- a/docs/community/getting-involved.md +++ b/docs/community/getting-involved.md @@ -16,10 +16,10 @@ Getting involved in the Developer community is easy and with options to suit you - Host a webinar - Please consider hosting a Webinar on any topic that you feel would benefit the developer community. We are able to provide a conference line and Collaborate software to support your webinar. Contact us if you are interested. - The Developer Office Hours is interested in hosting your presentation. Contact us if you have a topic on which you would like to present. -- [Contribute an idea](https://community.blackboard.com/developers) for a REST or LTI Tool -- [Link to your blog](https://community.blackboard.com/developers) +- [Contribute an idea](https://community.blackboard.com) for a REST or LTI Tool +- [Link to your blog](https://community.blackboard.com) - Present at a conference or user group event - - Check the [Calendar of Events](https://community.blackboard.com/developers) for upcoming deadlines or regularly meeting groups which may benefit from your experience + - Check the [Calendar of Events](https://community.blackboard.com) for upcoming deadlines or regularly meeting groups which may benefit from your experience - [Host an event](mailto:bbpartnerteam@blackboard.com) - E-mail [BbDN](mailto:bbpartnerteam@blackboard.com) with your event details so that we can add it to our events calendar. - [Give us feedback](mailto:developers@blackboard.com) diff --git a/docs/developer-portal/dev-portal-start-here.md b/docs/developer-portal/dev-portal-start-here.md index 578ad31aa..576dce1bf 100644 --- a/docs/developer-portal/dev-portal-start-here.md +++ b/docs/developer-portal/dev-portal-start-here.md @@ -33,7 +33,7 @@ When you enter our developer portal, you will find several links starting from t ### Developer Documentation -Blackboard’s Developer Documentation (which includes this page) helps you explore Blackboard’s product resources. It includes tutorials, sample code, articles, and API references. For an overview, visit https://docs.anthology.com/docs/site-intro. +Blackboard’s Developer Documentation (which includes this page) helps you explore Blackboard’s product resources. It includes tutorials, sample code, articles, and API references. For an overview, visit [Blackboard Integrations](/docs/blackboard/welcome) ### Explore APIs @@ -85,7 +85,7 @@ If you are encountering issues when you select **Create Account**, make sure you ![Developer portal sign up form](/assets/img/dev-portal-start-here-4.png) -Once you have successfully created your account, you will receive an email that gives information about our Documentation, Community, Partnerships, GitHub, and about our Amazon Machine Images [AMIs](https://docs.anthology.com/docs/rest-apis/learn/sandbox/developer-ami). +Once you have successfully created your account, you will receive an email that gives information about our Documentation, Community, Partnerships, GitHub, and about our Amazon Machine Images [AMIs](/docs/blackboard/sandbox-envs/welcome). Once you have created your account, you will be presented with a page that looks like this: @@ -140,7 +140,6 @@ This applies to our Learn, Ally and Student APIs that user Swagger for documenta 1. Beneath the **Name** is the name of the query parameter. The query parameter must be used in the same way it is written here. 2. Beneath the query parameter describes three things: - 1. Type of value 2. Character limit 3. Type of parameter (either query parameter or path parameter). diff --git a/docs/partners/blackboard-app-catalog-faq.md b/docs/partners/blackboard-app-catalog-faq.md index 6d8944198..4de77d649 100644 --- a/docs/partners/blackboard-app-catalog-faq.md +++ b/docs/partners/blackboard-app-catalog-faq.md @@ -23,7 +23,7 @@ Partner integrations continue to play a critical and vital role within the Learn ## What does "ULTRA READY" mean? -Any integration listed as "Ultra Ready" is labeled as such to indicate it was built leveraging only Blackboard integration frameworks specifically supported in Ultra (i.e. Partner Cloud, LTI 1.1+ and/or Learn REST APIs). The term "Ultra Ready" is not equivalent to a Blackboard certification status for the Ultra experience.[††](#ultraready) +Any integration listed as "Ultra Ready" is labeled as such to indicate it was built leveraging only Blackboard integration frameworks specifically supported in Ultra (i.e. Partner Cloud, LTI 1.1+ and/or Learn REST APIs). The term "Ultra Ready" is not equivalent to a Blackboard certification status for the Ultra experience. ![Ultra Ready Badges](/assets/img/ultraready.png "Ultra Ready Badges") diff --git a/docusaurus.config.js b/docusaurus.config.js index 24b22f715..ee4411cdb 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -67,6 +67,14 @@ const config = { // Remove this to remove the "edit this page" links. //editUrl: // 'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/', + feedOptions: { + type: "all", + title: "Latest from Blackboard Devs", + description: + "Get the latest blogs and news from the Blackboard Developer Docs!", + language: "en_US", + copyright: `Copyright © ${new Date().getFullYear()} Blackboard T&L Inc.`, + }, }, theme: { customCss: [ @@ -91,7 +99,12 @@ const config = { }, items: [ { to: "/blog", label: "Blog", position: "right" }, - { to: "/contributions", label: "Contributions", position: "right" }, + { + type: "html", + position: "right", + value: + '', + }, { type: "html", position: "right", diff --git a/sidebar.js b/sidebar.js index 08b273b02..7f426deae 100644 --- a/sidebar.js +++ b/sidebar.js @@ -180,7 +180,7 @@ const sidebars = { }, { type: "link", - label: "UEF specifications", + label: "UEF Specifications", href: "https://docs.anthology.com/uef-documentation/start.html", }, ], diff --git a/src/Components/BBButton/BBButton.module.css b/src/Components/BBButton/BBButton.module.css index 563db73b7..8c4665294 100644 --- a/src/Components/BBButton/BBButton.module.css +++ b/src/Components/BBButton/BBButton.module.css @@ -14,7 +14,7 @@ font-weight: 700; border-radius: 0.5rem; border: none; - background-color: var(--ifm-color-primary); + background-color: #172622; } .bbButton img { diff --git a/src/css/custom.css b/src/css/custom.css index 08993eff6..c53b48b9a 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -29,6 +29,7 @@ --ifm-heading-color: ##f9f7f6; --ifm-navbar-background-color: #172622; /* Background color */ --ifm-color-primary: #f9f7f6; + --ifm-link-color: #f1dbcf; --ifm-color-primary-dark: #f1dbcf; --ifm-color-primary-darker: #f1dbcf; --ifm-color-primary-darkest: #f1dbcf; @@ -73,6 +74,30 @@ h4 { font-family: "Wittgenstein", sans-serif !important; } +a { + font-weight: 600; +} + +/* Navbar RSS Styles */ +.navbar-rss-img-link { + padding: 0; + margin: 0; + width: 1.2rem; + height: 1.2rem; +} + +.navbar-rss-link { + display: flex; + align-self: center; + align-items: center; +} + +[data-theme="dark"] .navbar-rss-img-link { + filter: brightness(0) saturate(100%) invert(100%) sepia(0%) saturate(4012%) + hue-rotate(308deg) brightness(94%) contrast(108%); +} + +/* Navbar Home icon styles */ .navbar-home-img-link { padding: 0; margin: 0; diff --git a/src/pages/contributions.jsx b/src/pages/contributions.jsx deleted file mode 100644 index 7a7de9882..000000000 --- a/src/pages/contributions.jsx +++ /dev/null @@ -1,66 +0,0 @@ -import React, { useEffect, useState } from "react"; -import Layout from "@theme/Layout"; -import clsx from "clsx"; -import styles from "./contributions.module.css"; - -import ContributionsTable from "../Components/ContributionsTable/ContributionsTable"; -import { apiGetContributions } from "../services/apiContributions"; - -let apiContributionData = []; - -const productTypeLookup = { - Learn: "Learn", - Student: "Student", - Reach: "Reach", -}; - -export default function Contributions() { - const [allContributions, setAllContributions] = useState([]); - - function filterByProduct() { - const dataByProduct = apiContributionData - .filter((repo) => !repo.name.startsWith(".")) - .map((repo) => { - const productType = - Object.keys(productTypeLookup).find((key) => - repo.name.startsWith(key) - ) || "Other"; - - return { - ...repo, - product_type: productType, - }; - }); - console.log(`Filtered by product data`); - console.log(dataByProduct); - return dataByProduct; - } - - useEffect(() => { - async function getData() { - apiContributionData = await apiGetContributions(); - setAllContributions(filterByProduct()); - } - getData(); - }, []); - - return ( - -
-

Welcome to the Community Contributions page!

-

- This is the index of the applications/programs/documentation currently - available for our different products, along with the language and a - brief description of its purpose. -
- If you find any specific error or issue with any of the code - repositories, feel free to open a new issue within the repository of - the affected source and we'll review it. -

-
-
- -
-
- ); -} diff --git a/src/pages/contributions.module.css b/src/pages/contributions.module.css deleted file mode 100644 index 27aba096b..000000000 --- a/src/pages/contributions.module.css +++ /dev/null @@ -1,17 +0,0 @@ -.contributions-section { - display: flex; - flex-direction: column; - align-items: center; - margin: 2rem 1rem 0 1rem; -} - -.contributions-section h1 { - font-weight: 800; -} - -.contributions-main { - align-self: center; - align-content: center; - max-width: 90rem; - margin: 1rem 0 2rem 0; -} diff --git a/src/services/apiContributions.js b/src/services/apiContributions.js deleted file mode 100644 index c8cc2c44f..000000000 --- a/src/services/apiContributions.js +++ /dev/null @@ -1,16 +0,0 @@ -const URL = - "https://z9yn4qiqgk.execute-api.us-east-1.amazonaws.com/contributions"; - -export async function apiGetContributions() { - try { - const response = await fetch(URL); - if (response.status === 200) { - const data = await response.json(); - return data; - } else { - console.log(`Error status code: ${response.status}`); - } - } catch (error) { - console.error("Failed to get the repositories", error); - } -} diff --git a/static/img/rss.svg b/static/img/rss.svg new file mode 100644 index 000000000..4ce24e259 --- /dev/null +++ b/static/img/rss.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/widgets/newDocs.json b/widgets/newDocs.json index 7e96c70ff..7b7878f2e 100644 --- a/widgets/newDocs.json +++ b/widgets/newDocs.json @@ -1,11 +1,7 @@ { - "0": { - "name": "Tips for using the Create and SaveNew API operations", - "url": "/docs/student/best-practices/create-savenew-bestpractices" - }, "1": { - "name": "Tips for using the Get and Save API operations", - "url": "/docs/student/best-practices/get-save-bestpractices" + "name": "Changes to UEF on version 4000.21.0 and newer", + "url": "/docs/blackboard/uef/Integration Change Notice on 4000.21.0 and newer/01-uef-changes.md" }, "2": { "name": "Working with groups and the API", @@ -13,10 +9,10 @@ }, "3": { "name": "Sanctioned LTI Registration and Deployment with Learn", - "url": "/docs/blackboard/lti/lti-registration-deployment" + "url": "/docs/blackboard/lti/1.3/register-an-application" }, "4": { "name": "What are Premium APIs", - "url": "/docs/blackboard/premium-apis/requesting-premium-apis" + "url": "/docs/blackboard/uef/Start%20Developing%20for%20UEF/uef-requirements" } } From 51c572ba80c1c44a4215e7936926c0e6e2d0c21e Mon Sep 17 00:00:00 2001 From: Sebastian Silva <44152511+OneComputerGuy@users.noreply.github.com> Date: Mon, 7 Sep 2026 14:42:14 -0500 Subject: [PATCH 2/2] CSpell on /docs and /blog --- blog/2020/2020-07-10-In Orbit at DevCon 2020.md | 4 ++-- blog/2020/2020-10-15-Cookies-and-Browsers.md | 2 +- blog/2020/2020-12-16-SOAP-EOL-Explained.md | 6 +++--- ...e a User With Limited Entitlements For REST API Calls.md | 2 +- ...sion tokens instead of cookies for UEF authentication.md | 2 +- ...I 1.3 tools must generate their own keys and JWKS URL.md | 2 +- blog/2022/2022-08-12-DevCon2022.md | 2 +- ...23-05-01-IntegrationInstallationandCustomerExperience.md | 6 +++--- docs/ally/about-api-documentation.md | 2 +- docs/ally/auth.md | 4 ++-- docs/ally/getting-started.md | 2 +- docs/blackboard/caliper/caliper-event-store-for-learn.md | 2 +- docs/blackboard/caliper/events/assessment-events.md | 2 +- docs/blackboard/lti/1.3/tutorials/names-and-roles.md | 2 +- docs/blackboard/lti/1.3/tutorials/py-lti-1p3.md | 2 +- docs/blackboard/lti/1.3/tutorials/testing-tool.md | 2 +- docs/blackboard/lti/migrate-lti11.md | 2 +- docs/blackboard/proctoring/01-getting-started.md | 4 ++-- .../rest-apis/advanced/[review]ultra-assignments.md | 2 +- docs/blackboard/rest-apis/advanced/bbml.md | 4 ++-- docs/blackboard/rest-apis/demo-code/curl.md | 4 ++-- .../rest-apis/getting-started/basic-authentication.md | 2 +- docs/blackboard/rest-apis/getting-started/lti-or-rest.md | 6 +++--- .../getting-started/mapping-entitlements-to-privileges.md | 4 ++-- docs/blackboard/rest-apis/getting-started/tutorials.md | 2 +- docs/blackboard/rest-apis/hands-on/adaptive-release.md | 6 +++--- docs/blackboard/rest-apis/hands-on/calendar-api.md | 2 +- docs/blackboard/rest-apis/hands-on/copying-courses.md | 4 ++-- docs/blackboard/rest-apis/hands-on/gradebook.md | 4 ++-- docs/blackboard/sis/sis-password-hashes.md | 2 +- .../Start Developing for UEF/04-authenticating-to-uef.md | 2 +- .../Tutorials/05-tutorials-course-leftnav.md | 4 ++-- docs/developer-portal/creating-and-managing-groups.md | 2 +- docs/developer-portal/creating-rest-or-lti-application.md | 2 +- docs/student/best-practices/DeterminingAccountBalances.md | 2 +- docs/student/best-practices/ManageClassSections.md | 4 ++-- docs/student/best-practices/ManageCustomFields.md | 2 +- docs/student/best-practices/PaymentVendorPartnerOverview.md | 6 +++--- docs/student/best-practices/SaveStudentTransferCredit .md | 2 +- 39 files changed, 59 insertions(+), 59 deletions(-) diff --git a/blog/2020/2020-07-10-In Orbit at DevCon 2020.md b/blog/2020/2020-07-10-In Orbit at DevCon 2020.md index 765677bdc..825673025 100644 --- a/blog/2020/2020-07-10-In Orbit at DevCon 2020.md +++ b/blog/2020/2020-07-10-In Orbit at DevCon 2020.md @@ -16,7 +16,7 @@ Our most-attended session was 'Collaborate Best Practices' presented by Amy Eyre -Other highlights include the 'May the Data be with you' series. I definitly miss seeing everyone in person, so the lively interaction in these sessions led by a talented group of System Administrators was definitely the next best thing. Big thanks to Casey Eubank from WSU Tech, Chris Bray from Arkansas, Heather Crites from Columbia State Community College, Dan Gioia from St. Louis Community College, Bradley Lawton from Louisville, and Mark Reynolds from University of Illinois at Urbana-Champaign. +Other highlights include the 'May the Data be with you' series. I definitely miss seeing everyone in person, so the lively interaction in these sessions led by a talented group of System Administrators was definitely the next best thing. Big thanks to Casey Eubank from WSU Tech, Chris Bray from Arkansas, Heather Crites from Columbia State Community College, Dan Gioia from St. Louis Community College, Bradley Lawton from Louisville, and Mark Reynolds from University of Illinois at Urbana-Champaign. There were also a number of other sessions that were well-attended and extremely interesting, including: @@ -38,7 +38,7 @@ And don’t forget about Hackboard: Data. This weeklong event will allow attende As I write this, it looks like Mark Reynolds is atop the leaderboard, with Bradley Lawton and Eric Silva fast on his heels. And I would be remiss if I didn't mention our badging with Badgr. So far (not including Friday), we have awarded 480 badges, including: -- Arokia Raj, INTI Internation University and Colleges in Malaysia, who earned the 'Daily Champions Champion' badge by earning all of the Daily Champion badges. +- Arokia Raj, INTI International University and Colleges in Malaysia, who earned the 'Daily Champions Champion' badge by earning all of the Daily Champion badges. - Mark Carroll, Mark Reynolds, and Kevin Lowey who earned the 'Let's take it data day' badge, by attending 4 of the 8 data-based (see what I did there?) sessions. - Mark Carroll, Alicia Dunlap, Irene Rojas, and Elizabeth Barcena, who have attended more than half of the LTI sessions, earning them the 'LTI Advantageous' badge. diff --git a/blog/2020/2020-10-15-Cookies-and-Browsers.md b/blog/2020/2020-10-15-Cookies-and-Browsers.md index 970da4c01..7978bc15f 100644 --- a/blog/2020/2020-10-15-Cookies-and-Browsers.md +++ b/blog/2020/2020-10-15-Cookies-and-Browsers.md @@ -22,7 +22,7 @@ A web application may set a cookie to track a user’s session. This is very com Another case where cookies aren’t being sent back is during a form POST back to your application. If you set a cookie, then launch to a 3rd party application, if that application does a form POST back to you, the browser will likely not send your cookie back because it is trying to help prevent cross-site request forgery attacks. -Rather than detail all the scenarios and work arounds here I link to two web pages that are immensely helpful in explaining the situation and some possible workarounds. +Rather than detail all the scenarios and workarounds here I link to two web pages that are immensely helpful in explaining the situation and some possible workarounds. The TL;DR is if you must set a cookie in your web application, be careful how you configure that cookie’s properties, and understand that at least in Safari, your cookies may not get passed back to you. The other browser makers are going to get as restrictive as Safari soon. diff --git a/blog/2020/2020-12-16-SOAP-EOL-Explained.md b/blog/2020/2020-12-16-SOAP-EOL-Explained.md index cde18c743..1ac25dcbe 100644 --- a/blog/2020/2020-12-16-SOAP-EOL-Explained.md +++ b/blog/2020/2020-12-16-SOAP-EOL-Explained.md @@ -13,17 +13,17 @@ summary: In January 4, 2019 Blackboard announced deprecation of our SOAP Web Ser Back in the day, January 4, 2019 to be exact, Blackboard announced deprecation of our SOAP Web Services with this article [Blackboard SOAP Web Services Deprecation](https://blackboard.secure.force.com/publickbarticleview?id=kA039000000Tm3cCAC&homepage=true) -Now, almost two years later in our [Learn SaaS Relase Notes](https://help.blackboard.com/learn/Administrator/SaaS/Release_Notes) we've written "As of December 31, 2020, Learn SOAP Web Services are no longer supported, as they have reached the end of life per our deprecation policy." What does this mean for you as a develoepr? +Now, almost two years later in our [Learn SaaS Release Notes](https://help.blackboard.com/learn/Administrator/SaaS/Release_Notes) we've written "As of December 31, 2020, Learn SOAP Web Services are no longer supported, as they have reached the end of life per our deprecation policy." What does this mean for you as a developer? The most common concern is "Will my SOAP code continue to work in an earlier version of Learn?" or some variation. Here's a recent example: "Will this be for all versions, or will SOAP API still be available on version 3800?" -The answer is that client's self and manged-hosted systems that are on older versions of Learn will not be impacted. If your client is runnign 3800.0.3 and upgrades to the most recent Cumulative Update, the SOAP Webservices should continue to work for them. +The answer is that client's self and manged-hosted systems that are on older versions of Learn will not be impacted. If your client is running 3800.0.3 and upgrades to the most recent Cumulative Update, the SOAP Webservices should continue to work for them. For self and managed-hosted clients that are on 3900.0.0 and are now upgrading using the same build numbers as in SaaS, SOAP will not be supported in any release post Dec 31, 2020. -Another common quesiton is from those using the Learn LIS 2.0 SIS integration, which is SOAP based. No, we are keeping the LIS 2.0 SIS integration in the product at this time. It will not be affected. +Another common question is from those using the Learn LIS 2.0 SIS integration, which is SOAP based. No, we are keeping the LIS 2.0 SIS integration in the product at this time. It will not be affected. If you have additional questions, drop a line to developers@blackboard.com and we'll update this blog post with the answer. diff --git a/blog/2021/2021-01-06-How to Create a User With Limited Entitlements For REST API Calls.md b/blog/2021/2021-01-06-How to Create a User With Limited Entitlements For REST API Calls.md index 8b9614e3a..d51752c02 100644 --- a/blog/2021/2021-01-06-How to Create a User With Limited Entitlements For REST API Calls.md +++ b/blog/2021/2021-01-06-How to Create a User With Limited Entitlements For REST API Calls.md @@ -11,7 +11,7 @@ summary: How to Create a User With Limited Entitlements For REST API Calls # How to Create a User With Limited Entitlements For REST API Calls -First, as our documentation states, a Learn admin should never be told to associate a user with Learn admin privileges with any REST API integration, see this document. Hence we often get questions from folks on how to create a user to associate with a REST API integration that has limited capability on a Learn system. One way is to research and design your REST application to use OAuth 2 3-legged Authentication. See the documents referenced below. 3LO guarentees that the user using your REST Application can only do what they can do via the Learn UX when they are logged into Learn. +First, as our documentation states, a Learn admin should never be told to associate a user with Learn admin privileges with any REST API integration, see this document. Hence we often get questions from folks on how to create a user to associate with a REST API integration that has limited capability on a Learn system. One way is to research and design your REST application to use OAuth 2 3-legged Authentication. See the documents referenced below. 3LO guarantees that the user using your REST Application can only do what they can do via the Learn UX when they are logged into Learn. diff --git a/blog/2021/2021-05-10-use one time session tokens instead of cookies for UEF authentication.md b/blog/2021/2021-05-10-use one time session tokens instead of cookies for UEF authentication.md index adc1e7e03..36a7fb1d5 100644 --- a/blog/2021/2021-05-10-use one time session tokens instead of cookies for UEF authentication.md +++ b/blog/2021/2021-05-10-use one time session tokens instead of cookies for UEF authentication.md @@ -48,7 +48,7 @@ If you are a developer that has built a UEF integration, we actually implemented This one-time session cookie is added to the claims in the LTI 1.3 JWT and the form POST parameters in LTI 1.1. You can grab that value from the LTI launch, return it as a parameter in your 3LO authorization code request, and your problem will be solved. -UPDATE: This section previously mentioned a bug where the userId needed to be appended to the one_time_session token. This bug has been fixed. Your code can now use the one_time_session_token as provided by Blackboard LMS without appending the userId. Blackboard no longer appends a userId, nor expects it in the returned value. If your code does append a comma and userId, that’s OK, you don’t immediatly need to change your code it as Blackboard just ignores the comma and what comes after if those are part of the value you send back. +UPDATE: This section previously mentioned a bug where the userId needed to be appended to the one_time_session token. This bug has been fixed. Your code can now use the one_time_session_token as provided by Blackboard LMS without appending the userId. Blackboard no longer appends a userId, nor expects it in the returned value. If your code does append a comma and userId, that’s OK, you don’t immediately need to change your code it as Blackboard just ignores the comma and what comes after if those are part of the value you send back. ### LTI 1.3 diff --git a/blog/2021/2021-07-22-LTI 1.3 tools must generate their own keys and JWKS URL.md b/blog/2021/2021-07-22-LTI 1.3 tools must generate their own keys and JWKS URL.md index 0b1254634..1bbb005fc 100644 --- a/blog/2021/2021-07-22-LTI 1.3 tools must generate their own keys and JWKS URL.md +++ b/blog/2021/2021-07-22-LTI 1.3 tools must generate their own keys and JWKS URL.md @@ -34,7 +34,7 @@ FAQ: 1. Is this just a background change, and it will not impact anything on the front end? -> There is no impact to how our mutual clients use the LTI Tool or Learn. 2. Does making the change at the central location serve the purpose, or are we required to plan anything around individual connections for separate schools? - -> You will need to work with the individual schools to ensure that after you make the chage they redploy your tool as described above. + -> You will need to work with the individual schools to ensure that after you make the change they redeploy your tool as described above. 3. Will schools transition seamlessly once we transition from a static public key to keyset URL (JWKS), or does it require any intervention from the Black side or the school admins? -> The school admins will need to redeploy your tool as described above. 4. Currently, both static public key and keyset URL (JWKS) are going through successfully. Is it because Blackboard hasn’t yet discontinued supporting the static public key? diff --git a/blog/2022/2022-08-12-DevCon2022.md b/blog/2022/2022-08-12-DevCon2022.md index bcef0304f..387648b97 100644 --- a/blog/2022/2022-08-12-DevCon2022.md +++ b/blog/2022/2022-08-12-DevCon2022.md @@ -43,7 +43,7 @@ In this presentation you will get to know the Bb_rest_helper library, and how to #### Description -The Bb Rest Helper includes 5 classes to simpilfy common API operations with Blackboard APIs; +The Bb Rest Helper includes 5 classes to simplify common API operations with Blackboard APIs; 1. Get_Config. This class is used to get configuration variables (url,key,secret)from an external configuration file in Json format. If you are authenticating for more than one API (i.e. Learn and Collaborate) you will need separate configuration files (i.e. learn_config.json and collab_config.json). 2. Auth_Helper. This class is used to get the token that then will be used in the API calls. Provides different methods for the different APIs. diff --git a/blog/2023/2023-05-01-IntegrationInstallationandCustomerExperience.md b/blog/2023/2023-05-01-IntegrationInstallationandCustomerExperience.md index fb660b6ef..d0cb1ca4e 100644 --- a/blog/2023/2023-05-01-IntegrationInstallationandCustomerExperience.md +++ b/blog/2023/2023-05-01-IntegrationInstallationandCustomerExperience.md @@ -34,7 +34,7 @@ Blackboard has built our integration experience and best practices, with these l ## Integration Installation -Blackboard has thought long about how to simplify the integration experience for customers in the world of SaaS. In doing so we arrived at a "Register once, deploy everywhere" model for Integration developers to deliver theirr solutions. This applies to LTI 1.3 and RESTful integrations alike, and greatly simplifies installation for our mutual customers. +Blackboard has thought long about how to simplify the integration experience for customers in the world of SaaS. In doing so we arrived at a "Register once, deploy everywhere" model for Integration developers to deliver their solutions. This applies to LTI 1.3 and RESTful integrations alike, and greatly simplifies installation for our mutual customers. ### SaaS changed everything... @@ -53,10 +53,10 @@ Register once and Deploy anywhere means there are some differences in how you de > Note: The following pertains to development of integrations which are marketed to multiple customers. Only point 1 is pertinent to those who are developing campus-only solutions. 1. **Logs and data**: Integrations should maintain archives of customer logs and any integration specific data as those are not provided by Blackboard products. -2. **Multi-tenancy**: Integrations should follow a multi-tenant model vs single tenant. Multi-tenant means one integration service delivering your integration to all your customers vs requiring a new intetegration service per customer. This means you have to design into your integration the ability for enabling individual customer accounts, likely only administrator, for any customer specific configuration. +2. **Multi-tenancy**: Integrations should follow a multi-tenant model vs single tenant. Multi-tenant means one integration service delivering your integration to all your customers vs requiring a new integration service per customer. This means you have to design into your integration the ability for enabling individual customer accounts, likely only administrator, for any customer specific configuration. 3. **Separation of Customer data**: Multi-tenancy means that in addition to running a single service for your customers you are likely using a single database. This dictates a secure separation of customer data using a unique customer identifier prefix on customer-centric data keys. -Each of the above enable you to deliver a secure, efficient, and postive experience to customers at a cost savings of single instance vs multiple instance service delivery. +Each of the above enable you to deliver a secure, efficient, and positive experience to customers at a cost savings of single instance vs multiple instance service delivery. ### Best Practices diff --git a/docs/ally/about-api-documentation.md b/docs/ally/about-api-documentation.md index e76c2d313..a9c754708 100644 --- a/docs/ally/about-api-documentation.md +++ b/docs/ally/about-api-documentation.md @@ -15,7 +15,7 @@ To do this, you will need your client ID and your secret. See the [Getting Start At the bottom of the documentation for the `Upload a File to Ally` endpoint, there is a **Try it now** section, where you can select a file and click submit to upload that file to be processed. -Upon upload, you will see the results appear on the screen, which will include the content hash value. This content hash value is unique to a specific piece of content, and specifically, the piece of content you just uploaded. In your application, you will use this for all subsequent calls. In the API documentation, it will automatically capture that value and paste it into the subsequest endpoints. +Upon upload, you will see the results appear on the screen, which will include the content hash value. This content hash value is unique to a specific piece of content, and specifically, the piece of content you just uploaded. In your application, you will use this for all subsequent calls. In the API documentation, it will automatically capture that value and paste it into the subsequent endpoints. The next section is the `Check the processing status of a file` endpoint. In the **Try it now** section, you will see a field for the Content hash already filled in and a Submit button. Click submit to see the result of this call. diff --git a/docs/ally/auth.md b/docs/ally/auth.md index 09f20f753..886f43535 100644 --- a/docs/ally/auth.md +++ b/docs/ally/auth.md @@ -131,7 +131,7 @@ Ally as a Service identifies the following actions: A policy statement identifies which action(s) can be invoked on which(s) resources. -For example, the following statement would allow for retrieving the procesing status of an uploaded piece of content: +For example, the following statement would allow for retrieving the processing status of an uploaded piece of content: ```json { @@ -140,7 +140,7 @@ For example, the following statement would allow for retrieving the procesing st } ``` -Note that a colon indicates the start of a new part in the namespace. It is possible to use a wildcard asterisk _\*_ to widen the resource or action. For example, the following statement would allow for retrieving the procesing status of all content items: +Note that a colon indicates the start of a new part in the namespace. It is possible to use a wildcard asterisk _\*_ to widen the resource or action. For example, the following statement would allow for retrieving the processing status of all content items: ```json { diff --git a/docs/ally/getting-started.md b/docs/ally/getting-started.md index 5fbb7ed79..4bbcd5045 100644 --- a/docs/ally/getting-started.md +++ b/docs/ally/getting-started.md @@ -8,7 +8,7 @@ author: Scott Hurrey sidebar_position: 1 --- -Ally as a Service provides separatly licensed, stand-alone API access to allow an application to process files for accessibility. Many of you are using this power in your LMS to help instructors improve the accessibility of their content, and to give students, regardless of ability, access to the content that meets their needs and learning style the best. +Ally as a Service provides separately licensed, stand-alone API access to allow an application to process files for accessibility. Many of you are using this power in your LMS to help instructors improve the accessibility of their content, and to give students, regardless of ability, access to the content that meets their needs and learning style the best. To get started, the first thing you need is a client ID, key, and secret. At this time, the best way to obtain this information is to engage your Account Executive to discuss pricing and request credentials. As the API continues to grow, this process may change, so be sure to check back here often. diff --git a/docs/blackboard/caliper/caliper-event-store-for-learn.md b/docs/blackboard/caliper/caliper-event-store-for-learn.md index 5ae514453..bd6e43261 100644 --- a/docs/blackboard/caliper/caliper-event-store-for-learn.md +++ b/docs/blackboard/caliper/caliper-event-store-for-learn.md @@ -86,7 +86,7 @@ directly to your event store. ![fill-out-the-event-store-registration-form.png](/assets/img/caliper-event-store-for-learn-6.png) -

As soon as you enable your event store, it will start to recieve events. Your +

As soon as you enable your event store, it will start to receive events. Your event store should be a fully-hardened data warehouse. There is a ton of data and no way to filter the data you receive on the Learn server. You can certainly filter out the data that you want, but you will have to be able diff --git a/docs/blackboard/caliper/events/assessment-events.md b/docs/blackboard/caliper/events/assessment-events.md index 440334dbd..1277e5de5 100644 --- a/docs/blackboard/caliper/events/assessment-events.md +++ b/docs/blackboard/caliper/events/assessment-events.md @@ -1,7 +1,7 @@ --- title: "Assessment Events" categories: Standards -id: assesment-events +id: assessment-events author: Scott Hurrey published: "" edited: "" diff --git a/docs/blackboard/lti/1.3/tutorials/names-and-roles.md b/docs/blackboard/lti/1.3/tutorials/names-and-roles.md index 6f1506649..fc58749a5 100644 --- a/docs/blackboard/lti/1.3/tutorials/names-and-roles.md +++ b/docs/blackboard/lti/1.3/tutorials/names-and-roles.md @@ -9,7 +9,7 @@ author: Scott Hurrey ### Overview -This document documents gives updates on Names and Roles as new features become available. For the definitive specifications, always refer to the published IMS documenation. +This document documents gives updates on Names and Roles as new features become available. For the definitive specifications, always refer to the published IMS documentation. ### Student Preview User Now Indicated By TestUser Role via Names and Roles Service diff --git a/docs/blackboard/lti/1.3/tutorials/py-lti-1p3.md b/docs/blackboard/lti/1.3/tutorials/py-lti-1p3.md index 88836d461..8f1ac81f8 100644 --- a/docs/blackboard/lti/1.3/tutorials/py-lti-1p3.md +++ b/docs/blackboard/lti/1.3/tutorials/py-lti-1p3.md @@ -46,7 +46,7 @@ Click `Done` to take you back to the applications page. We have one more step to go. Next to the name of your game, click the ellipsis `...` icon to launch the context menu and select `Manage Placements`. Click the `Register` button. In the `Name` field, give the placement a name that you want to display to the instructor. -In the `Desciption` field, type anything you like. Under `Type`, select `Deep Linking content tool`. +In the `Description` field, type anything you like. Under `Type`, select `Deep Linking content tool`. Under `Target link URI`, enter the launch URL to your tool. In our case it is `https://pylti1p3-game.herokuapp.com/launch/`. Now click `Register placement`, and we are ready to deploy the tool in Learn. diff --git a/docs/blackboard/lti/1.3/tutorials/testing-tool.md b/docs/blackboard/lti/1.3/tutorials/testing-tool.md index 46a52f09c..932aa16a9 100644 --- a/docs/blackboard/lti/1.3/tutorials/testing-tool.md +++ b/docs/blackboard/lti/1.3/tutorials/testing-tool.md @@ -31,4 +31,4 @@ The most important thing you can do to begin is to read, and understand [the spe [Video Part IV is a demonstration](https://youtu.be/Xu1vI-wGIhA) of custom parameters from the Deep Link launch request and also a review of Names and Roles in that request. -The purpose of Names and Roles is to let the Tool Provider get all of the memberships in the course, and the role of each member with a call to one endpoint using LTI 1.3 security. Comming soon: A screenshot of how this looks from the BLTPN - showing the first two members and their roles that were retrieved from the course. +The purpose of Names and Roles is to let the Tool Provider get all of the memberships in the course, and the role of each member with a call to one endpoint using LTI 1.3 security. Coming soon: A screenshot of how this looks from the BLTPN - showing the first two members and their roles that were retrieved from the course. diff --git a/docs/blackboard/lti/migrate-lti11.md b/docs/blackboard/lti/migrate-lti11.md index c51ba83ac..8271cfa84 100644 --- a/docs/blackboard/lti/migrate-lti11.md +++ b/docs/blackboard/lti/migrate-lti11.md @@ -160,7 +160,7 @@ from that tool will be broken and can't be recovered. Manual re-creation of the - Migrate during a low-usage window, not mid-semester or during an active grading period. - Rehearse the migration on a test/staging Blackboard instance first if one is available. - Confirm readiness before they click through the final confirmation or test on a Stage/Test environment - before commiting to the migration. **Rollbacks are not possible when migrating**, if the migration was not + before committing to the migration. **Rollbacks are not possible when migrating**, if the migration was not properly completed, the associated links will break and will have to be manually re-created. ### Known caveats to flag proactively diff --git a/docs/blackboard/proctoring/01-getting-started.md b/docs/blackboard/proctoring/01-getting-started.md index 54f8c875c..b64e3ddfd 100644 --- a/docs/blackboard/proctoring/01-getting-started.md +++ b/docs/blackboard/proctoring/01-getting-started.md @@ -149,7 +149,7 @@ if (msg.data.type === "event:event") { // ID of portal in view console.log(msg.data.portalId); - // Any specific data relavant to this portal + // Any specific data relevant to this portal console.log(msg.data.selectorData); } } @@ -174,7 +174,7 @@ if (msg.data.type === "event:event") { // ID of this portal. This must be sent back to UEF in the portal:render message const portalId = msg.data.portalId; - // contentId is included for convience in the selectorData + // contentId is included for convenience in the selectorData console.log(msg.data.selectorData.contentId); const contentsToSend = { diff --git a/docs/blackboard/rest-apis/advanced/[review]ultra-assignments.md b/docs/blackboard/rest-apis/advanced/[review]ultra-assignments.md index 1489c174b..4edee1810 100644 --- a/docs/blackboard/rest-apis/advanced/[review]ultra-assignments.md +++ b/docs/blackboard/rest-apis/advanced/[review]ultra-assignments.md @@ -10,7 +10,7 @@ author: Ryan Haber ### Overview Blackboard Ultra experience offers a REST API for managing assignments. -As of Blackbord 3900.98, in Ultra, an assignment is different from a test. SEE [Changes to Assignments With Blackboard 3900.98](/blog/changes-to-assignments-blackboard-3900.98) In an test, there are questions of various types. For an assignment, which we are disucssing +As of Blackbord 3900.98, in Ultra, an assignment is different from a test. SEE [Changes to Assignments With Blackboard 3900.98](/blog/changes-to-assignments-blackboard-3900.98) In an test, there are questions of various types. For an assignment, which we are discussing here, there is only a leading set of instructions. For more information about assignments how Learn users experience them, see [Ultra: Create an Assignment](https://help.blackboard.com/learn/Instructor/Ultra/Assignments/Create_and_Edit_Assignments) in Blackboard Help. diff --git a/docs/blackboard/rest-apis/advanced/bbml.md b/docs/blackboard/rest-apis/advanced/bbml.md index b1a50a929..2bf895001 100644 --- a/docs/blackboard/rest-apis/advanced/bbml.md +++ b/docs/blackboard/rest-apis/advanced/bbml.md @@ -232,7 +232,7 @@ following notation: ``` For proper formatting and rendering within the ULTRA environment, it is -recommened to also include a data-bbfile attribute. An example value of this +recommended to also include a data-bbfile attribute. An example value of this can be seen above in the BbML specification section. However, to describe it a bit more, the data-bbfile attribute's value is an HTML encoded json string: @@ -286,7 +286,7 @@ fields of `data-bbfile` which are expected. (`data-bbfile` is a JSON-encoded object.) For example, for the Attachment plugin, the generated bbml is as follows -(minus unneccessary whitespace I've added for easy viewing): +(minus unnecessary whitespace I've added for easy viewing): ```html 2016.03.BlackboardPartnerUpdate.pdf<_/a>"}:_' https://bd-partner-a-ultra.blackboard.com/learn/api/public/v2/courses/courseId:mbk-ultra- +curl -k -X POST -H "Authorization: Bearer 4mgoFlQoi4Jq4biKpU4R264wugsKF9R1" -H "Content-Type: application/json" --data '{"studentComments":"this is the student comment", "studentSubmission": " 2016.03.BlackboardPartnerUpdate.pdf<_/a>"}:_' https://bd-partner-a-ultra.blackboard.com/learn/api/public/v2/courses/courseId:mbk-ultra- course/gradebook/columns/_3297_1/attempts ``` diff --git a/docs/blackboard/rest-apis/getting-started/basic-authentication.md b/docs/blackboard/rest-apis/getting-started/basic-authentication.md index ded0db68c..c0cb6956f 100644 --- a/docs/blackboard/rest-apis/getting-started/basic-authentication.md +++ b/docs/blackboard/rest-apis/getting-started/basic-authentication.md @@ -93,7 +93,7 @@ you made. ### Example: Using cURL to Get a Token and Make a REST Call -The easist way to test is using cURL. We will assume you have already +The easiest way to test is using cURL. We will assume you have already registered through the [Developer Portal](/rest-apis/learn/Getting Started/registry) and retrieved your application ID, key, and secret, as well as [added your application ID](/rest-apis/learn/Getting Started/registry) to the Learn server you wish to integrate with: diff --git a/docs/blackboard/rest-apis/getting-started/lti-or-rest.md b/docs/blackboard/rest-apis/getting-started/lti-or-rest.md index 619a5354f..0f9e5692b 100644 --- a/docs/blackboard/rest-apis/getting-started/lti-or-rest.md +++ b/docs/blackboard/rest-apis/getting-started/lti-or-rest.md @@ -38,15 +38,15 @@ everything with Learn is done over HTTPS.) Blackboard has developed and publishe ## LTI DISCUSSION -When talking about LTI, we use terms like launch, platform, and tool. A Learn administrator can set up your tool in Learn, following documentation that you provide. Blackboard provides documentation applicable to any LTI tool on help.blackboard.com. Rather than reference a link that may change your best bet for finding such documentation is to use your favorite internet search engine and look for "Learn LTI documentation." I just did and the help page for our LTI documentation for admins was the top result! Once your LTI tool has been configured on a Learn system by the admin for that system, course instructors can then place links to your Tool in their courses. Search this site for LTI and you will find demonstrations and tutorials on LTI in Learn. The most common, and likley the best, way for and instructor to place content from your tool in their course is to use Deep-Linking 2.0. The point of this discussion is that once configured by the administrator, use of your tool and the content it provides looks like it is a part of Learn, including when the instructor is selecting content to be 'placed' in the course, and then when the student views and uses that content. And, using the LTI Advantage Names and Roles Provisioning Service (NPRS) and the Assignment and Grades Service (AGS), your tool can integrate closely with the course roster and the gradebook for the course. In summary, you can do a lot with LTI 1.3 & LTI Advantage, where the users of the LMS can use your web-application seamlessly from within the LMS and then with the aforementioned services even manipulate the course roster and gradebook. Get started with [this documentation](../../lti/welcome.md). +When talking about LTI, we use terms like launch, platform, and tool. A Learn administrator can set up your tool in Learn, following documentation that you provide. Blackboard provides documentation applicable to any LTI tool on help.blackboard.com. Rather than reference a link that may change your best bet for finding such documentation is to use your favorite internet search engine and look for "Learn LTI documentation." I just did and the help page for our LTI documentation for admins was the top result! Once your LTI tool has been configured on a Learn system by the admin for that system, course instructors can then place links to your Tool in their courses. Search this site for LTI and you will find demonstrations and tutorials on LTI in Learn. The most common, and likely the best, way for and instructor to place content from your tool in their course is to use Deep-Linking 2.0. The point of this discussion is that once configured by the administrator, use of your tool and the content it provides looks like it is a part of Learn, including when the instructor is selecting content to be 'placed' in the course, and then when the student views and uses that content. And, using the LTI Advantage Names and Roles Provisioning Service (NPRS) and the Assignment and Grades Service (AGS), your tool can integrate closely with the course roster and the gradebook for the course. In summary, you can do a lot with LTI 1.3 & LTI Advantage, where the users of the LMS can use your web-application seamlessly from within the LMS and then with the aforementioned services even manipulate the course roster and gradebook. Get started with [this documentation](../../lti/welcome.md). ## REST DISCUSSION -Given how much you can do with LTI, why REST APIs? Well, the LMS is also a web application and it can be represented by many different types of 'objects'. Users, courses, enrollments, calendars, announcements, content items, assignments, quizes, etc. If you want a complete view of the representation of a user or course member in Learn, you need to use our REST APIs because LTI is written to apply to all platforms, while each platform has it's own nuanced way of representing the different 'objects' in the system. For example a User in Learn has a uuuid identifier, an external ID, a datasource ID, a set of system role IDs, a URL for an avatar, etc. Some other LMS may or may not have these. LTI won't give you everything about a User object in Learn, REST APIs will. LTI may give you a subset. Another thing is that LTI doesn't cover things like creating a document in Learn, or pulling a list of all of the different types of content in a course, or creating, reading and deleting announcements. Here's a short-list of 'objects' you can read and manipulate in Learn with our REST APIs: Announcements, Attendance/meetings, Calendar, content (in the LMS) & attached files, Assessments, Course Categories, Course Groups, Course Memberships (LTI does have Names & Roles, REST give more information about the membership object), Course Messages, Courses, Data Sources, Institutional Hierarchy Nodes, LTI Placements, Course Roles, Institution Roles, System Roles, User Sessions, Terms, Users. You can get started building your REST Application with [this documentation](/docs/blackboard/rest-apis/getting-started/first-steps.md). +Given how much you can do with LTI, why REST APIs? Well, the LMS is also a web application and it can be represented by many different types of 'objects'. Users, courses, enrollments, calendars, announcements, content items, assignments, quizzes, etc. If you want a complete view of the representation of a user or course member in Learn, you need to use our REST APIs because LTI is written to apply to all platforms, while each platform has it's own nuanced way of representing the different 'objects' in the system. For example a User in Learn has a uuuid identifier, an external ID, a datasource ID, a set of system role IDs, a URL for an avatar, etc. Some other LMS may or may not have these. LTI won't give you everything about a User object in Learn, REST APIs will. LTI may give you a subset. Another thing is that LTI doesn't cover things like creating a document in Learn, or pulling a list of all of the different types of content in a course, or creating, reading and deleting announcements. Here's a short-list of 'objects' you can read and manipulate in Learn with our REST APIs: Announcements, Attendance/meetings, Calendar, content (in the LMS) & attached files, Assessments, Course Categories, Course Groups, Course Memberships (LTI does have Names & Roles, REST give more information about the membership object), Course Messages, Courses, Data Sources, Institutional Hierarchy Nodes, LTI Placements, Course Roles, Institution Roles, System Roles, User Sessions, Terms, Users. You can get started building your REST Application with [this documentation](/docs/blackboard/rest-apis/getting-started/first-steps.md). ## REST AND LTI -Now things can get interesting. You might build a pure REST Application, but often the easiest way into your application is an LTI Launch from a course or system page on a Learn system. With the LTI launch, you get all of the information about the user and the context from where they came from in the Learn system. This is quite convenient for your user as they have a smooth path to using your application (Tool) from Learn. Next, as the user is already logged into Learn, you can behind-the-scenes get an authorization token for making REST API calls back to their Learn system, without having them log in again. (A REST application that doesn't use an LTI launch from Learn will need to ask the user to log into the Learn system they are working with.) Now your LTI Tool/Appication has all of the LTI 1.3 functionality without having to make a bunch of REST API calls for that, and can also make REST API calls for any functionality not available via LTI. +Now things can get interesting. You might build a pure REST Application, but often the easiest way into your application is an LTI Launch from a course or system page on a Learn system. With the LTI launch, you get all of the information about the user and the context from where they came from in the Learn system. This is quite convenient for your user as they have a smooth path to using your application (Tool) from Learn. Next, as the user is already logged into Learn, you can behind-the-scenes get an authorization token for making REST API calls back to their Learn system, without having them log in again. (A REST application that doesn't use an LTI launch from Learn will need to ask the user to log into the Learn system they are working with.) Now your LTI Tool/Application has all of the LTI 1.3 functionality without having to make a bunch of REST API calls for that, and can also make REST API calls for any functionality not available via LTI. ## HAPPY CODING!! diff --git a/docs/blackboard/rest-apis/getting-started/mapping-entitlements-to-privileges.md b/docs/blackboard/rest-apis/getting-started/mapping-entitlements-to-privileges.md index 006195660..ee359128c 100644 --- a/docs/blackboard/rest-apis/getting-started/mapping-entitlements-to-privileges.md +++ b/docs/blackboard/rest-apis/getting-started/mapping-entitlements-to-privileges.md @@ -37,11 +37,11 @@ Well look no further because we will explain to you how to match them! 1. You need to know how to create a _custom_ System Role: [How to create a System role](https://help.blackboard.com/Learn/Administrator/SaaS/User_Management/Roles_and_Privileges/System_Roles) 2. You need to know which api endpoints you will be using: [Learn API endpoints](https://developer.blackboard.com/portal/displayApi) -3. You need to review, based on the endpoints you will be using, the entilements that you need. Remember that each entitlement is described when opening an endpoint at the beggining. +3. You need to review, based on the endpoints you will be using, the entilements that you need. Remember that each entitlement is described when opening an endpoint at the beginning. ## Context -When you want to develop an application, you will need to enable permissions for it. Doing so within learn can be challening because we talk in different terms when creating system roles and assigning privileges, we explain about them up in this page, make sure to read that first. +When you want to develop an application, you will need to enable permissions for it. Doing so within learn can be challenging because we talk in different terms when creating system roles and assigning privileges, we explain about them up in this page, make sure to read that first. Given that you already have the things that you need [Custom system role, the endpoints and entitlements]. diff --git a/docs/blackboard/rest-apis/getting-started/tutorials.md b/docs/blackboard/rest-apis/getting-started/tutorials.md index b7a28d1e8..47f746d4d 100644 --- a/docs/blackboard/rest-apis/getting-started/tutorials.md +++ b/docs/blackboard/rest-apis/getting-started/tutorials.md @@ -11,7 +11,7 @@ edited: "" # REST Tutorials -You will find these tutorials very helpful as you start developement. +You will find these tutorials very helpful as you start development. ### The Python and the Postman - DevCon 2020 diff --git a/docs/blackboard/rest-apis/hands-on/adaptive-release.md b/docs/blackboard/rest-apis/hands-on/adaptive-release.md index ffdf29e7c..d768d568e 100644 --- a/docs/blackboard/rest-apis/hands-on/adaptive-release.md +++ b/docs/blackboard/rest-apis/hands-on/adaptive-release.md @@ -25,7 +25,7 @@ For all members, you can use additional conditions such as Date/Time and Perform It is also possible to release the content to specific members of the course or groups. -Note: We are aware that there is a known issue where, if you just enrolled a user (and haven't reloaded the page) the roster is not updated on adaptive release -> Specific memebers or groups -> Individual members and search for the user that has just been enrolled, the user does not show up, groups are correctly updated. To solve this, you can just reload the page and roster will be updated. +Note: We are aware that there is a known issue where, if you just enrolled a user (and haven't reloaded the page) the roster is not updated on adaptive release -> Specific members or groups -> Individual members and search for the user that has just been enrolled, the user does not show up, groups are correctly updated. To solve this, you can just reload the page and roster will be updated. Now let's move on to the REST API part @@ -138,7 +138,7 @@ You should get a result like this (may vary depending on the criteria that has a ### Using GradeRange -This criteria specifies a gradable item, a maximun and a minimum score. When the item has been graded and the score is within the range, the content becomes available. A GradeRange criterion can be converted to a GradePercentage criterion by setting the Type to GradePercentage and +This criteria specifies a gradable item, a maximum and a minimum score. When the item has been graded and the score is within the range, the content becomes available. A GradeRange criterion can be converted to a GradePercentage criterion by setting the Type to GradePercentage and You can get the gradeColumn id using (you need the course_id): @@ -268,7 +268,7 @@ Specifies a start and end dates. The content becomes available during the given This endpoint needs the following data: -1. Type -> ["DateRange"], inmutable +1. Type -> ["DateRange"], immutable 2. startDate -> ISODate, Nullable 3. endDate -> ISODate, Nullable & endDate > startDate diff --git a/docs/blackboard/rest-apis/hands-on/calendar-api.md b/docs/blackboard/rest-apis/hands-on/calendar-api.md index 184ec4cd9..469b83cae 100644 --- a/docs/blackboard/rest-apis/hands-on/calendar-api.md +++ b/docs/blackboard/rest-apis/hands-on/calendar-api.md @@ -54,7 +54,7 @@ Please keep in mind that: - The course calendar must be enabled for the course GradebookColumn associate with OfficeHours. - If OfficeHours are created for a course calendar (calendarId == a course_id). - The course calendar must be enabled for course calendar items associated with GradebookColumn. -- CalendarItems of type GradebookColumn are a representation of a specific gradable item and there read-only. Modifications to GradebookColumn items performed via the GradebokColumn endpoints will be reflected in the CalentarItems endoints. +- CalendarItems of type GradebookColumn are a representation of a specific gradable item and there read-only. Modifications to GradebookColumn items performed via the GradebokColumn endpoints will be reflected in the CalentarItems endpoints. - If you want to use the `columnIds` from Gradebook Column as a calendar Item id, you can get those from `/learn/api/public/v2/courses/{courseId}/gradebook/columns/{columnId}` - _You cannot read/create calendar items when there is no calendar._ diff --git a/docs/blackboard/rest-apis/hands-on/copying-courses.md b/docs/blackboard/rest-apis/hands-on/copying-courses.md index 78a092f15..aeecd3209 100644 --- a/docs/blackboard/rest-apis/hands-on/copying-courses.md +++ b/docs/blackboard/rest-apis/hands-on/copying-courses.md @@ -13,7 +13,7 @@ author: Mark Kauffman, Mark O'Neil > > - The Learn Course Copy APIs work the same for either Original or Ultra course experiences. > - Learn Public REST APIs are documented at https;//developer.blackboard.com/portal/displayAPI/Learn -> - Information on System Administrators is not generally available via Public REST APIs, thus it is a Best Practice for Learn Administrators who are teaching or taking courses be enrolled using a non-Admininistrator Role privileged user. +> - Information on System Administrators is not generally available via Public REST APIs, thus it is a Best Practice for Learn Administrators who are teaching or taking courses be enrolled using a non-Administrator Role privileged user. ## Topic @@ -26,7 +26,7 @@ We strongly recommended you follow the Best Practices outlined below. Details follow below but in general, the workflow for copying a course consists of: 1. POST to the course copy endpoint. -2. Poll via GET to the Location task endpiont that was returned in the header of the course copy response. Wait for a response other than 200. This is so that when you attempt to update the copied course with step #3 that the copy has completed. +2. Poll via GET to the Location task endpoint that was returned in the header of the course copy response. Wait for a response other than 200. This is so that when you attempt to update the copied course with step #3 that the copy has completed. 3. PATCH to update the copied course's externaId, name, description, dates, and any other values that are to be different for the copied course. Any of these values are optional to update, but the copied course won't look any different to the instructor as the copied course is an EXACT copy of the source course except for the courseId. DO NOT POST to UPDATE THE COPIED COURSE UNTIL CERTAIN THE COPY IS COMPLETE VIA STEP #2 ABOVE. diff --git a/docs/blackboard/rest-apis/hands-on/gradebook.md b/docs/blackboard/rest-apis/hands-on/gradebook.md index 8651e78a3..6baaad914 100644 --- a/docs/blackboard/rest-apis/hands-on/gradebook.md +++ b/docs/blackboard/rest-apis/hands-on/gradebook.md @@ -13,7 +13,7 @@ author: Mark O'Neil > > - All Learn Gradebook APIs work the same for either Original or Ultra course experiences. > - Learn Public REST APIs are documented at https;//developer.blackboard.com/portal/displayAPI/Learn -> - Information on System Administrators is not generally available via Public REST APIs, thus it is a Best Practice for Learn Administrators who are teaching or taking courses be enrolled using a non-Admininistrator Role privileged user. +> - Information on System Administrators is not generally available via Public REST APIs, thus it is a Best Practice for Learn Administrators who are teaching or taking courses be enrolled using a non-Administrator Role privileged user. ## Topic @@ -246,7 +246,7 @@ If membership has `childCourseId` then that user is a member of a child course, You now may handle the remaining processing workflow for this user’s assignment grade. -## Calulating API Use +## Calculating API Use Using the above we can calculate API usage. Let’s keep the math simple by assuming we have 10 courses, 10 columns per course, 10 students per course and every time we check there are grades to pull for every column\*: diff --git a/docs/blackboard/sis/sis-password-hashes.md b/docs/blackboard/sis/sis-password-hashes.md index 24162fe8a..35726d31f 100644 --- a/docs/blackboard/sis/sis-password-hashes.md +++ b/docs/blackboard/sis/sis-password-hashes.md @@ -64,7 +64,7 @@ Therefore, the hashes generated by `slappasswd(8)` cannot be used. ### Algorithm Description -1. For each password: create 8 random bytes of 'salt'. Never re-use salts. Use a Cryptographically Secure Psuedo-Random +1. For each password: create 8 random bytes of 'salt'. Never re-use salts. Use a Cryptographically Secure Pseudo-Random Number Generator, or a true environmentally sourced random-number generator. 2. Convert the password string to a byte array using UTF-8. 3. Digest the concatenation of the password bytes + the salt bytes as SHA-1. The SHA-1 digest must be a byte array diff --git a/docs/blackboard/uef/Start Developing for UEF/04-authenticating-to-uef.md b/docs/blackboard/uef/Start Developing for UEF/04-authenticating-to-uef.md index d985fd2c4..9714d5b79 100644 --- a/docs/blackboard/uef/Start Developing for UEF/04-authenticating-to-uef.md +++ b/docs/blackboard/uef/Start Developing for UEF/04-authenticating-to-uef.md @@ -28,7 +28,7 @@ window.parent.postMessage( ); ``` -You also need to register an Event Listener for messages, which will allow you to listen for the initial syncronization message from Ultra. The listener can be defined like this: +You also need to register an Event Listener for messages, which will allow you to listen for the initial synchronization message from Ultra. The listener can be defined like this: ```javascript addEventListener("message", (incomingMessage) => { diff --git a/docs/blackboard/uef/Start Developing for UEF/Tutorials/05-tutorials-course-leftnav.md b/docs/blackboard/uef/Start Developing for UEF/Tutorials/05-tutorials-course-leftnav.md index 59489b28d..56e24581a 100644 --- a/docs/blackboard/uef/Start Developing for UEF/Tutorials/05-tutorials-course-leftnav.md +++ b/docs/blackboard/uef/Start Developing for UEF/Tutorials/05-tutorials-course-leftnav.md @@ -85,7 +85,7 @@ if (message.data.type === "portal:callback") { } ``` -5. Our openPanelCD fuction posts a message to Ultra to open a new panel. We'll have this panel opening make the LTI launch and display the response. +5. Our openPanelCD function posts a message to Ultra to open a new panel. We'll have this panel opening make the LTI launch and display the response. ```js // COURSE-LEFTNAV tell Ultra to open our panel. It will send us a message back after @@ -113,7 +113,7 @@ function openPanelCD(panelSize, data) { ```js function renderPanelContents(message) { ... for brevity - // You MUST change the handle: value to match that of your LTI managed placment handle. + // You MUST change the handle: value to match that of your LTI managed placement handle. // In summary the panel got opened so we put the contents of an LTI launch within. if (message.data.correlationId === 'panel-3') { diff --git a/docs/developer-portal/creating-and-managing-groups.md b/docs/developer-portal/creating-and-managing-groups.md index 3a68bac42..ec5580a27 100644 --- a/docs/developer-portal/creating-and-managing-groups.md +++ b/docs/developer-portal/creating-and-managing-groups.md @@ -33,7 +33,7 @@ You can create groups for individual and team development. You can target a spec 4. **Add a new developer to the group.** Add a developer to a group using the developer's email address. -5. **Change the administrator status.** You can give administrator privileges to exisiting group members. An administrator is empowered to: +5. **Change the administrator status.** You can give administrator privileges to existing group members. An administrator is empowered to: - Add new developers to the group - Edit, Delete or manage keys of the application. - Manage placements and see which schools have the application deployed. diff --git a/docs/developer-portal/creating-rest-or-lti-application.md b/docs/developer-portal/creating-rest-or-lti-application.md index 91e31a8bd..9e64d6e92 100644 --- a/docs/developer-portal/creating-rest-or-lti-application.md +++ b/docs/developer-portal/creating-rest-or-lti-application.md @@ -119,7 +119,7 @@ Here you will be able to: 4. **Delete your application.** This removes your application. This is a one-way operation and cannot be undone. -5. **Manage your keys.** You can create new keys (keys and secrets), but the application keeps the same application ID. This can be used when you want to rotate your keys or make an old key and secret unusuable. You may never need to create additional keys. When you select **+**, it will generate new values that will be shown only once. Document and store them in a safe place because Blackboard is unable to retrieve this data. +5. **Manage your keys.** You can create new keys (keys and secrets), but the application keeps the same application ID. This can be used when you want to rotate your keys or make an old key and secret unusable. You may never need to create additional keys. When you select **+**, it will generate new values that will be shown only once. Document and store them in a safe place because Blackboard is unable to retrieve this data. ![Manage keys](/assets/img/create-rest-or-lti-app-8.png) diff --git a/docs/student/best-practices/DeterminingAccountBalances.md b/docs/student/best-practices/DeterminingAccountBalances.md index f74d989e1..47243ab0a 100644 --- a/docs/student/best-practices/DeterminingAccountBalances.md +++ b/docs/student/best-practices/DeterminingAccountBalances.md @@ -63,7 +63,7 @@ The authorization model for the odata endpoint is to either grant permission to ![AccountBalances](/assets/img/AccountBalances3.png) -All of the odata query model operations are named as follows: domain + entity name (singluar) + query. So to authorize the permission to retrieve data from the BillingCodeTransaction entity, the StudentAccounts.BillingTransactionCode.Query operation would need to be added for the user. +All of the odata query model operations are named as follows: domain + entity name (singular) + query. So to authorize the permission to retrieve data from the BillingCodeTransaction entity, the StudentAccounts.BillingTransactionCode.Query operation would need to be added for the user. ![AccountBalances](/assets/img/AccountBalances4.png) diff --git a/docs/student/best-practices/ManageClassSections.md b/docs/student/best-practices/ManageClassSections.md index c7adf2e32..8bd3af766 100644 --- a/docs/student/best-practices/ManageClassSections.md +++ b/docs/student/best-practices/ManageClassSections.md @@ -37,7 +37,7 @@ The entities listed below will hold data related to class section meeting schedu ClassSectionMeetingPattern - This entity will hold one row for each recurring meeting pattern that is specified for a class section. When choosing a meeting pattern, the user can either select from a pre-configured meeting pattern (ds/odata/MeetingPatterns) or create one on the fly. If selected from one of the configured meeting patterns, then the MeetingPatternId property will store the Id of the MeetingPattern row that was selected. The value of the Type property will be 'L'. If a meeting pattern is entered on the fly, then the MeetingPatternId property will store the Id of the ClassSectionCustomMeetingPattern row that stores the summary data of the meeting pattern entered (see below). The value of the Type property will be 'D'. IMPORTANT NOTE: There are two navigation properties defined that both use the MeetingPatternId property. The MeetingPattern navigation property expands to the MeetingPattern entity. The CustomMeetingPattern navigation property expands to the ClassSectionCustomMeetingPattern entity. In order to retrieve expected result sets, you MUST use a filter on the Type property. When utilizing the MeetingPattern navigation property, you need to filter on rows where Type equals 'L'. When utilizing the CustomMeetingPattern navigation property you need to filter on rows where Type equals 'D'. -MeetingPattern, ClassSectionCustomMeetingPattern - these entities store meta data for the recurring meeting pattern. Days of week meetings will be on, when does recurring meeting pattern start relative to class section start date, duration of recurring meeting pattern etc. As discussed above, the pre-configured meeting patterns will be stored in the MeetingPattern entity. Recurring meeting patterns created on the fly while building out a class section will be stored in the ClassSectionCustomMeetinPattern entity. +MeetingPattern, ClassSectionCustomMeetingPattern - these entities store meta data for the recurring meeting pattern. Days of week meetings will be on, when does recurring meeting pattern start relative to class section start date, duration of recurring meeting pattern etc. As discussed above, the pre-configured meeting patterns will be stored in the MeetingPattern entity. Recurring meeting patterns created on the fly while building out a class section will be stored in the ClassSectionCustomMeetingPattern entity. ClassSectionMeetingSchedule - This entity will hold one row for each day of the week specified in each of the recurring meeting patterns configured for the class section. This is the entity that stores the detail of each recurring meeting such as Instructor, Length of meeting, start/end time of meeting, location of meeting and day of week that the meeting occurs on. The DayOfWeek property specifies which day of the week the recurring meeting will occur. This is an Enum with the following values: 1=Sunday, 2=Monday, 3=Tuesday, 4=Wednesday, 5=Thursday, 6=Friday, 7=Saturday @@ -137,7 +137,7 @@ This endpoint should be used for updating any aspect of the meeting schedule for - Id - if the recurring meeting pattern is a pre-configured meeting pattern, then set this to the Id of the MeetingPattern entity instance being used. If a new recurring meeting pattern is being created, then set to 0. If an existing meeting pattern is being updated that was not created from a pre-configured meeting pattern, then set to the Id value of the ClassSectionCustomMeetingPatternEntity that is being updated - MeetingLength - set to the duration of the scheduled meeting in minutes - PatternType - W= Weekly, M= Monthly - - Frequency - set to frequency of pattern type. For example, if pattern type is Weekly and recurring pattern is the same every week, then Frequency would be set to 1. If recurring pattern is every other week, then Frequeny would be 2. + - Frequency - set to frequency of pattern type. For example, if pattern type is Weekly and recurring pattern is the same every week, then Frequency would be set to 1. If recurring pattern is every other week, then Frequency would be 2. - RecurrenceStartWeeks - if recurring meeting pattern will start sometime AFTER the class section begins meeting, then specify the number of weeks after the start of the class section when the recurring meeting pattern will begin. If the meeting pattern begins when the class section starts, then set this value to 0. - RecurrenceEndNumber - if recurring meeting pattern will occur only a set number of times and not carry through to the end date of the class section, then set this value to the number of times it will occur. Otherwise, set to 0. diff --git a/docs/student/best-practices/ManageCustomFields.md b/docs/student/best-practices/ManageCustomFields.md index 93be011ca..f96d53627 100644 --- a/docs/student/best-practices/ManageCustomFields.md +++ b/docs/student/best-practices/ManageCustomFields.md @@ -31,7 +31,7 @@ If there is a value being specified for a school defined field for the first tim School Defined fields data is stored in the StudentSchoolDefinedFieldValues entity. To retrieve all school defined field values for a given student, a filter on the StudentId property would be used: ds/odata/StudentSchoolDefinedFieldValues?$filter=StudentId eq ####### where ####### is the Id of the Student to retrieve data for. -If data for specific school defined fields is needed, then additional filtering would be done. There is a navigation property called SchoolDefinedField on the StudentSchoolDefinedFieldValues entity that expands to the school defined fields configuration entity (SchoolDefinedFields) which can be leveraged to include any additional filtering neded for retrieving the school defined field values. +If data for specific school defined fields is needed, then additional filtering would be done. There is a navigation property called SchoolDefinedField on the StudentSchoolDefinedFieldValues entity that expands to the school defined fields configuration entity (SchoolDefinedFields) which can be leveraged to include any additional filtering needed for retrieving the school defined field values. Lastly, there is a navigation property on the Student entity called SchoolDefinedFieldValues. You can include this in an expand statement to retrieve school defined field values data. i.e. ds/odata/Students?$expand=SchoolDefinedFieldValues diff --git a/docs/student/best-practices/PaymentVendorPartnerOverview.md b/docs/student/best-practices/PaymentVendorPartnerOverview.md index deb1f6561..a36ea68e0 100644 --- a/docs/student/best-practices/PaymentVendorPartnerOverview.md +++ b/docs/student/best-practices/PaymentVendorPartnerOverview.md @@ -31,7 +31,7 @@ To see additional details for the APIs within Student, access the Swagger output ### Post Payment -The most basic use case for an integration between a payment provider and Student (Ellucian) is to be able to process a payment within the payment vendor application and then post that payment to the student's ledger card within Student (Ellucian). At a high level, there are two different kinds of payments within the Student application. The first is a payment that is not associated with expected funding and the second is a payment that is associated to an expected disbursement. One of the features in Student is the ability to package a student for Financial Aid which results in a list of scheduled disbursements being created. Included in this are Student payment plans. A student payment plan will have 1 or more expected payments/installments created as part of the payment plan data. When posting a payment that is made against a payment plan, the payment will be associated with the expected disbursement record. Regardless of whether the payment being posted is for an expected disbursement or is not associated to an expected disbursement, the same API endpoint will be used. There are properies in the request payload that informs the API if the payment being posted is associated to an expected disbursement record or is not associated to an expected disbursement record. +The most basic use case for an integration between a payment provider and Student (Ellucian) is to be able to process a payment within the payment vendor application and then post that payment to the student's ledger card within Student (Ellucian). At a high level, there are two different kinds of payments within the Student application. The first is a payment that is not associated with expected funding and the second is a payment that is associated to an expected disbursement. One of the features in Student is the ability to package a student for Financial Aid which results in a list of scheduled disbursements being created. Included in this are Student payment plans. A student payment plan will have 1 or more expected payments/installments created as part of the payment plan data. When posting a payment that is made against a payment plan, the payment will be associated with the expected disbursement record. Regardless of whether the payment being posted is for an expected disbursement or is not associated to an expected disbursement, the same API endpoint will be used. There are properties in the request payload that informs the API if the payment being posted is associated to an expected disbursement record or is not associated to an expected disbursement record. The API to use for posting payments is POST api/student-accounting/ledger-payment-transactions @@ -111,7 +111,7 @@ Many Payment providers have a capability for processing refunds that are schedul #### Retrieve scheduled refunds -The first step is to retrieve the scheduled refunds that need to be processed. The best way to do this is to constuct an odata query to retrieve the needed information. The scheduled refunds will reside in the Refunds entity. One of the filters needed in the query will be on the Status property. A value of 'N' in the Status property indicates that the refund is scheduled but has not yet been processed/paid. Other valid values for this property are P= Processed/Paid, V= Processed but has since been Voided and S= Selected for Processing. The other key filters needed in the OData query will be on the DueDate property which indicates the date that the refund is due. Also, there will likely need to be filtering based on the fund source the refund is for. In many cases, refunds that are being returned to Title IV fund sources are not processed by Payment providers. The StudentAward navigation property on the Refunds entity will need to be utilized to construct the filtering condition needed to filter on the fund source(s) that should be included. +The first step is to retrieve the scheduled refunds that need to be processed. The best way to do this is to construct an odata query to retrieve the needed information. The scheduled refunds will reside in the Refunds entity. One of the filters needed in the query will be on the Status property. A value of 'N' in the Status property indicates that the refund is scheduled but has not yet been processed/paid. Other valid values for this property are P= Processed/Paid, V= Processed but has since been Voided and S= Selected for Processing. The other key filters needed in the OData query will be on the DueDate property which indicates the date that the refund is due. Also, there will likely need to be filtering based on the fund source the refund is for. In many cases, refunds that are being returned to Title IV fund sources are not processed by Payment providers. The StudentAward navigation property on the Refunds entity will need to be utilized to construct the filtering condition needed to filter on the fund source(s) that should be included. #### Flag the selected refund records @@ -181,7 +181,7 @@ For any OData queries that will be executed, additional authorization is needed. ![PaymentVendorPartnerOverview](/assets/img/PaymentVendorPartnerOverview13.png) -All of the odata query model operations are named as follows: domain + entity name (singluar) + query. So to authorize the permission to retrieve data from the BillingCodeTransaction entity, the StudentAccounts.BillingTransactionCode.Query operation would need to be added for the user. +All of the odata query model operations are named as follows: domain + entity name (singular) + query. So to authorize the permission to retrieve data from the BillingCodeTransaction entity, the StudentAccounts.BillingTransactionCode.Query operation would need to be added for the user. ![PaymentVendorPartnerOverview](/assets/img/PaymentVendorPartnerOverview14.png) diff --git a/docs/student/best-practices/SaveStudentTransferCredit .md b/docs/student/best-practices/SaveStudentTransferCredit .md index 4988a5d64..34452ee9a 100644 --- a/docs/student/best-practices/SaveStudentTransferCredit .md +++ b/docs/student/best-practices/SaveStudentTransferCredit .md @@ -105,7 +105,7 @@ An example payload for this API is below. In the example, there is 1 external courses taken that is satisfying the requirements for 1 internal course. -The TransferCreditStatusId property value will determine if the student's degree progress audit and transcript data will be updated when the API executes. The Transfer Credit Status table is reference data that is configured by the instituion. Any number of statuses can be configured that can be used to track the transfer credit process (i.e. Transfer credits are submitted, transfer credits are being reviewed, transfer credit is approved etc.). Each row in the Transfer Credit Status reference data entity has a boolean property called IsApproved. If the IsApproved attribute is true for the TransferCreditStatusId property value specified in the request, then the execution logic will perform the needed updates so that there is a Transfer grade recorded for the internal course Id provided and also update the degree progress audit data so that the requirement of taking the internal course Id shows as Fulfilled when generating the students Degree Progress Audit. +The TransferCreditStatusId property value will determine if the student's degree progress audit and transcript data will be updated when the API executes. The Transfer Credit Status table is reference data that is configured by the institution. Any number of statuses can be configured that can be used to track the transfer credit process (i.e. Transfer credits are submitted, transfer credits are being reviewed, transfer credit is approved etc.). Each row in the Transfer Credit Status reference data entity has a boolean property called IsApproved. If the IsApproved attribute is true for the TransferCreditStatusId property value specified in the request, then the execution logic will perform the needed updates so that there is a Transfer grade recorded for the internal course Id provided and also update the degree progress audit data so that the requirement of taking the internal course Id shows as Fulfilled when generating the students Degree Progress Audit. ## Additional notes: