# Connect an External LMS

Keep your courses where they already live, and let partners reach them from Fours without a second login.

---

## Overview

If your partner training already lives in a learning management system (LMS), such as Skilljar or another platform that supports SAML, you do not have to rebuild it in Fours. Connect the LMS once and Fours can:

- publish **external courses** that are a link into your LMS;
- sign partners in on arrival, through SAML single sign-on, so there is no second password;
- record who opened each course, and when;
- with Skilljar, read completions back, so a finished course completes in Fours on its own ([Completion sync](#completion-sync)).

Fours is the **identity provider** in this arrangement and your LMS is the service provider. Your LMS remains the authority on course content and completion.

Here's what happens when a partner opens an external course, once everything below is in place:

```d2
shape: sequence_diagram
partner: Partner
suger: Fours
lms: Your LMS
partner -> suger: "Click Open in … on a course"
suger -> suger: "Record the open"
suger -> partner: "Send the browser to the course's destination link" { style.stroke-dash: 4 }
partner -> lms: "Arrive at the course page"
signin: "If your LMS asks who this is" {
  lms -> suger: "Ask who this is (SAML)"
  suger -> lms: "Email, FirstName, LastName" { style.stroke-dash: 4 }
}
lms -> partner: "Signed in, on the course page" { style.stroke-dash: 4 }
```

Because the partner is already signed in to Fours, the SAML exchange is usually invisible — the course simply opens.

Setup is guided, and it starts with a conversation. To get started, contact your Fours representative. Self-service setup isn't available yet.

| Fours | You |
| --- | --- |
| Issues the sign-in URL, metadata URL, identity provider entity ID, and signing certificate | Configure your LMS with them ([Step 2](#step-2-configure-your-lms)) |
| — | Record both sides under **Settings → Partner → Training / LMS** ([Step 3](#step-3-record-the-values-in-fours)) |
| — | Turn single sign-on on when you're ready ([Step 4](#step-4-turn-on-single-sign-on)) |
| — | On Skilljar, optionally turn on [completion sync](#completion-sync) so finished courses come back to Fours |

## Before You Start

Check these before you pick a date:

- **Your LMS plan includes SAML single sign-on**, and you — or someone on your team — can reach its SSO settings. Some vendors offer SSO only on certain plans, or switch it on through their support team.
- **Your LMS recognizes returning learners by email address.** Fours sends each learner's email address as the SAML Name ID. If your LMS matches learners on anything else, an existing learner can end up with a second account and lose their history.
- **Your partner users have accepted their Fours invitations.** Single sign-on can only sign in people who have a Fours account.

:::warning
Single sign-on is switched on in your LMS, not in Fours. Check with whoever owns your LMS how enabling it affects the people who sign in there today, agree the timing, and rehearse on a test site first if your vendor offers one.
:::

## Configure the connection

Four steps connect the two systems. Fours handles the identity side; you configure your LMS and record both sides in Fours.

### Step 1: Request the connection

Contact your Fours representative and tell them which LMS you use. Fours sends you four values:

| Value | What your LMS may call it |
| ----- | ------------------------- |
| **Sign-in URL** | IdP SSO URL, or SSO login URL |
| **Metadata URL** | IdP metadata, or metadata XML |
| **Identity provider entity ID** | IdP entity ID, or Issuer |
| **Signing certificate** | IdP certificate, or X.509 certificate |

### Step 2: Configure your LMS

1. Open your LMS's SAML single sign-on settings and create a configuration.
2. **Import the metadata rather than pasting the certificate by hand** — from the metadata URL or its XML file, if your LMS offers that. The **Metadata URL** field in Fours gives the same advice.
3. **Map the attributes to these exact names:**

   | Attribute | What Fours sends |
   | --------- | ---------------- |
   | `Email` | The learner's email address. It is also the SAML Name ID. |
   | `FirstName` | The learner's first name in Fours. |
   | `LastName` | The learner's last name in Fours. |

   All three are required. Company and job title are not sent.

   :::warning
   After the first sign-in, check that all three attributes came through under these exact names, not just the email.
   :::

4. **Set the Name ID format to email address.** This is how your LMS recognizes a returning learner.
5. Save the configuration, then send these values from your LMS to your Fours representative:
   - Service provider entity ID
   - Assertion consumer service (ACS) URL
   - Single logout (SLO) URL

### Step 3: Record the values in Fours

1. Go to **Fours Console**, then **Settings**.
2. Click **Partner**, then **Training / LMS**.
3. Under **LMS**, choose **Skilljar** or **Other (SAML)**. Single sign-on works with either; [completion sync](#completion-sync) needs Skilljar. Optionally, enter a **Display name**, such as the name of your partner academy — this settings page uses it to label its sections. The name partners see on a course's button comes from that course's own **LMS** field — see [Publish an external course](#publish-an-external-course).
4. Under **Give these to *{your LMS}***, enter the **Sign-in URL**, **Metadata URL**, and **Identity provider entity ID** Fours sent you. Copy the entity ID exactly as the metadata shows it. **Test connection** flags a mismatch, which your LMS would otherwise reject without saying why.
5. Under **Get these from *{your LMS}***, enter the **Service provider entity ID**, **Assertion consumer service (ACS) URL**, and **Single logout (SLO) URL** from Step 2. Fours keeps them as a record of what was exchanged, so a broken connection can be diagnosed later.
6. Click **Save** at the bottom of the page.
7. Click **Test connection**. It reads the values you saved, so save first.

**Test connection** fetches the metadata from your metadata URL, which must be an `https://` address. The result reads **Metadata looks correct** or **Needs attention**, with each check listed separately:

| Check | What it confirms |
| ----- | ---------------- |
| **Reachable** | The metadata URL answered. |
| **Valid SAML metadata** | What it returned is SAML metadata. |
| **Issuer matches what is saved here** | The entity ID in the metadata is the one you saved. |
| **Email NameID offered** | The email-address Name ID format is available, so returning learners can be matched on email. |
| **Signing certificate published** | The metadata carries a signing certificate. |

The test checks the metadata only — it does not sign anyone in. If the test finds a signing certificate, **Download certificate** saves it as a `.pem` file, for an LMS that asks for the certificate on its own; until then the button stays disabled.

The tab's **What we send about each user** section lists the same three attributes as Step 2.

### Step 4: Turn on single sign-on

Do this last, once both sides are configured.

1. In **Training / LMS**, switch **External LMS single sign-on** on, then click **Save**.
2. Enable the SSO configuration in your LMS.

The switch turns the connection on in Fours. It doesn't change where a course opens: **Open in …** always sends partners to the course's destination link. [Completion sync](#completion-sync) has a switch of its own, so turning single sign-on off doesn't stop completions coming back.

## Completion sync

**Completion sync reads completions back out of your LMS, so an external course finishes in Fours on its own.** When your LMS reports that a partner finished a course, their enrollment becomes **Completed**, a journey's **Complete course** step waiting on that course ticks, and a journey that finishes this way can promote the partner's tier if it carries a tier outcome.

It works with **Skilljar**. With **Other (SAML)** selected, single sign-on and open tracking work as before, but completions can't be read.

Completions come back two ways:

| Path | How fast | What it's for |
| --- | --- | --- |
| **Completion webhook** | Seconds | Skilljar sends each completion to Fours as it happens. This is the main path. |
| **Scheduled check** | Slow | Fours asks your LMS about a few learners at a time, on a schedule, so it can take several days to come back round to everyone. It's the safety net that catches what the webhook missed. |

```d2
direction: right

finish: "A partner finishes\na course in Skilljar" { shape: rectangle }
webhook: "Completion webhook\nin seconds" { shape: rectangle }
poll: "Scheduled check\na few learners at a time" { shape: rectangle }
match: "Course, learner and\nenrollment all match?" { shape: diamond }
skipped: "Passed over:\nunmatched course, unknown\nlearner, or not enrolled" { shape: rectangle; style.stroke-dash: 3 }
completed: "Enrollment reads Completed" { shape: rectangle }
journey: "Complete course step ticks" { shape: rectangle }
tier: "A journey with a tier outcome\ncan promote the partner" { shape: rectangle }

finish -> webhook
finish -> poll
webhook -> match
poll -> match
match -> completed: "yes"
match -> skipped: "no"
completed -> journey
journey -> tier
```

### Set up completion sync

1. In **Training / LMS**, set **LMS** to **Skilljar**.
2. Switch **Completion sync** on and enter your **Training domain**, for example `courses.example.com`. Fours never guesses it: your LMS's API is scoped to one training domain while one key reaches every domain in the account, so this is what keeps the sync pointed at the right site. Click **Save** at the bottom of the page.
3. Paste an **API key** from your LMS and click the **Save** button next to the field. Create it as a **read-only** key — in Skilljar, tick **Read Only** when you generate it. Fours only ever reads from your LMS, so a full-access key would grant delete rights nothing here uses.
4. Click **Sync now** to test the setup. It runs the same check the schedule does, straight away, and reports what it did — *"Applied 3 completions."* or *"Sync ran. No new completions to apply."* — plus how many it passed over as unmatched course, unknown learner, or not enrolled. A key your LMS rejects fails here, with your LMS's own message, instead of failing quietly later.
5. [Set up the completion webhook](#set-up-the-completion-webhook).
6. Link each external course to the matching course in your LMS. See [Publish an external course](#publish-an-external-course).

The key is stored encrypted and never shown again; the field shows a **Stored** badge instead. To remove it, empty the field and click **Clear**, which switches completion sync off at the source.

If completion sync is on but something it needs is missing — Skilljar isn't selected, or no training domain is saved — a warning under the switch says which. The section also shows when Fours last checked, or **Not checked yet**.

### Set up the completion webhook

The webhook is the half Fours can't configure for you: creating it is a change in your LMS, and the key you gave Fours is read-only. Under **Completion webhook**:

1. Click **Generate secret** and copy the secret straight away. It's shown once and can't be retrieved; if you lose it, generate another and update your LMS.
2. In Skilljar, create a webhook with the **Target URL** shown on the page. Add a custom header whose name is the **Custom header name** shown on the page, with the secret as its value. Skilljar doesn't sign its webhook deliveries, so this header is what proves a delivery is genuinely yours.
3. Set the event type to `COURSE_COMPLETION`, or leave it empty to send every event — Fours ignores the ones it doesn't need.

Once a secret exists, the badge next to **Completion webhook** reads **Secret generated** instead of **Not set up**, and the button reads **Generate a new secret**. Generating a new secret immediately stops deliveries that still carry the old one, until you update Skilljar.

:::warning
**If the secret in Skilljar stops matching, Skilljar turns the webhook off permanently, without telling anyone.** Completions still arrive through the scheduled check, just slowly. If completions that used to land in seconds start taking days, check the webhook in Skilljar.
:::

### How completions are matched

A completion counts only when Fours can match all three of these. Anything it can't match is counted and passed over, never treated as an error:

| Fours needs | Otherwise passed over as | What to do |
| --- | --- | --- |
| The course is linked to its course in your LMS | Unmatched course | Pick it under **Course in your LMS**. An unlinked course reports zero completions, however many partners finish it. |
| The learner's email address belongs to a Fours user | Unknown learner | Make sure the learner has a Fours account under the same email address — the same people single sign-on can sign in. |
| That user is enrolled in the course in Fours | Not enrolled | The learner enrolls in the course in Fours, or is assigned it. |

A partner doesn't have to open the course from Fours first. Someone who went straight to your LMS is still recorded as having finished, as long as they're enrolled in Fours.

**Re-running is safe.** A completion is recorded once. Running **Sync now** again, or getting the same completion from both the webhook and the scheduled check, changes nothing and never ticks a journey step twice.

## Publish an external course

**Link external LMS** is a third kind of course, alongside the built-in editor and SCORM uploads. See [Build a Training Course](/prm/build-a-training-course/).

An external course is only a destination, so it asks for less:

| Field | Notes |
| ----- | ----- |
| **Course name** | What partners see, for example *Acme Partner Onboarding*. |
| **Destination link** | Where the learner lands in your LMS. It must be a full `https://` address. |
| **Course in your LMS** | Appears once [completion sync](#completion-sync) is set up, listing the courses published on your training domain. Pick the one this course mirrors so its completions can come back. Optional: without it the course still works, but no completion can be matched to it. |
| **LMS** | The name on the partner's **Open in …** button, for example *Skilljar*. Left blank, the button reads **Open in external LMS**. |
| **Category** | Where it sits in your catalogue. |
| **Est. minutes** | Shown to partners as the expected time. |

To link a course you've already created, open it in the course builder. **Course in your LMS** carries a **Not linked** badge until you pick one, and changing the link applies to the next published version.

The destination is pinned to a version, so editing the course later does not silently repoint partners who are already working through it.

You don't need a single sign-on connection to publish an external course. Without one, **Open in …** sends partners straight to the destination link, and your LMS signs them in however it normally does.

## What partners see

On an external course the partner gets a single button — **Open in** followed by the course's LMS name — at every stage. There is no Start / Resume / Review progression, because Fours is not running the lessons and has nothing to resume.

## Verify Before Announcing It

Before you tell partners, run these checks with a real partner user:

1. The partner clicks **Open in …** on a course in Fours and lands on that course page in your LMS, already signed in.
2. **An existing learner signs in and still sees their completion history**, with no new learner record. If not, stop and recheck the Name ID setting in [Step 2](#step-2-configure-your-lms).
3. A partner on a different device, with no existing session, can sign in.
4. In Fours, the course's **Enrollments** view shows that learner's last-opened date and open count.
5. If you use completion sync, finish a linked course as that partner, then check that their enrollment reads **Completed** in the course's **Enrollments** view.

## What you can still monitor

**An external course reports that it was opened and, with completion sync, that it was finished — never how far through it a partner is.** Fours keeps a per-enrollment open ledger, so [Share and Monitor Training](/prm/share-monitor-training/) shows an **Opened** status and a count of how many partners have opened it — never a percentage complete.

Tell your team these limits before go-live:

- **Nothing in between comes back.** An external enrollment is **Not Started**, **Opened**, or — once your LMS reports a completion through completion sync — **Completed**. It never reads **In Progress**. In a course's **Enrollments** view, each learner shows **Last opened** with a date and an open count instead of a progress bar.
- **"Opened" means "clicked the link."** The open is recorded when the partner clicks **Open in …**, before they reach your LMS — so it includes people who never got past your LMS's sign-in page.
- **Certificates can't be earned from an external course**, even with completion sync on. You can attach one, but Fours issues a certificate only for a passed quiz or a completed SCORM package, and an external course has neither.
- **Without completion sync, journey steps and tier conditions on an external course have to be completed by hand.** With it, a **Complete course** step ticks itself once the completion comes back.
- **Signing out of your LMS doesn't end the Fours session.**

That is a real limit, not a gap to work around: the lessons run in your LMS, so your LMS is the only place that knows how far a learner has got. Completion sync brings back the one fact it reports — that they finished.

## Troubleshooting

| What you see | Usual cause |
| ------------ | ----------- |
| Sign-in fails with a signature error | Your LMS may hold an outdated or mistyped signing certificate. Re-import the metadata rather than pasting the certificate by hand ([Step 2](#step-2-configure-your-lms)). |
| Learners sign in, but without a name | Check that your LMS maps the attributes under the exact names `Email`, `FirstName`, and `LastName` ([Step 2](#step-2-configure-your-lms)). |
| Existing learners get brand-new records | The Name ID isn't set to email address, or your LMS matches learners on something else. Stop and check before more learners sign in. |
| **Test connection** passes, but sign-in fails | The test checks the metadata only and never signs anyone in. Recheck the ACS URL and service provider entity ID exchanged in Steps 2 and 3. |
| **Test connection** reports that no metadata URL is configured yet | The metadata URL wasn't saved. Enter it, click **Save**, then test again. |
| A course reports zero completions, although partners have finished it | It isn't linked under **Course in your LMS** ([Publish an external course](#publish-an-external-course)). |
| **Sync now** reports completions it passed over | Each count names the match that failed. See [How completions are matched](#how-completions-are-matched). |
| Completions that used to land in seconds now take days | The webhook has stopped delivering, most often because the secret in Skilljar no longer matches. See [Set up the completion webhook](#set-up-the-completion-webhook). |

### The partner arrives signed out

Check that **External LMS single sign-on** is switched on and saved in Fours ([Step 4](#step-4-turn-on-single-sign-on)), and that the SSO configuration is enabled in your LMS. **Open in …** always sends partners to the course's destination link; whether that page asks a visitor to sign in is decided by your LMS's own settings.

## Related

- [Build a Training Course](/prm/build-a-training-course/)
- [Share and Monitor Partner Training Courses](/prm/share-monitor-training/)
- [Take a Training Course](/prm/take-training-course/)
