> ## Documentation Index
> Fetch the complete documentation index at: https://docs.junojourney.com/llms.txt
> Use this file to discover all available pages before exploring further.

# xAPI Content

> Add xAPI (TinCan or cmi5) packages to Juno — link to content hosted by a vendor, or upload a package that Juno stores and plays for you.

export const RelatedPages = ({pages = []}) => {
  if (pages.length === 0) return null;
  return <>
      <br />
      <strong>Related articles</strong>
      <CardGroup cols={2}>
        {pages.map(page => <Card title={page.title} href={page.href} key={page.href} />)}
      </CardGroup>
    </>;
};

export const RoleBadge = ({roles = []}) => {
  const colorMap = {
    Admin: "yellow",
    Manager: "blue",
    Learner: "green",
    "Co-editor": "purple"
  };
  return <>
      {roles.map(role => <span key={role}><Badge color={colorMap[role] || "gray"} size="sm" shape="pill">{role}</Badge>{" "}</span>)}
    </>;
};

export const FeatureAvailability = ({module, feature}) => {
  const label = feature || module;
  return <Info title="Feature availability">
      {label ? <>This feature requires the <strong>{label}</strong> module. </> : <>This feature may not be enabled for your organization. </>}
      If you don't see it in Juno, contact your administrator.
    </Info>;
};

<FeatureAvailability />

**xAPI** content (also known as **TinCan** or **cmi5**) is interactive learning that reports what a learner did as it plays. You add it to Juno from a ZIP package, and Juno marks the unit complete when the package reports completion.

This page is about content you **add to Juno**. To send Juno learning activity to an external Learning Record Store, see [xAPI integration](/integrations/xapi).

***

## Two kinds of xAPI package

Juno reads the package's manifest to find its launch target. The launch target decides how Juno handles the unit.

| Kind | How to recognize it | What Juno does |
| - | - | - |
| **Vendor-hosted** | The manifest has a full web address as its launch target. Packages from content vendors that host their own courses are often like this. | Juno stores only the address. The content stays on the vendor's server and opens in a new window. |
| **Self-hosted** | The manifest's launch target is a file inside the package, such as the `index_lms.html` file that Articulate Storyline produces. | Juno stores the package, serves it from a separate content address, and plays it inside the unit page. |

<Note>
  Vendor-hosted xAPI needs one setting. Self-hosted xAPI needs a second setting on top of it. If your package contains the course files and you see **This package contains the course files itself, which isn't supported yet**, the second setting is off for your organization. Ask your administrator.
</Note>

***

## Add xAPI content

<RoleBadge roles={["Admin"]} />

<Steps>
  <Step title="Open the SCORM dialog">
    Select **+ Create**, hover **New**, and choose **SCORM**. When xAPI is enabled, the dialog shows a switch above the form.
  </Step>

  <Step title="Choose xAPI">
    Select **xAPI / TinCan · cmi5** instead of **SCORM 1.2 / 2004**. The dialog title changes to **Create xAPI / TinCan content**.
  </Step>

  <Step title="Upload the package">
    Under **Upload manifest file**, drop a ZIP onto **Drag & Drop your ZIP file or click to browse**. The ZIP must contain a `tincan.xml` or `cmi5.xml` manifest. It can sit in a folder inside the ZIP. Juno reads the manifest and fills in the title and **Launch URL** for you. The launch URL carries an **auto-detected** tag.
  </Step>

  <Step title="Check the details">
    The dropzone confirms **Manifest parsed successfully**. Edit the title, add a description, and set the language, audience, tags, and co-editors if you need to.
  </Step>

  <Step title="Create">
    Select **Create**. For a self-hosted package, Juno then uploads and unpacks the files and shows its progress. The unit opens when it finishes. If you started from a Journey, the unit is added to that Journey as a step.
  </Step>
</Steps>

### If the manifest can't be read

The dropzone says **Could not parse manifest — click to try a different file**, with the reason under it.

| Message | What to do |
| - | - |
| **No tincan.xml or cmi5.xml found in ZIP** | The ZIP has no manifest. Check that you zipped the package, and try again. |
| **Manifest could not be read — it is not valid XML.** | Re-export the package from your authoring tool. |
| **Manifest is missing a launch URL**, or **Manifest has no activity with a launch target** | Re-export the package with a valid launch element. |
| **This package contains the course files itself, which isn't supported yet** | Self-hosting is off for your organization. Publish the content as SCORM and upload that, host the package on your own server and re-export it with a full launch URL, or ask your administrator to turn on self-hosted xAPI. |

### Change a vendor-hosted unit

To point a vendor-hosted unit at a different launch URL, open its editor. The package area shows the current launch URL. Drop a new ZIP onto it, then select **Update**. When xAPI is enabled, an editor switch also lets you change a unit between **SCORM 1.2 / 2004** and **xAPI / TinCan · cmi5**. Switching replaces the unit's content when you upload the new package.

***

## How learners take xAPI content

What a learner sees depends on the kind of package.

### Self-hosted packages

The content plays inside the unit page, the same way SCORM content does. Juno checks for completion in the background and updates the unit when the package reports it. Camera and microphone are not available to the package.

### Vendor-hosted packages

<Steps>
  <Step title="Launch the content">
    The page says **This content will open in a new window.** Select **Launch content**.
  </Step>

  <Step title="Take the content">
    Work through the content in the new window. Back in Juno, the unit page says **Content opened in a new window. Waiting for completion...** Select **Reopen content window** if you closed it.
  </Step>

  <Step title="Come back to Juno">
    When you return to the Juno tab, Juno checks completion. The page changes to **Content completed!** Select **Relaunch content** to open it again.
  </Step>
</Steps>

If the content does not load, learners see **Failed to load content. Please try again.** If the stored address is not a valid web address, they see a message asking them to contact their administrator to re-upload the package.

<Note>
  Vendors often block their content from loading inside another page. That is why vendor-hosted content opens in a new window.
</Note>

<RelatedPages
  pages={[
{ href: "/learning/scorm-content", title: "SCORM Content" },
{ href: "/learning/html-lessons", title: "HTML Lessons" },
{ href: "/integrations/xapi", title: "xAPI integration" },
{ href: "/learning/units-and-courses", title: "Content Types Overview" },
]}
/>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.