For Developers

The Deep Linking Workflow

This page strictly applies to LTI 1.3 based integrations. If you are looking for how to send assignments or grades to the LMS more generally, please visit this guide instead.

The LTI deep linking flow represents a pretty significant deviation from the way Edlink normally handles the assignment creation process. The most obvious difference is that "push" assignments or coursework into the LMS with an LTI-based connection. Instead, the LMS must "pull" resources from the curriculum platform into its own system.

Even though it is possible to "push" grades into the LMS via what the LTI spec calls "Assignment & Grade Services" (AGS), this process typically only creates a column in the gradebook for a given resource - it doesn't create the resource itself. For example, you can inform Canvas (e.g.) that a gradeable item exists and that it is worth 10 points, but you cannot provide Canvas an LTI launch link that points to your resource.

This limitation requires that we provide support for the LTI deep linking flow. The deep linking flow is the only way to get coursework into the LMS when using an LTI 1.3-based integration.

The Deep Linking Flow

  1. The user signs into their LMS, selects a course, and clicks "Create Assignment" (or similar).
  2. The user indicates to the LMS that they want to create an assignment that is connected to a piece of external content (i.e. from your platform).
  3. The LMS opens an iframe window in a modal above the assignment creation screen.
  4. The iframe LTI launches into Edlink.
  5. Edlink silently processes the login and forwards the user down the chain to your primary redirect URI (via our typical OAuth 2.0 flow).
  6. When your platform exchanges the authorization_code for an access_token and refresh_token you'll also receive an LTI context object.
  7. The context object will contain details about the user's intent (select in this case) and the class they're currently viewing.
  8. Your application should display (ideally) a lightweight UI for selecting one of their resources.
  9. After the user has made a selection, you should send their selection in a payload.
  10. Edlink will handle the payload and the LMS will close the iframe.
  11. When the teacher or students subsequently clicks on the assignment link, they will be launched into your application via our typical OAuth 2.0 flow.
  12. This time, you'll receive a slightly different context object. The intent will be assignment and it will contain the payload that you shared with Edlink in step #9.
  13. You should display the correct resource to the user.
  14. If your platform produces submissions or grades, you can send them to Edlink via our normal API endpoints (this process is not LTI-specific).

The Initial LTI Launch

When a user wants to select a piece of content from your platform, the LMS opens up an iframe. Typically, this iframe would point to your LTI launch URL, but since LTI is abstracted by Edlink, the LMS opens up the page to Edlink's LTI launch URL. Edlink processes the launch, captures the launch context, and forwards the user to your primary redirect_uri (the first one on the list on your application settings page).

This launch will come through to your application as a standard OAuth 2.0 launch (as described elsewhere in the docs). When you make the POST request to exchange your temporary authorization_code for an access_token, the API response will contain some additional information - the LTI launch context.

The LTI Context Object

The LTI context object contains two key bits of information:

  • The launch intent.
  • The class that the user was viewing when they clicked a link to select a resource from your platform.

When the user is trying to select a resource from your platform for LTI Deep Linking, the intent will always be select. This is the easiest way to determine that the user wants to select an item from your platform.

It is recommended, but not required, that you consider the class object that gets returned with the OAuth reseponse. Your platform may choose to show resources available to that class, or to otherwise tailor the teacher's experience based on their class.

{
    "$data": {
        "access_token": "f7a...746",
        "refresh_token": "2cc...81d",
        "token_type": "Bearer",
        "expires_in": 3600,
        "context": {
            "version": 2,
            "intent": "select",
            "custom": {
                "custom_param_1": "custom_value_1"
            },
            "class": {
                "id": "8b78e591-ca00-4e16-9ac7-2dd9f9e460fa",
                "name": "Math 101",
                "description": null,
                "state": "active",
                "picture_url": null,
                "created_date": "2023-01-13T05:44:00.217Z",
                "updated_date": "2023-01-13T05:50:59.695Z",
                "locale": null,
                "time_zone": null,
                "school_id": "d20a4cf3-fdcc-4f21-b0fc-f2db854ff63d",
                "course_id": null,
                "session_ids": [],
                "subjects": [],
                "grade_levels": [],
                "periods": [],
                "properties": {},
                "identifiers": [],
                "materialization_id": "c696449b-f254-47fd-9249-1abc8a0beaf0",
                "rules": {},
                "product_ids": {}
            }
        }
    },
    "$request": "caf2da76-002a-4e5f-baab-6c6ff6dbdeca"
}

Resource Selection

There is no specific process for how the user should go about selecting a resource to assign. Your platform gets to control the user experience.

When the user has selected a given resource, your platform will form a "payload".

  • This payload can be any arbitrary Javascript object.
  • The payload can contain as much information as you need in order to later identify the resource that the user selected.
  • The payload should not contain the actual resource metadata (e.g. the title or description).

Once the user has selected a resource and you've constructed your payload, you are going to use window.parent.postMessage to send your payload to Edlink. For the unfamiliar, postMessage is a mechanism to send messages to outer iframes. Edlink will be waiting to receive and process your message.

Resource Payload Properties

PropertyTypeDescription
typestringMust be set to "lti".
titlestringThe lineItem resource title.
thumbnailstringURL to the lineItem resource thumbnail.
customobjectA map of key/value custom parameters.
external_idstringThe lineItem resource ID.
display_dateDateThe lineItem resource available startDateTime.
end_dateDateThe lineItem resource available endDateTime.
start_dateDateThe lineItem resource submission startDateTime.
due_dateDateThe lineItem resource submission endDateTime.

For more information on LTI resource linking for lineItems please visit the LTI Deep Linking Specification.

Sample Payload

This is an example of how to return a payload to the Edlink parent window via postMessage. The target origin must be exactly https://ed.link. Do not change this value to your own domain name or add any additional parameters.

window.parent.postMessage(
    {
        type: 'lti',
        title: 'Title of Your Attachment',
        thumbnail: 'https://thubmnail.url',
        custom: {
            my_custom_property_1: 'my_custom_value_1',
            my_custom_property_2: 'my_custom_value_2'
        },
        external_id: '000000000000', // this will map to LTI lineItem resourceId
        display_date: '2024-09-01T07:00:00.0000Z', // this will map to LTI lineItem startDateTime
        end_date: '2024-09-05T12:00:00.0000Z', // this will map to LTI lineItem endDateTime
        start_date: '2024-09-05T12:00:00.0000Z',
        due_date: '2024-09-04T17:00:00.0000Z'
    },
    'https://ed.link'
);

Assignment Launch

After the assignment has been created by the teacher, students can access it via their LMS. There is no notification to your platform that the assignment has been created successfully in the LMS prior to a student or teacher launching into it. This is not a limitation of Edlink; it is a limitation of the LTI specification.

This launch will come through to your application as a standard OAuth 2.0 launch. Again, when you make the POST request to exchange your temporary authorization_code for an access_token, the API response will contain some additional context.

The LTI Context Object

The LTI context object will contain four key bits of information:

  • The launch intent (always assignment in this case).
  • The class that the user was viewing when they clicked a link to select a resource from your platform.
  • The assignment that the user is launching into.
  • The original payload that you sent to Edlink when the user first selected the resource.

There's no right answer here, but we recommend implementing a lightweight "assignment viewer" where you provide a trimmed-down version of your standard UI that displays the desired assignment in the relevant class.