Skip to content

LTI Partner Provisioning

How to register Humans But Guided as an LTI 1.3 tool on a partner's Canvas instance. Covers both the automated API path (preferred) and the manual UI path.


What we give partners

Before they start, share these values with the partner Canvas admin:

Our endpointValue
OIDC Initiation URLhttps://api.humansbutguided.com/api/lti/oidc-login
Redirect URI (Launch URL)https://api.humansbutguided.com/api/lti/launch
JWK Set URLhttps://api.humansbutguided.com/api/lti/jwks
Target Link URIhttps://api.humansbutguided.com/api/lti/launch

What they give us

After they create the key, we need:

FieldWhere they find it
Canvas base URLe.g. https://canvas.partner.edu
client_idShown on the Developer Key row after creation
deployment_idFrom the installed tool — see finding deployment_id

Option A — Automated via Canvas REST API (preferred)

Partners can create the developer key without touching the UI. A Canvas admin with an API token runs:

bash
CANVAS_URL="https://canvas.partner.edu"
CANVAS_TOKEN="<their_admin_api_token>"
ACCOUNT_ID="1"   # usually 1 for the root account

curl -s -X POST "$CANVAS_URL/api/v1/accounts/$ACCOUNT_ID/developer_keys" \
  -H "Authorization: Bearer $CANVAS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "developer_key": {
      "name": "Grading Students",
      "email": "lti@humansbutguided.com",
      "redirect_uris": "https://api.humansbutguided.com/api/lti/launch",
      "tool_configuration": {
        "settings": {
          "title": "Grading Students",
          "description": "AI-assisted homework grading",
          "target_link_uri": "https://api.humansbutguided.com/api/lti/launch",
          "oidc_initiation_url": "https://api.humansbutguided.com/api/lti/oidc-login",
          "public_jwk_url": "https://api.humansbutguided.com/api/lti/jwks",
          "scopes": [
            "https://purl.imsglobal.org/spec/lti-ags/scope/lineitem",
            "https://purl.imsglobal.org/spec/lti-ags/scope/score",
            "https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly"
          ],
          "extensions": [{
            "platform": "canvas.instructure.com",
            "settings": {
              "placements": [{
                "placement": "assignment_selection",
                "message_type": "LtiResourceLinkRequest",
                "target_link_uri": "https://api.humansbutguided.com/api/lti/launch",
                "text": "Grading Students"
              }, {
                "placement": "homework_submission",
                "message_type": "LtiResourceLinkRequest",
                "target_link_uri": "https://api.humansbutguided.com/api/lti/launch",
                "text": "Grading Students"
              }]
            }
          }]
        }
      }
    }
  }'

The response JSON contains "id" — that is the internal developer key ID. The global client_id (used in LTI launches) is different; read it from Canvas after creation.

Then enable the key on the account:

bash
KEY_ID="<id from above>"

curl -s -X PUT "$CANVAS_URL/api/v1/accounts/$ACCOUNT_ID/developer_keys/${KEY_ID}/developer_key_account_bindings" \
  -H "Authorization: Bearer $CANVAS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"developer_key_account_binding": {"workflow_state": "on"}}'

Set OIDC initiation URL on the Developer Key

Canvas uses DeveloperKey.oidc_initiation_url when building assignment launch forms. Tool configuration JSON alone is not enough — if this column is empty, launches fail with Missing state param on HBG.

ruby
key = DeveloperKey.find(<KEY_ID>)
key.update!(oidc_initiation_url: "https://api.humansbutguided.com/api/lti/oidc-login")
puts key.global_id  # this is the client_id for LTI

Install the app by Client ID

Creating a developer key does not install the tool in courses. Install at account and course level:

bash
CLIENT_ID="<global_id from above>"
COURSE_ID="<course_id>"

curl -sS -X POST "$CANVAS_URL/api/v1/accounts/$ACCOUNT_ID/external_tools" \
  -H "Authorization: Bearer $CANVAS_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"client_id\":\"$CLIENT_ID\"}"

curl -sS -X POST "$CANVAS_URL/api/v1/courses/$COURSE_ID/external_tools" \
  -H "Authorization: Bearer $CANVAS_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"client_id\":\"$CLIENT_ID\"}"

Without this step, assignments show "Couldn't find valid settings for this link".

public_jwk_url (a URL Canvas fetches at launch time) is preferred over pasting the raw JWK, so key rotation doesn't require re-provisioning.


Finding deployment_id

After installing the app, read the deployment ID Canvas will send in launch tokens:

ruby
ContextExternalTool.find_by(name: "Grading Students").deployment_id

Register it on HBG:

bash
cd backend
python scripts/seed_lti_platform.py \
  --canvas-url "$CANVAS_URL" \
  --client-id "$CLIENT_ID" \
  --deployment-id "<deployment_id from above>"

Option B — Manual Canvas UI

For partners who prefer the UI:

See Canvas admin setup for a screenshot walkthrough.

Summary:

  1. Admin → Developer Keys → + Developer Key+ LTI Key
  2. Fill Key Settings (left panel):
FieldValue
Key NameGrading Students
Owner Emaillti@humansbutguided.com
Redirect URIshttps://api.humansbutguided.com/api/lti/launch
  1. Fill Configure (right panel), Method = Manual Entry:
FieldValue
TitleGrading Students
DescriptionAI-assisted homework grading
Target Link URIhttps://api.humansbutguided.com/api/lti/launch
OpenID Connect Initiation URLhttps://api.humansbutguided.com/api/lti/oidc-login
JWK MethodPublic JWK URLhttps://api.humansbutguided.com/api/lti/jwks
  1. LTI Advantage Services — enable all four gradebook scopes.
  2. Placements — remove defaults; add Assignment Selection and Homework Submission with message type LtiResourceLinkRequest.
  3. Save → toggle key ONinstall by Client ID → share client_id and deployment_id with HBG.

Verification checklist

After provisioning, confirm:

bash
# 1. HBG tool JWKS (RSA, alg=RS256)
curl -s https://api.humansbutguided.com/api/lti/jwks | jq '.keys[0] | {kty,alg,use,kid}'

# 2. OIDC login redirects to Canvas (302)
curl -sS -D - -o /dev/null -X POST "https://api.humansbutguided.com/api/lti/oidc-login" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "iss=${CANVAS_URL}&login_hint=1&target_link_uri=https://api.humansbutguided.com/api/lti/launch&client_id=${CLIENT_ID}"

Then open an External Tool assignment as a student. The HBG workspace should match Outcome after integration.

If anything fails, see LTI troubleshooting.

For the self-hosted demo stack (canvas-demo.humansbutguided.com), also complete LTI signing keys in the grading-students repo.