# LTI 1.3 Proctoring Services

Endpoint is an LTI 1.3 Tool. Your assessment platform or LMS is the Platform. This page documents the full LTI Proctoring Services integration: launch, candidate check-in, Start Assessment, End Assessment, ACS flags, AGS score evidence, and fallback disarm.

## What this integration covers

- Your platform launches Endpoint with `LtiStartProctoring`.
- Endpoint opens candidate check-in in a top-level browser window.
- After check-in, Endpoint signs `LtiStartAssessment` back to your `start_assessment_url`.
- Your platform sends `LtiEndAssessment` when the attempt ends.
- Endpoint sends ACS `flag` calls for durable violations and posts AGS score evidence.

If you only need server-to-server session creation, use [REST integration](/docs/proctoring/rest-integration). If you need LTI Core placement rather than LTI Proctoring Services, see the limited note at the end of this page.

## Endpoints

Production host: `https://app.endpoint.solutions`

| Purpose | Method | Path |
|---|---|---|
| OIDC login initiation | `GET` or `POST` | `/lti/login` |
| Proctoring launch | `POST` | `/lti/launch` |
| JWKS | `GET` | `/.well-known/jwks.json` |
| End Assessment | `POST` | `/lti/end_assessment` |

The root-level paths also have namespaced aliases under `/proctoring/api/v1/lti/`. Register the short paths above unless we agree otherwise.

## OIDC launch flow

```
1. Platform -> Endpoint /lti/login
   iss, client_id, login_hint, lti_message_hint, target_link_uri

2. Endpoint -> Platform authorize URL
   scope=openid
   response_type=id_token
   response_mode=form_post
   prompt=none
   client_id=<registered client_id>
   redirect_uri=<registered launch URL>
   login_hint=<from step 1>
   lti_message_hint=<from step 1>
   state=<single-use>
   nonce=<single-use>

3. Platform -> Endpoint launch URL
   id_token=<signed JWT>
   state=<state from step 2>

4. Endpoint creates or resumes the proctoring session and opens check-in.
```

`redirect_uri` always comes from the Endpoint registration record. It is not copied from inbound `target_link_uri`.

`state` and `nonce` are single-use and expire 10 minutes after login initiation. A retry must start a new OIDC launch; replaying the old `id_token` is rejected.

Check-in opens in a top-level browser window because camera, screen capture, extension permissions, and third-party cookie behavior are unreliable inside an LMS iframe.

## What we validate

Inbound launch JWTs are validated before any session is created. Invalid tokens receive a generic rejection; details are logged server-side.

| Check | Applied to |
|---|---|
| Header `alg` is exactly `RS256` | All inbound LTI JWTs |
| Active registration resolves for `(iss, client_id)` | All |
| Signature verifies against the platform JWKS key selected by `kid` | All |
| `iss` equals the registered issuer | All |
| `aud` contains our client ID; `azp` must match when required | All |
| `deployment_id` matches | Launch |
| `iat` is present and not more than 60 seconds in the future; if `exp` is present, it must be in the future | All |
| `state` and `nonce` match an unexpired, unconsumed login | Launch |
| LTI version is `1.3.0` | Launch |
| `message_type` is accepted by the endpoint | All |
| `resource_link.id` is present | Resource link launches |
| `target_link_uri` equals the registered launch URL | Launch |

Provisioning then requires:

| Requirement | Status |
|---|---|
| `email` claim | Required |
| `sub` claim | Required |
| `session_data` claim | Required |
| Valid `proctoring_settings` if present | Required |

A malformed per-launch policy fails closed with `422`; see [Proctoring settings](/docs/proctoring/proctoring-settings).

## Proctoring launch

Launch with `LtiStartProctoring`. The launch must include:

- `email` and `sub`.
- `https://purl.imsglobal.org/spec/lti-ap/claim/session_data`.
- `https://purl.imsglobal.org/spec/lti-ap/claim/start_assessment_url`.
- Standard LTI 1.3 launch claims, including `deployment_id`, `resource_link`, version, and target link URI.
- Optional Endpoint policy in the standard `proctoring_settings` claim.

`start_assessment_url` must be `https` and on the same host as your issuer. We reject a launch that points it elsewhere.

### Start Assessment post-back

After check-in passes, the candidate browser form-posts a JWT signed by Endpoint to your `start_assessment_url`. Verify it with our JWKS and redirect the candidate into the exam.

The JWT includes standard claims plus:

| Claim | Meaning |
|---|---|
| `message_type` | `LtiStartAssessment` |
| `session_data` | Your attempt key, echoed back |
| `end_assessment_return` | `true`; asks you to send `LtiEndAssessment` when the exam ends |
| `id_verified` | `true` only when Endpoint actually verified identity |
| `id_type` | Document type read, or `null` |
| `name_matched` | `true`, `false`, or `null` when not checked |
| `checked_at` | ISO 8601 timestamp, or `null` |
| `policy` | `required` or `skip` |

A candidate who fails identity verification does not reach this post-back.

### ACS and AGS

LTI Proctoring Services sessions send:

| Service | Scope | Current use |
|---|---|---|
| Assessment Control Service | `https://purl.imsglobal.org/spec/lti-ap/scope/control.all` | `flag` for durable violations and failed identity checks |
| AGS line item | `https://purl.imsglobal.org/spec/lti-ags/scope/lineitem` | Create or update the proctoring line item |
| AGS score | `https://purl.imsglobal.org/spec/lti-ags/scope/score` | Post the compliance score as evidence |

Server-to-server service calls use OAuth 2.0 client credentials with a `private_key_jwt` client assertion signed by Endpoint. We request only scopes granted on the registration.

Endpoint does not send ACS `pause`, `resume`, or `terminate`. We flag; your platform decides.

ACS maps Endpoint severities as `low`/`medium` -> `minor` and `high`/`critical` -> `major`. Use the ACS `event_id` as your deduplication key.

### End Assessment

Send `LtiEndAssessment` to `POST /lti/end_assessment` when the attempt stops for any reason: submit, timeout, abandonment, or your own termination. Form-post the signed JWT as `JWT` or `jwt`.

We require `iss`, `aud`, `iat`, `message_type`, and `session_data`. If the JWT includes `exp`, it must be in the future. Repeat deliveries for the same `session_data` are no-ops. Unknown `session_data` also returns success because there is nothing useful to retry. A bad signature is rejected and monitoring stays armed.

If no End Assessment arrives, Endpoint has an independent fallback disarm window: exam duration plus 30 minutes, or 4 hours when no duration is known, measured from exam start when available. This exists to avoid indefinite recording; do not rely on it as your normal stop signal.

## JWKS

`GET https://app.endpoint.solutions/.well-known/jwks.json`

The response is a JSON Web Key Set containing public `RS256` signing keys. Cache it for up to 1 hour. Multiple keys can be present during rotation; always select by `kid`.

## Registration checklist

Give Endpoint:

- Issuer (`iss`), `client_id`, and `deployment_id`.
- Platform JWKS URL.
- OIDC authorize URL.
- Token URL and granted scopes.
- Registration type: `proctoring_services`.
- Exam hostnames where the extension may arm.

Endpoint gives you:

- OIDC login URL: `https://app.endpoint.solutions/lti/login`.
- Redirect URI and target link URI: `https://app.endpoint.solutions/lti/launch`.
- JWKS URL: `https://app.endpoint.solutions/.well-known/jwks.json`.
- End Assessment URL: `https://app.endpoint.solutions/lti/end_assessment`.

Exam hostnames are required. The extension arms only on registered hosts. Hosts are matched exactly, lowercased, without scheme or port; wildcards are not expanded.

Before launch, verify:

- OIDC launch reaches Endpoint and opens candidate check-in.
- Launch JWT includes `email` and `sub`.
- Launch includes `session_data` and a trusted `start_assessment_url`.
- Your platform verifies Endpoint's Start Assessment JWT against our JWKS.
- Your platform sends `LtiEndAssessment` on submit, timeout, and termination.
- The real exam host is registered and the extension arms there.

## Limited LTI Core launch support

Endpoint also has a separate `/proctoring/api/v1/lti/core_launch` endpoint for LMS placement work:

| Message | Current behavior |
|---|---|
| `LtiResourceLinkRequest` | Creates or resumes a proctoring session and opens check-in. Requires `email`, `sub`, and `resource_link.id`; does not require `session_data`. |
| `LtiDeepLinkingRequest` | Returns a signed `LtiDeepLinkingResponse` with one `ltiResourceLink` content item. No proctoring session is created during placement. |

Use that endpoint only when we are setting up an LMS Core placement. It is not the full LTI Proctoring Services integration, and it does not currently provide ACS flags, AGS score posting, End Assessment handling, artifact registration, or fallback disarm.

## Related

- [Overview](/docs/proctoring/overview)
- [Proctoring settings](/docs/proctoring/proctoring-settings)
- [Webhooks and events](/docs/proctoring/webhooks-and-events)
- [REST integration](/docs/proctoring/rest-integration)

_Last verified: 2026-09-03 against main._
