# Kapi Works courses and policies

> Make Kapi Works courses and policies with your own AI or by hand: the course format, the seven course types, Kapi's checks and an example course for each type, and the policy format with six example policies.

- Format: kapi.works.package/2, checked by checker 2.2.0, which reports kapi.works.check/2.
- An example course for each type: https://docs.kapiworks.com/build/examples/training-course.json, https://docs.kapiworks.com/build/examples/scenario-course.json, https://docs.kapiworks.com/build/examples/quick-refresher.json, https://docs.kapiworks.com/build/examples/certificate-course.json, https://docs.kapiworks.com/build/examples/walkthrough.json, https://docs.kapiworks.com/build/examples/what-changed.json, https://docs.kapiworks.com/build/examples/video.json
- JSON Schemas of the data files: https://docs.kapiworks.com/schemas/package-2.json, https://docs.kapiworks.com/schemas/content-2.json, https://docs.kapiworks.com/schemas/questions-2.json, https://docs.kapiworks.com/schemas/words-1.json, https://docs.kapiworks.com/schemas/support-1.json, https://docs.kapiworks.com/schemas/theme-1.json, https://docs.kapiworks.com/schemas/bundle-1.json
- TypeScript types of the data files: https://docs.kapiworks.com/schemas/kapi-works-package.d.ts
- Check a bundle in the browser: https://docs.kapiworks.com/build/check
- Policies: the whole policy format, its prompt and Kapi's example policies in one file: https://docs.kapiworks.com/build/policies/llms.txt
- Every page below is also Markdown: add .md to its address, or send Accept: text/markdown.
- Docs MCP server (streamable HTTP, read-only): https://docs.kapiworks.com/api/mcp, with get_course_type, get_schema and get_check.

# Build courses

Make Kapi Works courses with Kapi or with your own AI, check them against Kapi's rules, and bring them into Works Studio.

A Kapi Works course is a small set of data files. `content.json` holds its lessons, pages and blocks. `questions.json` holds its questions, with feedback on every choice. A words file holds every word a learner reads. `kapi-works.json` says what the course is, including its type. Kapi's course player draws the course, so it holds no page code. [Files](https://docs.kapiworks.com/build/reference/files) lists every file and key.

## Seven course types

Each type is a shape for a course, with checks of its own. All seven play on Kapi's course player.

| Course type | `courseType` | For |
| --- | --- | --- |
| [Training course](https://docs.kapiworks.com/build/course-types/training-course) | `training-course` | Teach a topic in short lessons, with practice questions and a test. |
| [Scenario practice](https://docs.kapiworks.com/build/course-types/scenario-course) | `scenario-course` | Practise real situations: people choose what to do, then see why. |
| [Quick refresher](https://docs.kapiworks.com/build/course-types/quick-refresher) | `quick-refresher` | A short yearly refresh: questions first, so people who know move on. |
| [Certificate course](https://docs.kapiworks.com/build/course-types/certificate-course) | `certificate-course` | Lessons, then a test drawn from a larger pool, for a certificate. |
| [Step-by-step walkthrough](https://docs.kapiworks.com/build/course-types/walkthrough) | `walkthrough` | Show how to use a tool or follow a process, step by step. |
| [What changed](https://docs.kapiworks.com/build/course-types/what-changed) | `what-changed` | A rule changed: show the new rule, the old one once, and why. |
| [Video](https://docs.kapiworks.com/build/course-types/video) | `video` | A short film with questions that pause it, for one clear message. |

## Three ways in

In Works Studio, press **Create**, then **Course**. **New course** opens with three ways in:

* **Make it with Kapi.** Say what the course is about. Kapi chooses the type that fits and replies with a plan: the type, each lesson with its minutes and what it covers, and the test. Ask for changes, another type included, or press **Make the course**. Add PDF, Word, PowerPoint, web page or text files, up to 25 MB each, and Kapi plans the course from them. It leaves out the email addresses and phone numbers it finds unless you keep them, and checks every answer against a quote from your documents.
* **Copy prompt for your AI.** Copies one prompt with Kapi's example course inside it, for ChatGPT, Claude, Gemini or any AI. Your AI chooses the type. The [quickstart](https://docs.kapiworks.com/build/quickstart) shows how.
* **Upload your course.** Paste what your AI made, or choose a Kapi course as a JSON bundle, a zip or a folder.

Below them are Kapi's seven example courses, one of each type. **Have a look** plays one, and **Copy prompt** copies the prompt for a course like it.

Every way in ends on the same stage. The course plays, Kapi's checks list what is left to fix, and **Let Kapi fix** fixes what it can. **Continue** opens the course's settings, where **Publish** is.

## Kapi's checks

Kapi checks every course the same way, wherever it comes from: in Works Studio, on Kapi's server when the course is saved, and in your browser on [Check a course](https://docs.kapiworks.com/build/check). Each finding says what is wrong and links to how to fix it. Errors block approval; warnings and tips do not. [Checks](https://docs.kapiworks.com/build/reference/checks) lists every one.

## Find your way

- [Course quickstart](https://docs.kapiworks.com/build/quickstart): A course that passes Kapi's checks, made with your own AI.
- [What makes a great course](https://docs.kapiworks.com/build/guides/great-courses): The rules behind a good course, and which ones Kapi checks.
- [Check a course](https://docs.kapiworks.com/build/check): Paste a bundle and see every finding, worst first.
- [Files](https://docs.kapiworks.com/build/reference/files): Every file and key of a course, from the JSON Schemas.
- [Checks](https://docs.kapiworks.com/build/reference/checks): Every check, with its severity and how to fix it.
- [Policies](https://docs.kapiworks.com/build/policies): Policies people acknowledge or sign, and the HTML format they are written in.
- [For AI agents](https://docs.kapiworks.com/build/ai): Prompts, example courses, schemas and plain text for your AI.


# Course quickstart

Make a course that passes Kapi's checks with your own AI, in about ten minutes.

You need an AI chat, such as the one your company already uses, and a Kapi Works company where you can make courses. This quickstart makes a [training course](https://docs.kapiworks.com/build/course-types/training-course). Every [course type](https://docs.kapiworks.com/build) works the same way.

## 1. Copy the prompt

Open [Training course](https://docs.kapiworks.com/build/course-types/training-course) and press **Copy the prompt**. The prompt gives your AI the type's shape and Kapi's rules:

```text
Kapi Works course prompt · Training course · package 2

Make a training course for Kapi Works, my company's learning platform. Answer with one JSON object in one code block: { "schema": "kapi.works.bundle/1", "files": { … } }, with "courseType": "training-course" in kapi-works.json. Kapi checks it and fixes small problems itself.

THIS TYPE
Write 2 to 4 lessons of 4 to 7 minutes, each with 2 to 4 pages. Put a practice question on most pages, so every lesson has at least one. Add a test pool of 6 to 12 questions that sit on no page.

RULES
1. Copy the layout of Kapi's attached example: its files, fields and ID style. Replace all its content; never copy its topic or its words.
2. Every word a learner sees goes in "words/en-GB.json" under an ID. Everywhere else names the ID.
3. Right answers go in questions.json. Every choice has feedback saying why it is right or wrong, and every question has an explanation.
4. Test pool questions go in "assessments" in kapi-works.json and sit on no page.
5. Never draw a test, score, certificate, signature or "I agree". Kapi adds its own after the course.
6. No personal data: write {company.name}, and a contact block for who to ask, never a real name, email or phone.
7. Use only my documents for rules and figures. If they don't say, ask me.
8. Give the whole object. Never shorten it or write "…".

If you can open web pages, read https://docs.kapiworks.com/build/llms-full.txt first.
Ask me up to five questions, then propose an outline (lessons, minutes, questions) and wait for my OK.
If Kapi's example isn't attached, ask me for it.
```

In Works Studio, **Create**, then **Course**, then **Copy prompt for your AI** copies one prompt for any course type with Kapi's example inside it. With that prompt, skip step 2.

## 2. Download the example

On the same page, press **Download the example** to save [`training-course.json`](https://docs.kapiworks.com/build/examples/training-course.json). It is a whole training course for a made-up company, as one bundle. Your AI copies its layout, not its words.

## 3. Ask your AI

Start a new chat. Paste the prompt, attach the example, and say what the course is about. Attach your own documents too: the prompt tells your AI to take rules and figures only from them.

Your AI asks a few questions, proposes an outline and waits for your OK. Then it answers with one JSON block: the bundle. A long answer can come in parts; keep every part.

## 4. Check the bundle

Paste the bundle into [Check a course](https://docs.kapiworks.com/build/check). Each finding shows as a row, worst first, with a link to its check. Errors block approval; warnings and tips do not. To fix one, give its message to your AI and ask for the whole bundle again.

## 5. Bring it into Works Studio

In Works Studio, press **Create**, then **Course**, then **Upload your course**. Paste the bundle into **Paste what your AI made** and press **Use this course**. Or save the bundle as a `.json` file and press **Choose a file**.

Kapi checks the course again and shows it playing, with anything left to fix. **Continue** opens the course's settings, where **Publish** is.

## Next steps

* [What makes a great course](https://docs.kapiworks.com/build/guides/great-courses): the rules behind a good course.
* [Files](https://docs.kapiworks.com/build/reference/files): every file and key, from the JSON Schemas.
* [Checks](https://docs.kapiworks.com/build/reference/checks): every check, with how to fix it.


# Training course

Teach a topic in short lessons, with practice questions and a test.

A course of this type has `"courseType": "training-course"` in `kapi-works.json`. A course that leaves `courseType` out is one too.

## Its shape

Write 2 to 4 lessons of 4 to 7 minutes, each with 2 to 4 pages. Put a practice question on most pages, so every lesson has at least one. Add a test pool of 6 to 12 questions that sit on no page.

## What Kapi checks

Kapi runs [every check](https://docs.kapiworks.com/build/reference/checks) on every course. This one runs only on this type:

| Check | Severity | What Kapi says |
| --- | --- | --- |
| [`lesson_without_question`](https://docs.kapiworks.com/build/reference/checks/lesson-without-question) | Warning | … has no practice question. A question in each lesson helps people keep what they read. |

## The prompt

Copy it into your own AI and attach the example. It stays under 2,000 characters, so it fits the smallest chat box.

```text
Kapi Works course prompt · Training course · package 2

Make a training course for Kapi Works, my company's learning platform. Answer with one JSON object in one code block: { "schema": "kapi.works.bundle/1", "files": { … } }, with "courseType": "training-course" in kapi-works.json. Kapi checks it and fixes small problems itself.

THIS TYPE
Write 2 to 4 lessons of 4 to 7 minutes, each with 2 to 4 pages. Put a practice question on most pages, so every lesson has at least one. Add a test pool of 6 to 12 questions that sit on no page.

RULES
1. Copy the layout of Kapi's attached example: its files, fields and ID style. Replace all its content; never copy its topic or its words.
2. Every word a learner sees goes in "words/en-GB.json" under an ID. Everywhere else names the ID.
3. Right answers go in questions.json. Every choice has feedback saying why it is right or wrong, and every question has an explanation.
4. Test pool questions go in "assessments" in kapi-works.json and sit on no page.
5. Never draw a test, score, certificate, signature or "I agree". Kapi adds its own after the course.
6. No personal data: write {company.name}, and a contact block for who to ask, never a real name, email or phone.
7. Use only my documents for rules and figures. If they don't say, ask me.
8. Give the whole object. Never shorten it or write "…".

If you can open web pages, read https://docs.kapiworks.com/build/llms-full.txt first.
Ask me up to five questions, then propose an outline (lessons, minutes, questions) and wait for my OK.
If Kapi's example isn't attached, ask me for it.
```

## The example

[`training-course.json`](https://docs.kapiworks.com/build/examples/training-course.json) is a whole course of this type for a made-up company, as one `kapi.works.bundle/1` bundle of its data files. Your AI copies its layout, not its words.


# Scenario practice

Practise real situations: people choose what to do, then see why.

A course of this type has `"courseType": "scenario-course"` in `kapi-works.json`.

## Its shape

Write 2 to 4 lessons of 4 to 7 minutes. Each lesson's first page opens with a choice question that has a "situation", and its feedback explains every option. Then ask 2 or 3 recall questions. Add a test pool of 6 to 12 questions that sit on no page.

## What Kapi checks

Kapi runs [every check](https://docs.kapiworks.com/build/reference/checks) on every course. This one runs only on this type:

| Check | Severity | What Kapi says |
| --- | --- | --- |
| [`scenario_opening_missing`](https://docs.kapiworks.com/build/reference/checks/scenario-opening-missing) | Error | … doesn't open with a situation to choose from. In scenario practice, each lesson starts with a situation and a choice. |

## The prompt

Copy it into your own AI and attach the example. It stays under 2,000 characters, so it fits the smallest chat box.

```text
Kapi Works course prompt · Scenario practice · package 2

Make a scenario practice for Kapi Works, my company's learning platform. Answer with one JSON object in one code block: { "schema": "kapi.works.bundle/1", "files": { … } }, with "courseType": "scenario-course" in kapi-works.json. Kapi checks it and fixes small problems itself.

THIS TYPE
Write 2 to 4 lessons of 4 to 7 minutes. Each lesson's first page opens with a choice question that has a "situation", and its feedback explains every option. Then ask 2 or 3 recall questions. Add a test pool of 6 to 12 questions that sit on no page.

RULES
1. Copy the layout of Kapi's attached example: its files, fields and ID style. Replace all its content; never copy its topic or its words.
2. Every word a learner sees goes in "words/en-GB.json" under an ID. Everywhere else names the ID.
3. Right answers go in questions.json. Every choice has feedback saying why it is right or wrong, and every question has an explanation.
4. Test pool questions go in "assessments" in kapi-works.json and sit on no page.
5. Never draw a test, score, certificate, signature or "I agree". Kapi adds its own after the course.
6. No personal data: write {company.name}, and a contact block for who to ask, never a real name, email or phone.
7. Use only my documents for rules and figures. If they don't say, ask me.
8. Give the whole object. Never shorten it or write "…".

If you can open web pages, read https://docs.kapiworks.com/build/llms-full.txt first.
Ask me up to five questions, then propose an outline (lessons, minutes, questions) and wait for my OK.
If Kapi's example isn't attached, ask me for it.
```

## The example

[`scenario-course.json`](https://docs.kapiworks.com/build/examples/scenario-course.json) is a whole course of this type for a made-up company, as one `kapi.works.bundle/1` bundle of its data files. Your AI copies its layout, not its words.


# Quick refresher

A short yearly refresh: questions first, so people who know move on.

A course of this type has `"courseType": "quick-refresher"` in `kapi-works.json`.

## Its shape

Keep the whole refresher to 8 to 12 minutes. Every page starts with its question, and the feedback on each choice and the explanation do the teaching in one or two sentences. Keep any text after the question short.

## What Kapi checks

Kapi runs [every check](https://docs.kapiworks.com/build/reference/checks) on every course. These run only on this type:

| Check | Severity | What Kapi says |
| --- | --- | --- |
| [`refresher_question_first`](https://docs.kapiworks.com/build/reference/checks/refresher-question-first) | Error | This page doesn't start with its question. In a quick refresher, every page asks first and the feedback teaches. |
| [`refresher_too_long`](https://docs.kapiworks.com/build/reference/checks/refresher-too-long) | Warning | This refresher takes about … minutes. A quick refresher takes 8 to 12. |

## The prompt

Copy it into your own AI and attach the example. It stays under 2,000 characters, so it fits the smallest chat box.

```text
Kapi Works course prompt · Quick refresher · package 2

Make a quick refresher for Kapi Works, my company's learning platform. Answer with one JSON object in one code block: { "schema": "kapi.works.bundle/1", "files": { … } }, with "courseType": "quick-refresher" in kapi-works.json. Kapi checks it and fixes small problems itself.

THIS TYPE
Keep the whole refresher to 8 to 12 minutes. Every page starts with its question, and the feedback on each choice and the explanation do the teaching in one or two sentences. Keep any text after the question short.

RULES
1. Copy the layout of Kapi's attached example: its files, fields and ID style. Replace all its content; never copy its topic or its words.
2. Every word a learner sees goes in "words/en-GB.json" under an ID. Everywhere else names the ID.
3. Right answers go in questions.json. Every choice has feedback saying why it is right or wrong, and every question has an explanation.
4. Test pool questions go in "assessments" in kapi-works.json and sit on no page.
5. Never draw a test, score, certificate, signature or "I agree". Kapi adds its own after the course.
6. No personal data: write {company.name}, and a contact block for who to ask, never a real name, email or phone.
7. Use only my documents for rules and figures. If they don't say, ask me.
8. Give the whole object. Never shorten it or write "…".

If you can open web pages, read https://docs.kapiworks.com/build/llms-full.txt first.
Ask me up to five questions, then propose an outline (lessons, minutes, questions) and wait for my OK.
If Kapi's example isn't attached, ask me for it.
```

## The example

[`quick-refresher.json`](https://docs.kapiworks.com/build/examples/quick-refresher.json) is a whole course of this type for a made-up company, as one `kapi.works.bundle/1` bundle of its data files. Your AI copies its layout, not its words.


# Certificate course

Lessons, then a test drawn from a larger pool, for a certificate.

A course of this type has `"courseType": "certificate-course"` in `kapi-works.json`.

## Its shape

Write 3 to 5 lessons of 4 to 7 minutes with practice questions. Add a test pool at least twice the size of the draw, with "suggest": {"draw": n, "passMark": 80}. Pool questions sit on no page and cover every lesson.

## What Kapi checks

Kapi runs [every check](https://docs.kapiworks.com/build/reference/checks) on every course. These run only on this type:

| Check | Severity | What Kapi says |
| --- | --- | --- |
| [`certificate_pool_small`](https://docs.kapiworks.com/build/reference/checks/certificate-pool-small) | Error | A certificate test needs a pool at least twice the size of its draw (…), so each retake asks different questions. |
| [`certificate_pass_mark_missing`](https://docs.kapiworks.com/build/reference/checks/certificate-pass-mark-missing) | Warning | The test suggests no pass mark. The company can change it, but a certificate course should suggest one. |

## The prompt

Copy it into your own AI and attach the example. It stays under 2,000 characters, so it fits the smallest chat box.

```text
Kapi Works course prompt · Certificate course · package 2

Make a certificate course for Kapi Works, my company's learning platform. Answer with one JSON object in one code block: { "schema": "kapi.works.bundle/1", "files": { … } }, with "courseType": "certificate-course" in kapi-works.json. Kapi checks it and fixes small problems itself.

THIS TYPE
Write 3 to 5 lessons of 4 to 7 minutes with practice questions. Add a test pool at least twice the size of the draw, with "suggest": {"draw": n, "passMark": 80}. Pool questions sit on no page and cover every lesson.

RULES
1. Copy the layout of Kapi's attached example: its files, fields and ID style. Replace all its content; never copy its topic or its words.
2. Every word a learner sees goes in "words/en-GB.json" under an ID. Everywhere else names the ID.
3. Right answers go in questions.json. Every choice has feedback saying why it is right or wrong, and every question has an explanation.
4. Test pool questions go in "assessments" in kapi-works.json and sit on no page.
5. Never draw a test, score, certificate, signature or "I agree". Kapi adds its own after the course.
6. No personal data: write {company.name}, and a contact block for who to ask, never a real name, email or phone.
7. Use only my documents for rules and figures. If they don't say, ask me.
8. Give the whole object. Never shorten it or write "…".

If you can open web pages, read https://docs.kapiworks.com/build/llms-full.txt first.
Ask me up to five questions, then propose an outline (lessons, minutes, questions) and wait for my OK.
If Kapi's example isn't attached, ask me for it.
```

## The example

[`certificate-course.json`](https://docs.kapiworks.com/build/examples/certificate-course.json) is a whole course of this type for a made-up company, as one `kapi.works.bundle/1` bundle of its data files. Your AI copies its layout, not its words.


# Step-by-step walkthrough

Show how to use a tool or follow a process, step by step.

A course of this type has `"courseType": "walkthrough"` in `kapi-works.json`.

## Its shape

Write one lesson per task. Each lesson shows numbered steps in a "steps" block, a picture of the screen beside them (ask me for the screenshots and list them in "media"), a "Try it now" callout, and a checked question.

## What Kapi checks

Kapi runs [every check](https://docs.kapiworks.com/build/reference/checks) on every course. These run only on this type:

| Check | Severity | What Kapi says |
| --- | --- | --- |
| [`walkthrough_steps_missing`](https://docs.kapiworks.com/build/reference/checks/walkthrough-steps-missing) | Error | … has no numbered steps. A walkthrough shows each step in order. |
| [`walkthrough_picture_missing`](https://docs.kapiworks.com/build/reference/checks/walkthrough-picture-missing) | Tip | These steps have no picture. A screenshot of each step helps people follow along. |

## The prompt

Copy it into your own AI and attach the example. It stays under 2,000 characters, so it fits the smallest chat box.

```text
Kapi Works course prompt · Step-by-step walkthrough · package 2

Make a step-by-step walkthrough for Kapi Works, my company's learning platform. Answer with one JSON object in one code block: { "schema": "kapi.works.bundle/1", "files": { … } }, with "courseType": "walkthrough" in kapi-works.json. Kapi checks it and fixes small problems itself.

THIS TYPE
Write one lesson per task. Each lesson shows numbered steps in a "steps" block, a picture of the screen beside them (ask me for the screenshots and list them in "media"), a "Try it now" callout, and a checked question.

RULES
1. Copy the layout of Kapi's attached example: its files, fields and ID style. Replace all its content; never copy its topic or its words.
2. Every word a learner sees goes in "words/en-GB.json" under an ID. Everywhere else names the ID.
3. Right answers go in questions.json. Every choice has feedback saying why it is right or wrong, and every question has an explanation.
4. Test pool questions go in "assessments" in kapi-works.json and sit on no page.
5. Never draw a test, score, certificate, signature or "I agree". Kapi adds its own after the course.
6. No personal data: write {company.name}, and a contact block for who to ask, never a real name, email or phone.
7. Use only my documents for rules and figures. If they don't say, ask me.
8. Give the whole object. Never shorten it or write "…".

If you can open web pages, read https://docs.kapiworks.com/build/llms-full.txt first.
Ask me up to five questions, then propose an outline (lessons, minutes, questions) and wait for my OK.
If Kapi's example isn't attached, ask me for it.
```

## The example

[`walkthrough.json`](https://docs.kapiworks.com/build/examples/walkthrough.json) is a whole course of this type for a made-up company, as one `kapi.works.bundle/1` bundle of its data files. Your AI copies its layout, not its words.

A bundle carries no pictures, so the example lists its 2 pictures in `media` without their files.


# What changed

A rule changed: show the new rule, the old one once, and why.

A course of this type has `"courseType": "what-changed"` in `kapi-works.json`.

## Its shape

Write one lesson per change. In each: the new rule; the old rule once, in a block whose words start "Before" and the date it changed; why it changed; the new rule again; then one choice question with a "situation" about the change.

## What Kapi checks

Kapi runs [every check](https://docs.kapiworks.com/build/reference/checks) on every course. These run only on this type:

| Check | Severity | What Kapi says |
| --- | --- | --- |
| [`change_before_missing`](https://docs.kapiworks.com/build/reference/checks/change-before-missing) | Error | … doesn't show the old rule. Show it once, starting "Before" and the date it changed. |
| [`change_question_missing`](https://docs.kapiworks.com/build/reference/checks/change-question-missing) | Error | … has no situation question about the change. |

## The prompt

Copy it into your own AI and attach the example. It stays under 2,000 characters, so it fits the smallest chat box.

```text
Kapi Works course prompt · What changed · package 2

Make a what changed for Kapi Works, my company's learning platform. Answer with one JSON object in one code block: { "schema": "kapi.works.bundle/1", "files": { … } }, with "courseType": "what-changed" in kapi-works.json. Kapi checks it and fixes small problems itself.

THIS TYPE
Write one lesson per change. In each: the new rule; the old rule once, in a block whose words start "Before" and the date it changed; why it changed; the new rule again; then one choice question with a "situation" about the change.

RULES
1. Copy the layout of Kapi's attached example: its files, fields and ID style. Replace all its content; never copy its topic or its words.
2. Every word a learner sees goes in "words/en-GB.json" under an ID. Everywhere else names the ID.
3. Right answers go in questions.json. Every choice has feedback saying why it is right or wrong, and every question has an explanation.
4. Test pool questions go in "assessments" in kapi-works.json and sit on no page.
5. Never draw a test, score, certificate, signature or "I agree". Kapi adds its own after the course.
6. No personal data: write {company.name}, and a contact block for who to ask, never a real name, email or phone.
7. Use only my documents for rules and figures. If they don't say, ask me.
8. Give the whole object. Never shorten it or write "…".

If you can open web pages, read https://docs.kapiworks.com/build/llms-full.txt first.
Ask me up to five questions, then propose an outline (lessons, minutes, questions) and wait for my OK.
If Kapi's example isn't attached, ask me for it.
```

## The example

[`what-changed.json`](https://docs.kapiworks.com/build/examples/what-changed.json) is a whole course of this type for a made-up company, as one `kapi.works.bundle/1` bundle of its data files. Your AI copies its layout, not its words.


# Video

A short film with questions that pause it, for one clear message.

A course of this type has `"courseType": "video"` in `kapi-works.json`.

## Its shape

Write one lesson per film, 2 to 4 minutes each. The lesson's first page holds one "film" block of 6 to 12 scenes of 15 to 30 seconds, in the drawn layouts: title, number, email, chat, person, icons and checklist. Each scene's caption is what the narrator says, in short sentences with no placeholders, and its picture says what it shows. Stop the film 2 or 3 times with a "pause" choice question that has a "situation". Add a test pool of 6 to 12 questions that sit on no page. Set "sdk" to "2.1".

## What Kapi checks

Kapi runs [every check](https://docs.kapiworks.com/build/reference/checks) on every course. This one runs only on this type:

| Check | Severity | What Kapi says |
| --- | --- | --- |
| [`video_opening_missing`](https://docs.kapiworks.com/build/reference/checks/video-opening-missing) | Error | … doesn't open with a film. In a video, each lesson starts with its film. |

## The prompt

Copy it into your own AI and attach the example. It stays under 2,000 characters, so it fits the smallest chat box.

```text
Kapi Works course prompt · Video · package 2

Make a video for Kapi Works, my company's learning platform. Answer with one JSON object in one code block: { "schema": "kapi.works.bundle/1", "files": { … } }, with "courseType": "video" in kapi-works.json. Kapi checks it and fixes small problems itself.

THIS TYPE
Write one lesson per film, 2 to 4 minutes each. The lesson's first page holds one "film" block of 6 to 12 scenes of 15 to 30 seconds, in the drawn layouts: title, number, email, chat, person, icons and checklist. Each scene's caption is what the narrator says, in short sentences with no placeholders, and its picture says what it shows. Stop the film 2 or 3 times with a "pause" choice question that has a "situation". Add a test pool of 6 to 12 questions that sit on no page. Set "sdk" to "2.1".

RULES
1. Copy the layout of Kapi's attached example: its files, fields and ID style. Replace all its content; never copy its topic or its words.
2. Every word a learner sees goes in "words/en-GB.json" under an ID. Everywhere else names the ID.
3. Right answers go in questions.json. Every choice has feedback saying why it is right or wrong, and every question has an explanation.
4. Test pool questions go in "assessments" in kapi-works.json and sit on no page.
5. Never draw a test, score, certificate, signature or "I agree". Kapi adds its own after the course.
6. No personal data: write {company.name}, and a contact block for who to ask, never a real name, email or phone.
7. Use only my documents for rules and figures. If they don't say, ask me.
8. Give the whole object. Never shorten it or write "…".

If you can open web pages, read https://docs.kapiworks.com/build/llms-full.txt first.
Ask me up to five questions, then propose an outline (lessons, minutes, questions) and wait for my OK.
If Kapi's example isn't attached, ask me for it.
```

## The example

[`video.json`](https://docs.kapiworks.com/build/examples/video.json) is a whole course of this type for a made-up company, as one `kapi.works.bundle/1` bundle of its data files. Your AI copies its layout, not its words.


# What makes a great course

The rules behind a good Kapi Works course. Each one says whether Kapi checks it or it is guidance for you and your AI.

A course people finish and remember is short, practical and set in their own work. These rules come from Kapi's checks and from the shapes of the [course types](https://docs.kapiworks.com/build). Each says **Kapi checks this**, with a link to the check, or **Guidance**.

## Keep it short

* **Lessons of 4 to 7 minutes**, with two to four pages each. Kapi checks this: [`lesson_long`](https://docs.kapiworks.com/build/reference/checks/lesson-long).
* **Short sentences.** Shorter sentences are easier to read, especially in a second language. Kapi checks this: [`sentence_long`](https://docs.kapiworks.com/build/reference/checks/sentence-long).
* **A quick refresher takes 8 to 12 minutes in all.** Kapi checks this on a quick refresher: [`refresher_too_long`](https://docs.kapiworks.com/build/reference/checks/refresher-too-long).
* **One idea a page.** A page people can read in a minute or two keeps them going. Guidance.

## Set it in their work

* **Questions set in a situation from the job.** They check that people can use what they learned. Kapi checks this: [`few_situations`](https://docs.kapiworks.com/build/reference/checks/few-situations).
* **Scenario practice opens with a choice.** Each lesson starts with a situation to choose from. Kapi checks this on scenario practice: [`scenario_opening_missing`](https://docs.kapiworks.com/build/reference/checks/scenario-opening-missing).
* **Walkthroughs show numbered steps, with a picture of each.** Kapi checks this on a walkthrough: [`walkthrough_steps_missing`](https://docs.kapiworks.com/build/reference/checks/walkthrough-steps-missing) and [`walkthrough_picture_missing`](https://docs.kapiworks.com/build/reference/checks/walkthrough-picture-missing).
* **Use the company's own words for its tools, teams and forms.** Guidance.

## Ask, then explain

* **A practice question in every lesson.** Kapi checks this on a training course: [`lesson_without_question`](https://docs.kapiworks.com/build/reference/checks/lesson-without-question).
* **In a quick refresher, every page asks first.** People who know the answer move on; the feedback teaches the rest. Kapi checks this on a quick refresher: [`refresher_question_first`](https://docs.kapiworks.com/build/reference/checks/refresher-question-first).
* **Every choice says why it is right or wrong.** Kapi checks this: [`feedback_missing`](https://docs.kapiworks.com/build/reference/checks/feedback-missing).
* **Every question explains its answer.** Kapi checks this: [`explanation_missing`](https://docs.kapiworks.com/build/reference/checks/explanation-missing).
* **Wrong choices people might really pick.** A question is only as good as its wrong answers. Guidance.

## Make the test fair

* **Test questions sit on no page.** Kapi's test draws them from a held pool, so people meet them fresh. Kapi checks this: [`held_question_on_page`](https://docs.kapiworks.com/build/reference/checks/held-question-on-page).
* **A pool larger than the draw**, so retakes ask different questions. Kapi checks this: [`pool_too_small`](https://docs.kapiworks.com/build/reference/checks/pool-too-small) and [`pool_small`](https://docs.kapiworks.com/build/reference/checks/pool-small), and on a certificate course [`certificate_pool_small`](https://docs.kapiworks.com/build/reference/checks/certificate-pool-small).
* **The pool covers every lesson.** Guidance.

## Say only what your documents say

* **A source for every answer key**, quoted word for word in `support.json`. Kapi checks this: [`support_missing`](https://docs.kapiworks.com/build/reference/checks/support-missing) and [`quote_not_found`](https://docs.kapiworks.com/build/reference/checks/quote-not-found).
* **Numbers, money, dates and named Acts come from the source.** Kapi checks this: [`fact_not_in_source`](https://docs.kapiworks.com/build/reference/checks/fact-not-in-source).
* **A changed rule shows the old one once**, starting "Before" and the date it changed. Kapi checks this on a what changed course: [`change_before_missing`](https://docs.kapiworks.com/build/reference/checks/change-before-missing).
* **No promises the course does not keep.** Say what the course does. Kapi checks this: [`claim_word`](https://docs.kapiworks.com/build/reference/checks/claim-word).

## Leave the ending to the company

* **The closing says the learning is finished.** The company's rules decide what comes after, such as a test or a signature, and Kapi adds it. Kapi checks this: [`closing_names_ending`](https://docs.kapiworks.com/build/reference/checks/closing-names-ending).
* **No test, score or certificate in the pages.** Guidance.

## Write for everyone

* **Every picture has alt text**, unless it adds nothing to the words. Kapi checks this: [`alt_missing`](https://docs.kapiworks.com/build/reference/checks/alt-missing).
* **Speech has captions.** Kapi checks this: [`captions_missing`](https://docs.kapiworks.com/build/reference/checks/captions-missing).
* **Plain words, and "you" for the learner.** Guidance.
* **No personal data.** Write `{company.name}` for the company and use a contact block for who to ask, not a real name, email or phone number. Kapi checks the [placeholders](https://docs.kapiworks.com/build/reference/placeholders): [`placeholder_unknown`](https://docs.kapiworks.com/build/reference/checks/placeholder-unknown).
* **Links use https, to hosts the course lists.** Kapi checks this: [`link_not_https`](https://docs.kapiworks.com/build/reference/checks/link-not-https) and [`link_host_undeclared`](https://docs.kapiworks.com/build/reference/checks/link-host-undeclared).


# Check a course

Paste the bundle your AI made and see every finding from Kapi's checker, worst first.

The checker runs in a web browser, at [https://docs.kapiworks.com/build/check](https://docs.kapiworks.com/build/check). Paste a bundle there to see every finding.

This is checker 2.2.0, the same code Works Studio runs. It reads what you paste here in your browser and sends it nowhere. Each finding links to its check, with how to fix it.

A bundle carries no pictures, so a picture it lists in `media` shows as missing here unless it names one Works Studio already keeps, by its `sha256`. Once the course is in Works Studio, add its pictures in the chat and say where they go: Kapi places them and writes their alt text. [Checks](https://docs.kapiworks.com/build/reference/checks) lists every check Kapi runs.


# Files

The data files of a Kapi Works course, and every key each one takes, from the published JSON Schemas.

A course is a folder of data files in the `kapi.works.package/2` format. Kapi's course player draws it, so it holds no page code. Each file can name its JSON Schema in `"$schema"`, so editors check it as you type.

| File | Holds | Schema |
| --- | --- | --- |
| `kapi-works.json` | What the package is, its language, how it plays, and the roles, tests, context, links, media and sources it declares | [`package-2.json`](https://docs.kapiworks.com/schemas/package-2.json) |
| `content.json` | A course's lessons, pages and blocks, in reading order | [`content-2.json`](https://docs.kapiworks.com/schemas/content-2.json) |
| `words/<language>.json` | Every text in the package, by text ID, up to 1 MiB | [`words-1.json`](https://docs.kapiworks.com/schemas/words-1.json) |
| `questions.json` | Every question, with its answer, feedback and explanation | [`questions-2.json`](https://docs.kapiworks.com/schemas/questions-2.json) |
| `support.json` | Where each answer key and fact comes from, quoted word for word from its source | [`support-1.json`](https://docs.kapiworks.com/schemas/support-1.json) |
| `look/theme.json` | The package's look, which starts from the company's brand | [`theme-1.json`](https://docs.kapiworks.com/schemas/theme-1.json) |

Pictures, sound and video sit under `media/`, each listed in `media` in `kapi-works.json`. `AGENTS.md` can hold notes for coding agents. The types of the data files, for code: [`kapi-works-package.d.ts`](https://docs.kapiworks.com/schemas/kapi-works-package.d.ts).

## `kapi-works.json`

What the package is, its language, how it plays, and the roles, tests, context, links, media and sources it declares. Every text is a text ID from the words file.

Every course has this file. Its schema: [`https://docs.kapiworks.com/schemas/package-2.json`](https://docs.kapiworks.com/schemas/package-2.json).

- `schema`: `"kapi.works.package/2"`, required. The format, kapi.works.package/2.
- `sdk`: SDK version, required. The SDK the package needs: 2 and a minor, such as 2.0. Kapi serves up to 2.1.
- `id`: ID, required. The package's ID, the same in every version: lower-case letters, digits and hyphens, up to 64 characters.
- `kind`: `"course"`, required. The kind of package: course.
- `courseType`: `"training-course"`, `"scenario-course"`, `"quick-refresher"`, `"certificate-course"`, `"walkthrough"`, `"what-changed"`, `"video"`. What the course is for, which sets the type checks Kapi runs. Left out, the course is a training-course. Only a course has one.
- `title`: text ID, required. The text ID of the package's title, such as course.title.
- `summary`: text ID. The text ID of a one-sentence summary, such as course.summary.
- `label`: text. The author's name for this version: one line, up to 40 characters.
- `languages`: object, required. The package's language and its words file. A package has one language for now.
- `languages.default`: language tag, required. The language, as a BCP 47 tag such as en-GB.
- `languages.files`: object, required. The words file for the default language, and only that one: { "en-GB": "words/en-GB.json" }.
- `view`: object, required. How the package plays: on Kapi's player for its kind.
- `view.player`: `"course"`, required. The player, the same as kind.
- `view.line`: `"1.0"`, required. The player's line: 1.0.
- `state`: text. The version of what the package saves for each person, such as new-hire-welcome/v2.
- `roles`: list of objects. The roles lessons can be required for, up to 32, with IDs all different. Mark one as the default.
- `roles[].id`: ID, required. The role's ID, which lessons name in requiredFor.
- `roles[].title`: text ID, required. The text ID of the role's name.
- `roles[].default`: `true`. true on the role for people whose job role isn't mapped to one of these.
- `assessments`: list of objects. The tests Kapi gives, up to 8, with IDs all different.
- `assessments[].id`: ID, required. The test's ID.
- `assessments[].title`: text ID, required. The text ID of the test's name.
- `assessments[].pool`: list of IDs, required. The IDs of the questions the test draws from. These held questions sit on no page.
- `assessments[].suggest`: object. The test settings Kapi suggests. The company decides.
- `assessments[].suggest.draw`: whole number, required. How many questions each attempt draws, up to 50.
- `assessments[].suggest.passMark`: whole number, required. The pass mark, as a percentage.
- `assessments[].suggest.attempts`: whole number. How many attempts a person gets, up to 10.
- `context`: object. What Kapi fills in when the package opens: required if the package needs it, optional if it works without it. See [Placeholders](https://docs.kapiworks.com/build/reference/placeholders).
- `links`: list of host names. The hosts the words may link to, up to 50. Every link in the words uses https and one of these hosts.
- `media`: list of objects. The package's pictures, sound, video and fonts, with IDs all different. Blocks show them by ID.
- `media[].id`: ID, required. The media ID blocks use, such as laptop-setup.
- `media[].file`: text, required. The file's path under media/, such as media/laptop-setup.png, up to 240 characters.
- `media[].kind`: `"image"`, `"audio"`, `"video"`, `"font"`, required. What the file is. Kapi reads its first bytes, not its name.
- `media[].sha256`: SHA-256 digest. The SHA-256 of a picture the company added in Works Studio, as sha256:\<64 hex digits\>. Kapi keeps that picture, so its file can stay out of the package. A file in the package must have this SHA-256.
- `media[].alt`: text ID or null. The text ID of what the picture shows, in a sentence. A picture needs it unless it's decorative.
- `media[].decorative`: `true`. true for a picture that adds nothing to the words, so screen readers skip it.
- `media[].speech`: true or false. true when the sound or video has speech, which needs captions.
- `media[].captions`: object. A WebVTT captions file under media/ for each language, such as { "en-GB": "media/welcome.vtt" }.
- `sources`: list of objects. The documents the package was made from.
- `sources[].title`: text, required. The document's title, up to 200 characters.
- `sources[].sha256`: SHA-256 digest. The SHA-256 of the document's text, as sha256:\<64 hex digits\>.

## `content.json`

A course's lessons, pages and blocks, in reading order. Every text is a text ID from the words file.

Every course has this file. Its schema: [`https://docs.kapiworks.com/schemas/content-2.json`](https://docs.kapiworks.com/schemas/content-2.json).

- `schema`: `"kapi.works.content/2"`, required. The format, kapi.works.content/2.
- `lessons`: list of lessons, required. The lessons, in order: up to 64 lessons and 200 pages in all.
- `lessons[].id`: ID, required. The lesson's ID. Its text IDs start with it, such as first-week.title. Lesson and page IDs are all different.
- `lessons[].title`: text ID, required. The text ID of the lesson's title.
- `lessons[].minutes`: whole number. About how many minutes the lesson takes, from 1 to 120.
- `lessons[].requiredFor`: list of IDs or null. The role IDs the lesson is required for. null or left out: it's for everyone.
- `lessons[].pages`: list of pages, required. The lesson's pages, in order.
- `lessons[].pages[].id`: page ID, required. The page's ID: lower-case letters, digits and hyphens, up to 48 characters. Its text IDs start with it.
- `lessons[].pages[].title`: text ID, required. The text ID of the page's title.
- `lessons[].pages[].blocks`: list of blocks. What the page shows, from top to bottom. See [Blocks](https://docs.kapiworks.com/build/reference/blocks).

## `words/<language>.json`

Every text in the package, by text ID, up to 1 MiB. A text ID's first part names what it belongs to: a lesson, page or question ID, or course, common, role or assessment. Words take only \*\*strong\*\*, \_emphasis\_, \[label\](https://host/path) links and line breaks.

Every course has this file. Its schema: [`https://docs.kapiworks.com/schemas/words-1.json`](https://docs.kapiworks.com/schemas/words-1.json).

- `<text ID>`: text. The words for this text ID.

## `questions.json`

Every question, with its answer, feedback and explanation. Practice questions sit on pages; held questions sit only in a test's pool.

A course may leave this file out. Its schema: [`https://docs.kapiworks.com/schemas/questions-2.json`](https://docs.kapiworks.com/schemas/questions-2.json).

- `schema`: `"kapi.works.questions/2"`, required. The format, kapi.works.questions/2.
- `questions`: list of questions, required. The questions, up to 2,000. Question IDs are all different. See [Questions](https://docs.kapiworks.com/build/reference/questions).

## `support.json`

Where each answer key and fact comes from, quoted word for word from its source.

A course may leave this file out. Its schema: [`https://docs.kapiworks.com/schemas/support-1.json`](https://docs.kapiworks.com/schemas/support-1.json).

- `schema`: `"kapi.works.support/1"`, required. The format, kapi.works.support/1.
- `items`: list of objects, required. One item for each answer key or fact.
- `items[].for`: text ID or ID, required. The question ID or text ID it supports.
- `items[].source`: SHA-256 digest, required. The source's SHA-256, as in kapi-works.json's sources.
- `items[].unit`: unit ID. The ID of the part of the source the quote is from, such as u2-1.
- `items[].quote`: text, required. The passage, word for word, up to 2,000 characters.

## `look/theme.json`

The package's look, which starts from the company's brand.

A course may leave this file out. Its schema: [`https://docs.kapiworks.com/schemas/theme-1.json`](https://docs.kapiworks.com/schemas/theme-1.json).

- `schema`: `"kapi.works.theme/1"`, required. The format, kapi.works.theme/1.
- `base`: `"company"`, required. What the look starts from: the company's brand.
- `tokens`: object. Changes to the player's look, each within its range.
- `tokens.radius`: number. How round corners are, in pixels, from 0 to 24.
- `tokens.density`: number. How much space there is, as a multiple of the player's, from 0.75 to 1.25.
- `tokens.typeScale`: number. How large text is, as a multiple of the player's, from 0.875 to 1.25.
- `cover`: object. The cover picture.
- `cover.media`: ID, required. The media ID of the cover picture.
- `cover.style`: `"split"`, `"full"`, `"band"`, required. The cover's layout: split, full, band.

## The bundle

A whole package's data as one JSON block, for an AI that writes text rather than files. Long output can come in parts, which Kapi joins in order. Kapi then reads the files as a package, under the same rules as an upload.

Its schema: [`https://docs.kapiworks.com/schemas/bundle-1.json`](https://docs.kapiworks.com/schemas/bundle-1.json).

- `schema`: `"kapi.works.bundle/1"`, required. The format, kapi.works.bundle/1.
- `part`: whole number. This part's number, when the bundle comes in parts. Left out: 1.
- `of`: whole number. How many parts the bundle comes in, up to 20. Left out: 1. Every part gives the same number.
- `files`: object, required. The package's files by path. Media come separately: Kapi asks for them by their IDs.

## What Kapi checks

| Check | Severity | What Kapi says |
| --- | --- | --- |
| [`file_not_allowed`](https://docs.kapiworks.com/build/reference/checks/file-not-allowed) | Error | This file isn't a file a package holds. Remove it, or move it where the docs say it goes. |
| [`unsafe_path`](https://docs.kapiworks.com/build/reference/checks/unsafe-path) | Error | This path isn't safe. Use lower-case relative paths with no "..", backslashes or hidden parts. |
| [`file_type`](https://docs.kapiworks.com/build/reference/checks/file-type) | Error | This file isn't the kind of file its place says. Kapi reads a file's first bytes, not its name. |
| [`not_utf8`](https://docs.kapiworks.com/build/reference/checks/not-utf8) | Error | This file isn't saved as UTF-8 text. Save it again as UTF-8. |
| [`json_invalid`](https://docs.kapiworks.com/build/reference/checks/json-invalid) | Error | This file isn't valid JSON. |
| [`schema_invalid`](https://docs.kapiworks.com/build/reference/checks/schema-invalid) | Error | This value should be as the format says. |
| [`unknown_key`](https://docs.kapiworks.com/build/reference/checks/unknown-key) | Error | "…" isn't part of the format. Remove it, or check its spelling. |
| [`file_missing`](https://docs.kapiworks.com/build/reference/checks/file-missing) | Error | The package needs this file. |
| [`id_duplicate`](https://docs.kapiworks.com/build/reference/checks/id-duplicate) | Error | The … ID is used twice. Every ID must be unique. |
| [`family_not_available`](https://docs.kapiworks.com/build/reference/checks/family-not-available) | Error | Kapi doesn't have a … player yet. Courses play today. |
| [`sdk_too_new`](https://docs.kapiworks.com/build/reference/checks/sdk-too-new) | Error | The package needs a newer SDK than Kapi serves. Kapi serves SDK …. |
| [`player_line_unknown`](https://docs.kapiworks.com/build/reference/checks/player-line-unknown) | Error | There's no such player line. Use …. |


# Blocks

The 15 blocks a course page is made of, and the keys each one takes.

A page's `blocks` hold what the page shows, from top to bottom. Each block has a `"type"`, which sets its other keys. Every text a block shows is a text ID from the words file.

| Block | What it shows |
| --- | --- |
| [`heading`](#heading) | A heading. |
| [`text`](#text) | A paragraph. |
| [`list`](#list) | A list. |
| [`steps`](#steps) | Numbered steps, such as how to use a tool. |
| [`callout`](#callout) | A note that stands out from the page. |
| [`table`](#table) | A table. |
| [`quote`](#quote) | A quotation. |
| [`image`](#image) | A picture. |
| [`audio`](#audio) | A sound. |
| [`video`](#video) | A video. |
| [`film`](#film) | A film Kapi draws and plays from its scenes, with captions, a transcript and questions that pause it. A package with a film says "sdk": "2.1". |
| [`question`](#question) | A practice question, with feedback after each answer. |
| [`contact`](#contact) | A company contact. Where the company hasn't filled it in, the page shows common.contact-missing.\<key\>. |
| [`sources`](#sources) | The titles of the documents the package was made from. |
| [`divider`](#divider) | A line between parts of a page. |

## `heading`

A heading.

- `type`: `"heading"`, required. The block's type.
- `text`: text ID, required. The text ID of the heading.

## `text`

A paragraph.

- `type`: `"text"`, required. The block's type.
- `text`: text ID, required. The text ID of the paragraph.
- `style`: `"body"`, `"lead"`, `"small"`. lead for an opening paragraph, small for a note, or body. Left out: body.

## `list`

A list.

- `type`: `"list"`, required. The block's type.
- `items`: list of text IDs, required. The items, in order.
- `ordered`: true or false. true to number the items.

## `steps`

Numbered steps, such as how to use a tool.

- `type`: `"steps"`, required. The block's type.
- `items`: list of text IDs, required. The steps, in order.

## `callout`

A note that stands out from the page.

- `type`: `"callout"`, required. The block's type.
- `tone`: `"note"`, `"important"`, `"warning"`, required. How strongly it stands out: note, important or warning.
- `text`: text ID, required. The text ID of the note.

## `table`

A table.

- `type`: `"table"`, required. The block's type.
- `header`: list of text IDs. The column headings.
- `rows`: list of lists of text IDs, required. The rows.

## `quote`

A quotation.

- `type`: `"quote"`, required. The block's type.
- `text`: text ID, required. The text ID of the quoted words.
- `cite`: text ID. The text ID of who or what it quotes.

## `image`

A picture.

- `type`: `"image"`, required. The block's type.
- `media`: ID, required. The media ID of a picture in kapi-works.json.

## `audio`

A sound.

- `type`: `"audio"`, required. The block's type.
- `media`: ID, required. The media ID of a sound in kapi-works.json.

## `video`

A video.

- `type`: `"video"`, required. The block's type.
- `media`: ID, required. The media ID of a video in kapi-works.json.

## `film`

A film Kapi draws and plays from its scenes, with captions, a transcript and questions that pause it. A package with a film says "sdk": "2.1".

- `type`: `"film"`, required. The block's type.
- `scenes`: list of film-scenes, required. The scenes, in order: 2 to 30, up to 10 minutes in all. Scene IDs are all different.
- `emails`: list of film-emails. The emails the film's email scenes show, with IDs all different: up to 4.
- `emails[].id`: ID, required. The email's ID, which email scenes name.
- `emails[].from`: text ID, required. The text ID of the sender's name.
- `emails[].address`: text ID, required. The text ID of the sender's address. Use an address that ends in .example.
- `emails[].subject`: text ID, required. The text ID of the subject.
- `emails[].lines`: list of text IDs, required. The email's lines.
- `emails[].button`: text ID. The text ID of a button in the email.
- `emails[].link`: text ID. The text ID of the address the button really goes to, shown when the pointer rests on it.
- `emails[].attachment`: text ID. The text ID of an attached file's name.
- `style`: text. CSS for the film's drawing scenes, up to 32000 bytes. It may use @keyframes, @media and @supports rules, and no addresses: url() names only a part of the same drawing. Kapi's clock plays every animation it starts, and every part sizes with box-sizing: border-box. The canvas is .kw-canvas; while a scene waits for a tap it also has .kw-targeting, and a tapped target has .kw-right or .kw-wrong. A part chosen for a question with several right parts has .kw-chosen, and every chosen part has .kw-right once the answer is right.

### Scenes

A scene of a film. Its layout sets the keys it takes.

- `scenes[].id`: ID, required. The scene's ID.
- `scenes[].title`: text ID, required. The text ID of the scene's name, shown in the transcript and on the seek bar.
- `scenes[].seconds`: number, required. How long the scene runs, from 4 to 60 seconds, in tenths at most, such as 6.5.
- `scenes[].layout`: `"title"`, `"number"`, `"email"`, `"chat"`, `"person"`, `"icons"`, `"checklist"`, `"drawing"`, required. The drawn layout.
- `scenes[].caption`: text ID, required. The text ID of what the narrator says, shown as captions. Short sentences, and never a placeholder.
- `scenes[].picture`: text ID, required. The text ID of what the scene shows, for the transcript and screen readers.
- `scenes[].headline`: text ID. The text ID of a few words on the picture.
- `scenes[].pause`: ID. The ID of a choice or multi practice question the film stops for after this scene. No page or test pool may hold it too.

### `title` scenes

A title card.

- `scenes[].heading`: text ID, required. The text ID of the title.
- `scenes[].kicker`: text ID. The text ID of a small line above it.

### `number` scenes

A number that counts up, with its label.

- `scenes[].number`: text ID, required. The text ID of the number, such as 38%.
- `scenes[].label`: text ID, required. The text ID of what the number counts.
- `scenes[].note`: text ID. The text ID of a small line under it, such as where the number comes from.

### `email` scenes

An email from this film's emails. Each beat moves the camera to the part it marks, in order.

- `scenes[].email`: ID, required. The ID of an email in this film's emails.
- `scenes[].beats`: list of `"arrive"`, `"mark-from"`, `"reveal-address"`, `"mark-subject"`, `"mark-lines"`, `"point-link"`, `"mark-attachment"`, `"report"`. What happens, in order. Left out: the email shows still.

### `chat` scenes

Chat messages that arrive one by one.

- `scenes[].messages`: list of objects, required. The messages, in order.
- `scenes[].messages[].who`: text ID, required. The text ID of who sends it.
- `scenes[].messages[].text`: text ID, required. The text ID of the message.
- `scenes[].mark`: whole number. The number of the message to mark as the one to notice, counting from 1.

### `person` scenes

A drawn person at work, on a call with someone else or saying something.

- `scenes[].label`: text ID, required. The text ID of who it is, such as You.
- `scenes[].prop`: `"phone"`, `"laptop"`, `"none"`, required. What they hold: a phone, a laptop, or none.
- `scenes[].with`: text ID. The text ID of who they're talking to, which draws a call.
- `scenes[].says`: text ID. The text ID of what they say, in a speech bubble.

### `icons` scenes

Icons with their words, each in turn.

- `scenes[].items`: list of objects, required. The icons, in order.
- `scenes[].items[].icon`: `"search"`, `"phone"`, `"flag"`, `"mail"`, `"link"`, `"file"`, `"lock"`, `"key"`, `"shield"`, `"alert"`, `"check"`, `"clock"`, `"card"`, `"person"`, required. The icon.
- `scenes[].items[].text`: text ID, required. The text ID of its words.

### `checklist` scenes

A checklist that ticks each item in turn.

- `scenes[].items`: list of text IDs, required. The items, in order.

### `drawing` scenes

A scene the author draws on a 960 by 540 canvas, with the film's style.

- `scenes[].drawing`: text, required. The scene's markup, up to 16000 bytes: div, span, p, b, strong, i, em, u, s, small, sup, sub, br, ul, ol, li, and inside an svg svg, g, path, rect, circle, ellipse, line, polyline, polygon, defs, linearGradient, radialGradient, stop, clipPath, with only class, style, id, aria-hidden, data-text, data-count, data-from, data-d, data-du, data-target, viewBox, width, height, x, y, x1, y1, x2, y2, cx, cy, r, rx, ry, fx, fy, d, points, fill, fill-opacity, fill-rule, clip-rule, clip-path, stroke, stroke-width, stroke-linejoin, stroke-linecap, stroke-dasharray, stroke-opacity, opacity, offset, stop-color, stop-opacity, transform, gradientUnits, gradientTransform, preserveAspectRatio. Every word is a text ID on an empty element, such as \<span data-text="intro.name"\>\</span\>. data-count counts a number up from data-from, after data-d seconds over data-du seconds. data-target makes a part a choice of the question the scene stops for, tapped on the picture: a choice question takes one tap, and a multi question takes every right part, then Check answer.

## `question`

A practice question, with feedback after each answer.

- `type`: `"question"`, required. The block's type.
- `question`: ID, required. The ID of a question in questions.json that isn't in a test's pool.

## `contact`

A company contact. Where the company hasn't filled it in, the page shows common.contact-missing.\<key\>.

- `type`: `"contact"`, required. The block's type.
- `contact`: ID, required. The contact's key, such as it-help, declared in context as contacts.it-help.

## `sources`

The titles of the documents the package was made from.

- `type`: `"sources"`, required. The block's type.

## `divider`

A line between parts of a page.

- `type`: `"divider"`, required. The block's type.

## What Kapi checks

| Check | Severity | What Kapi says |
| --- | --- | --- |
| [`reference_unknown`](https://docs.kapiworks.com/build/reference/checks/reference-unknown) | Error | This names …, which the package doesn't declare. |
| [`word_missing`](https://docs.kapiworks.com/build/reference/checks/word-missing) | Error | The words file has no text for …. |
| [`word_owner`](https://docs.kapiworks.com/build/reference/checks/word-owner) | Error | …'s first part names nothing in the package. Start a text ID with its lesson, page or question ID, or course, common, role or assessment. |
| [`word_unused`](https://docs.kapiworks.com/build/reference/checks/word-unused) | Warning | … isn't used anywhere. Remove it, or use it. |
| [`markup_not_allowed`](https://docs.kapiworks.com/build/reference/checks/markup-not-allowed) | Error | These words use …. Words take only \*\*strong\*\*, \_emphasis\_, \[label\](https://host/path) links and line breaks. |
| [`link_not_https`](https://docs.kapiworks.com/build/reference/checks/link-not-https) | Error | The link to … must start with https://. |
| [`link_host_undeclared`](https://docs.kapiworks.com/build/reference/checks/link-host-undeclared) | Error | These words link to …, which kapi-works.json doesn't list in links. Add the host if people may open it. |
| [`alt_missing`](https://docs.kapiworks.com/build/reference/checks/alt-missing) | Error | This picture needs alt text, or mark it decorative. |
| [`captions_missing`](https://docs.kapiworks.com/build/reference/checks/captions-missing) | Error | Sound or video with speech needs captions. |
| [`media_file_missing`](https://docs.kapiworks.com/build/reference/checks/media-file-missing) | Error | The package has no file …. |
| [`media_not_listed`](https://docs.kapiworks.com/build/reference/checks/media-not-listed) | Error | This media file isn't listed in kapi-works.json. |


# Questions

Question kinds, answer keys, feedback and explanations, and the held questions Kapi's test draws from.

Every question, with its answer, feedback and explanation. Practice questions sit on pages; held questions sit only in a test's pool.

## Every question

A question. Its kind sets the keys it takes besides id, kind, prompt, situation and explanation.

- `id`: ID, required. The question's ID. Its text IDs start with it, such as q1.prompt.
- `kind`: `"choice"`, `"multi"`, `"exact"`, `"order"`, `"match"`, required. The question's kind.
- `prompt`: text ID, required. The text ID of the question.
- `situation`: text ID. The text ID of the situation it's set in, shown before the question.
- `explanation`: text ID. The text ID of why the answer is right, shown after an answer.

## Kinds

| Kind | What it asks |
| --- | --- |
| [`choice`](#choice) | One right choice. |
| [`multi`](#multi) | One or more right choices. |
| [`exact`](#exact) | A typed answer. |
| [`order`](#order) | Put items in order. |
| [`match`](#match) | Sort items into groups. |

## `choice`

One right choice.

- `choices`: list of choices, required. The choices.
- `choices[].id`: ID, required. The choice's ID.
- `choices[].text`: text ID, required. The text ID of the choice.
- `choices[].feedback`: text ID. The text ID of why this choice is right or wrong, shown after an answer.
- `answer`: ID, required. The ID of the right choice.

## `multi`

One or more right choices.

- `choices`: list of choices, required. The choices.
- `choices[].id`: ID, required. The choice's ID.
- `choices[].text`: text ID, required. The text ID of the choice.
- `choices[].feedback`: text ID. The text ID of why this choice is right or wrong, shown after an answer.
- `answer`: list of IDs, required. The IDs of every right choice.

## `exact`

A typed answer.

- `accepted`: list of texts, required. The answers Kapi accepts, as the words themselves.
- `match`: `"prose"`, `"exact"`, required. prose ignores case, accents, punctuation and extra spaces. exact keeps them all, for code and symbols.

## `order`

Put items in order.

- `items`: list of items, required. The items.
- `items[].id`: ID, required. Its ID.
- `items[].text`: text ID, required. The text ID of its words.
- `answer`: list of IDs, required. The item IDs, in the right order.

## `match`

Sort items into groups.

- `items`: list of items, required. The items to sort.
- `items[].id`: ID, required. Its ID.
- `items[].text`: text ID, required. The text ID of its words.
- `groups`: list of items, required. The groups.
- `groups[].id`: ID, required. Its ID.
- `groups[].text`: text ID, required. The text ID of its words.
- `answer`: object, required. Each item's ID, with the ID of its group.

## Choices and items

Each choice in `choices`:

- `id`: ID, required. The choice's ID.
- `text`: text ID, required. The text ID of the choice.
- `feedback`: text ID. The text ID of why this choice is right or wrong, shown after an answer.

Each item or group in `items` and `groups`:

- `id`: ID, required. Its ID.
- `text`: text ID, required. The text ID of its words.

## Practice and the test

A practice question sits on one page, in a `question` block, and shows its feedback and explanation after an answer. A held question sits only in a test's `pool`, in `assessments` in `kapi-works.json`, and Kapi's test draws from it.

- `assessments[].id`: ID, required. The test's ID.
- `assessments[].title`: text ID, required. The text ID of the test's name.
- `assessments[].pool`: list of IDs, required. The IDs of the questions the test draws from. These held questions sit on no page.
- `assessments[].suggest`: object. The test settings Kapi suggests. The company decides.
- `assessments[].suggest.draw`: whole number, required. How many questions each attempt draws, up to 50.
- `assessments[].suggest.passMark`: whole number, required. The pass mark, as a percentage.
- `assessments[].suggest.attempts`: whole number. How many attempts a person gets, up to 10.

## What Kapi checks

| Check | Severity | What Kapi says |
| --- | --- | --- |
| [`answer_key_invalid`](https://docs.kapiworks.com/build/reference/checks/answer-key-invalid) | Error | The answer key …. |
| [`explanation_missing`](https://docs.kapiworks.com/build/reference/checks/explanation-missing) | Error | This question has no explanation of why the answer is right. |
| [`feedback_missing`](https://docs.kapiworks.com/build/reference/checks/feedback-missing) | Error | Choice … has no feedback. Every choice says why it's right or wrong. |
| [`held_question_on_page`](https://docs.kapiworks.com/build/reference/checks/held-question-on-page) | Error | This question is in …'s pool, so it can't also sit on a page. Kapi's test would show it again. |
| [`held_kind_not_allowed`](https://docs.kapiworks.com/build/reference/checks/held-kind-not-allowed) | Error | Kapi's test takes choice and multi questions only. |
| [`pool_too_small`](https://docs.kapiworks.com/build/reference/checks/pool-too-small) | Error | The pool holds fewer questions than the test draws (…). |
| [`pool_small`](https://docs.kapiworks.com/build/reference/checks/pool-small) | Warning | The pool holds less than one and a half times the draw (…), so retakes repeat questions. |
| [`question_unused`](https://docs.kapiworks.com/build/reference/checks/question-unused) | Warning | No page or pool uses this question. |
| [`few_situations`](https://docs.kapiworks.com/build/reference/checks/few-situations) | Tip | … Questions set in a situation check that people can use what they learned. |


# Placeholders

The words Kapi fills in when a person opens a course: the company's name, its contacts and the learner's first name.

Words can hold placeholders in braces. Kapi fills them in from the company's settings when a person opens the course. Declare each one in `context` in `kapi-works.json`: `"required"` when the course needs it, `"optional"` when it works without it.

| Placeholder | Declare in `context` | What Kapi fills in |
| --- | --- | --- |
| `{company.name}` | `company.name` | The company's name, for {company.name}. |
| `{learner.firstName}` | `learner.firstName` | The person's first name, for {learner.firstName}, where the company switches it on. |
| `{contacts.<key>.name}`, `{contacts.<key>.email}`, `{contacts.<key>.phone}`, `{contacts.<key>.url}` | `contacts.<key>` | A contact the company fills in, such as contacts.it-help, for {contacts.it-help.name}, .email, .phone and .url. |

A `contact` block shows a whole contact, by its key. Where the company hasn't filled in an optional contact, the page shows `common.contact-missing.<key>` from the words file instead.

## Context without a placeholder

Kapi gives a course these too. Words can't name them.

| Key | What it is |
| --- | --- |
| `door` | Which door the person learns through: employee, partner or customer. |
| `role` | The person's role, one of roles. |

## What Kapi checks

| Check | Severity | What Kapi says |
| --- | --- | --- |
| [`placeholder_unknown`](https://docs.kapiworks.com/build/reference/checks/placeholder-unknown) | Error | … isn't a placeholder Kapi fills. Use {company.name}, {contacts.\<key\>.name}, .email, .phone, .url or {learner.firstName}. |
| [`placeholder_undeclared`](https://docs.kapiworks.com/build/reference/checks/placeholder-undeclared) | Error | These words use a placeholder, but kapi-works.json doesn't declare … in context. |
| [`placeholder_in_link`](https://docs.kapiworks.com/build/reference/checks/placeholder-in-link) | Error | A link address can't hold a placeholder. Kapi checks every address before a learner opens it. |
| [`first_name_twin_missing`](https://docs.kapiworks.com/build/reference/checks/first-name-twin-missing) | Error | These words use {learner.firstName}, so they need a twin, …, for people whose first name isn't given. |
| [`contact_missing_word`](https://docs.kapiworks.com/build/reference/checks/contact-missing-word) | Error | This contact is optional, so write … for companies that haven't filled it in. |
| [`context_not_allowed`](https://docs.kapiworks.com/build/reference/checks/context-not-allowed) | Error | … can't be required for customers. Kapi never gives it in a customer door. |


# Limits

Every limit Kapi's reader and checker hold a course to.

Kapi holds every course to these limits when it reads and checks it. A MiB is 1,048,576 bytes; an MB is 1,000,000.

| Limit | Value |
| --- | --- |
| Pages in a course | 200 |
| Lessons in a course | 64 |
| Questions in questions.json | 2,000 |
| Fewest choices in a question | 2 |
| Most choices in a question | 10 |
| Longest typed answer Kapi accepts | 512 bytes |
| Tests in a course | 8 |
| Most questions one attempt at a test draws | 50 |
| All data files together | 4 MiB |
| One words file | 1 MiB |
| Files the player loads for a page, besides media | 5 MiB |
| One picture, sound or video | 25 MB |
| Files in a course | 300 |
| Hosts the words may link to | 50 |
| Roles | 32 |
| Characters in a text ID | 128 |
| Characters in a file path | 240 |

## What Kapi checks

| Check | Severity | What Kapi says |
| --- | --- | --- |
| [`over_limit`](https://docs.kapiworks.com/build/reference/checks/over-limit) | Error | This is over the limit of …. |
| [`media_too_large`](https://docs.kapiworks.com/build/reference/checks/media-too-large) | Error | This file is over 25 MB, the most a page can carry. Make it smaller. |


# Checks

Every check Kapi runs on a course, with its severity, the course types it runs for and what it says.

Kapi's checker reads a course, then runs every check on it. Works Studio, Kapi's server and [Check a course](https://docs.kapiworks.com/build/check) all run the same code, checker 2.2.0. A course's type adds the checks listed on [its page](https://docs.kapiworks.com/build).

## Severity

* **Error**: it blocks approval until it is fixed.
* **Warning**: it does not block approval. The approver sees it.
* **Tip**: advice. It does not block approval.

Some checks are stricter in a course Kapi makes from your documents. Each check's page says so.

## A finding

The checker reports `kapi.works.check/2`. Each finding has:

* `code`: the check, such as `feedback_missing`. A code keeps its meaning.
* `severity`: `error`, `warning` or `tip`.
* `where`: the `file`, a JSON Pointer to the place in it, and the page, question or text it concerns.
* `message`: what is wrong, in words for people.
* `fixes`: when Kapi knows the fix, the change to make.
* `docs`: the address of the check's page here.

In Works Studio, **Let Kapi fix** takes the findings it can fix: those to write or change, apart from tips, the choices that are yours and quotes that need your documents.

## Every check

| Check | Severity | Course type | What Kapi says |
| --- | --- | --- | --- |
| [`file_not_allowed`](https://docs.kapiworks.com/build/reference/checks/file-not-allowed) | Error | Every type | This file isn't a file a package holds. Remove it, or move it where the docs say it goes. |
| [`unsafe_path`](https://docs.kapiworks.com/build/reference/checks/unsafe-path) | Error | Every type | This path isn't safe. Use lower-case relative paths with no "..", backslashes or hidden parts. |
| [`file_type`](https://docs.kapiworks.com/build/reference/checks/file-type) | Error | Every type | This file isn't the kind of file its place says. Kapi reads a file's first bytes, not its name. |
| [`not_utf8`](https://docs.kapiworks.com/build/reference/checks/not-utf8) | Error | Every type | This file isn't saved as UTF-8 text. Save it again as UTF-8. |
| [`json_invalid`](https://docs.kapiworks.com/build/reference/checks/json-invalid) | Error | Every type | This file isn't valid JSON. |
| [`schema_invalid`](https://docs.kapiworks.com/build/reference/checks/schema-invalid) | Error | Every type | This value should be as the format says. |
| [`unknown_key`](https://docs.kapiworks.com/build/reference/checks/unknown-key) | Error | Every type | "…" isn't part of the format. Remove it, or check its spelling. |
| [`file_missing`](https://docs.kapiworks.com/build/reference/checks/file-missing) | Error | Every type | The package needs this file. |
| [`over_limit`](https://docs.kapiworks.com/build/reference/checks/over-limit) | Error | Every type | This is over the limit of …. |
| [`family_not_available`](https://docs.kapiworks.com/build/reference/checks/family-not-available) | Error | Every type | Kapi doesn't have a … player yet. Courses play today. |
| [`sdk_too_new`](https://docs.kapiworks.com/build/reference/checks/sdk-too-new) | Error | Every type | The package needs a newer SDK than Kapi serves. Kapi serves SDK …. |
| [`player_line_unknown`](https://docs.kapiworks.com/build/reference/checks/player-line-unknown) | Error | Every type | There's no such player line. Use …. |
| [`id_duplicate`](https://docs.kapiworks.com/build/reference/checks/id-duplicate) | Error | Every type | The … ID is used twice. Every ID must be unique. |
| [`reference_unknown`](https://docs.kapiworks.com/build/reference/checks/reference-unknown) | Error | Every type | This names …, which the package doesn't declare. |
| [`role_default_missing`](https://docs.kapiworks.com/build/reference/checks/role-default-missing) | Error | Every type | Mark exactly one role as the default, for people whose job role isn't mapped. |
| [`word_missing`](https://docs.kapiworks.com/build/reference/checks/word-missing) | Error | Every type | The words file has no text for …. |
| [`word_owner`](https://docs.kapiworks.com/build/reference/checks/word-owner) | Error | Every type | …'s first part names nothing in the package. Start a text ID with its lesson, page or question ID, or course, common, role or assessment. |
| [`word_unused`](https://docs.kapiworks.com/build/reference/checks/word-unused) | Warning | Every type | … isn't used anywhere. Remove it, or use it. |
| [`markup_not_allowed`](https://docs.kapiworks.com/build/reference/checks/markup-not-allowed) | Error | Every type | These words use …. Words take only **strong**, _emphasis_, [label](https://host/path) links and line breaks. |
| [`link_not_https`](https://docs.kapiworks.com/build/reference/checks/link-not-https) | Error | Every type | The link to … must start with https://. |
| [`link_host_undeclared`](https://docs.kapiworks.com/build/reference/checks/link-host-undeclared) | Error | Every type | These words link to …, which kapi-works.json doesn't list in links. Add the host if people may open it. |
| [`placeholder_unknown`](https://docs.kapiworks.com/build/reference/checks/placeholder-unknown) | Error | Every type | … isn't a placeholder Kapi fills. Use {company.name}, {contacts.<key>.name}, .email, .phone, .url or {learner.firstName}. |
| [`placeholder_undeclared`](https://docs.kapiworks.com/build/reference/checks/placeholder-undeclared) | Error | Every type | These words use a placeholder, but kapi-works.json doesn't declare … in context. |
| [`placeholder_in_link`](https://docs.kapiworks.com/build/reference/checks/placeholder-in-link) | Error | Every type | A link address can't hold a placeholder. Kapi checks every address before a learner opens it. |
| [`first_name_twin_missing`](https://docs.kapiworks.com/build/reference/checks/first-name-twin-missing) | Error | Every type | These words use {learner.firstName}, so they need a twin, …, for people whose first name isn't given. |
| [`contact_missing_word`](https://docs.kapiworks.com/build/reference/checks/contact-missing-word) | Error | Every type | This contact is optional, so write … for companies that haven't filled it in. |
| [`claim_word`](https://docs.kapiworks.com/build/reference/checks/claim-word) | Warning | Every type | "…" is a claim Kapi can't stand behind. Say what the course does instead. |
| [`closing_names_ending`](https://docs.kapiworks.com/build/reference/checks/closing-names-ending) | Warning | Every type | The closing words name "…". Endings are the company's rules, so the closing should only say the learning is finished. |
| [`answer_key_invalid`](https://docs.kapiworks.com/build/reference/checks/answer-key-invalid) | Error | Every type | The answer key …. |
| [`explanation_missing`](https://docs.kapiworks.com/build/reference/checks/explanation-missing) | Error | Every type | This question has no explanation of why the answer is right. |
| [`feedback_missing`](https://docs.kapiworks.com/build/reference/checks/feedback-missing) | Error | Every type | Choice … has no feedback. Every choice says why it's right or wrong. |
| [`held_question_on_page`](https://docs.kapiworks.com/build/reference/checks/held-question-on-page) | Error | Every type | This question is in …'s pool, so it can't also sit on a page. Kapi's test would show it again. |
| [`held_kind_not_allowed`](https://docs.kapiworks.com/build/reference/checks/held-kind-not-allowed) | Error | Every type | Kapi's test takes choice and multi questions only. |
| [`pool_too_small`](https://docs.kapiworks.com/build/reference/checks/pool-too-small) | Error | Every type | The pool holds fewer questions than the test draws (…). |
| [`pool_small`](https://docs.kapiworks.com/build/reference/checks/pool-small) | Warning | Every type | The pool holds less than one and a half times the draw (…), so retakes repeat questions. |
| [`question_unused`](https://docs.kapiworks.com/build/reference/checks/question-unused) | Warning | Every type | No page or pool uses this question. |
| [`media_file_missing`](https://docs.kapiworks.com/build/reference/checks/media-file-missing) | Error | Every type | The package has no file …. |
| [`media_sha256_mismatch`](https://docs.kapiworks.com/build/reference/checks/media-sha256-mismatch) | Error | Every type | This file's SHA-256 doesn't match the one kapi-works.json lists for it. Use the file it lists, or list this file's SHA-256. |
| [`media_not_listed`](https://docs.kapiworks.com/build/reference/checks/media-not-listed) | Error | Every type | This media file isn't listed in kapi-works.json. |
| [`alt_missing`](https://docs.kapiworks.com/build/reference/checks/alt-missing) | Error | Every type | This picture needs alt text, or mark it decorative. |
| [`captions_missing`](https://docs.kapiworks.com/build/reference/checks/captions-missing) | Error | Every type | Sound or video with speech needs captions. |
| [`media_too_large`](https://docs.kapiworks.com/build/reference/checks/media-too-large) | Error | Every type | This file is over 25 MB, the most a page can carry. Make it smaller. |
| [`context_not_allowed`](https://docs.kapiworks.com/build/reference/checks/context-not-allowed) | Error | Every type | … can't be required for customers. Kapi never gives it in a customer door. |
| [`starter_words_left`](https://docs.kapiworks.com/build/reference/checks/starter-words-left) | Error | Every type | The starter's sample words are still here (…). Replace them with your own. |
| [`starter_media_left`](https://docs.kapiworks.com/build/reference/checks/starter-media-left) | Error | Every type | This is still the starter's sample file. Replace it with your own. |
| [`support_missing`](https://docs.kapiworks.com/build/reference/checks/support-missing) | Warning | Every type | This answer key has no quote from a source in support.json. |
| [`support_target_unknown`](https://docs.kapiworks.com/build/reference/checks/support-target-unknown) | Error | Every type | support.json names …, which is neither a question nor a text in the package. |
| [`source_not_linked`](https://docs.kapiworks.com/build/reference/checks/source-not-linked) | Warning | Every type | Kapi can't check this quote until its source is linked to the draft. |
| [`quote_not_found`](https://docs.kapiworks.com/build/reference/checks/quote-not-found) | Error | Every type | This quote isn't in its source, word for word. |
| [`fact_not_in_source`](https://docs.kapiworks.com/build/reference/checks/fact-not-in-source) | Warning | Every type | … isn't in any source this cites. Check it against the source. |
| [`lesson_long`](https://docs.kapiworks.com/build/reference/checks/lesson-long) | Tip | Every type | This lesson runs about … minutes. People keep more from lessons of 4 to 7. |
| [`sentence_long`](https://docs.kapiworks.com/build/reference/checks/sentence-long) | Tip | Every type | … Shorter sentences are easier to read, especially in a second language. |
| [`few_situations`](https://docs.kapiworks.com/build/reference/checks/few-situations) | Tip | Every type | … Questions set in a situation check that people can use what they learned. |
| [`film_sdk`](https://docs.kapiworks.com/build/reference/checks/film-sdk) | Error | Every type | This package has a film, so kapi-works.json needs "sdk": "2.1". |
| [`narration_placeholder`](https://docs.kapiworks.com/build/reference/checks/narration-placeholder) | Error | Every type | Narration can't hold a placeholder. Kapi records it once for every company, so say "your company" or "your IT team" instead. |
| [`pause_question_kind`](https://docs.kapiworks.com/build/reference/checks/pause-question-kind) | Error | Every type | A film can stop only for a choice or multi question. |
| [`pause_question_elsewhere`](https://docs.kapiworks.com/build/reference/checks/pause-question-elsewhere) | Error | Every type | This question also …. A question a film stops for belongs to that film only. |
| [`drawing_target_unknown`](https://docs.kapiworks.com/build/reference/checks/drawing-target-unknown) | Error | Every type | This drawing's target … names no choice of the question the scene stops for. |
| [`drawing_target_missing`](https://docs.kapiworks.com/build/reference/checks/drawing-target-missing) | Error | Every type | The choice … of the question this scene stops for has no target in the drawing, so nobody could tap it. |
| [`lesson_without_question`](https://docs.kapiworks.com/build/reference/checks/lesson-without-question) | Warning | Training course | … has no practice question. A question in each lesson helps people keep what they read. |
| [`scenario_opening_missing`](https://docs.kapiworks.com/build/reference/checks/scenario-opening-missing) | Error | Scenario practice | … doesn't open with a situation to choose from. In scenario practice, each lesson starts with a situation and a choice. |
| [`refresher_question_first`](https://docs.kapiworks.com/build/reference/checks/refresher-question-first) | Error | Quick refresher | This page doesn't start with its question. In a quick refresher, every page asks first and the feedback teaches. |
| [`refresher_too_long`](https://docs.kapiworks.com/build/reference/checks/refresher-too-long) | Warning | Quick refresher | This refresher takes about … minutes. A quick refresher takes 8 to 12. |
| [`certificate_pool_small`](https://docs.kapiworks.com/build/reference/checks/certificate-pool-small) | Error | Certificate course | A certificate test needs a pool at least twice the size of its draw (…), so each retake asks different questions. |
| [`certificate_pass_mark_missing`](https://docs.kapiworks.com/build/reference/checks/certificate-pass-mark-missing) | Warning | Certificate course | The test suggests no pass mark. The company can change it, but a certificate course should suggest one. |
| [`walkthrough_steps_missing`](https://docs.kapiworks.com/build/reference/checks/walkthrough-steps-missing) | Error | Step-by-step walkthrough | … has no numbered steps. A walkthrough shows each step in order. |
| [`walkthrough_picture_missing`](https://docs.kapiworks.com/build/reference/checks/walkthrough-picture-missing) | Tip | Step-by-step walkthrough | These steps have no picture. A screenshot of each step helps people follow along. |
| [`change_before_missing`](https://docs.kapiworks.com/build/reference/checks/change-before-missing) | Error | What changed | … doesn't show the old rule. Show it once, starting "Before" and the date it changed. |
| [`change_question_missing`](https://docs.kapiworks.com/build/reference/checks/change-question-missing) | Error | What changed | … has no situation question about the change. |
| [`video_opening_missing`](https://docs.kapiworks.com/build/reference/checks/video-opening-missing) | Error | Video | … doesn't open with a film. In a video, each lesson starts with its film. |


# file_not_allowed

This file isn't a file a package holds. Remove it, or move it where the docs say it goes.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a file to add, replace or remove.

## How to fix it

Add, replace or remove the file the finding names.

[Files](https://docs.kapiworks.com/build/reference/files) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# unsafe_path

This path isn't safe. Use lower-case relative paths with no "..", backslashes or hidden parts.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a file to add, replace or remove.

## How to fix it

Add, replace or remove the file the finding names.

[Files](https://docs.kapiworks.com/build/reference/files) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# file_type

This file isn't the kind of file its place says. Kapi reads a file's first bytes, not its name.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a file to add, replace or remove.

## How to fix it

Add, replace or remove the file the finding names.

[Files](https://docs.kapiworks.com/build/reference/files) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# not_utf8

This file isn't saved as UTF-8 text. Save it again as UTF-8.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a file to add, replace or remove.

## How to fix it

Add, replace or remove the file the finding names.

[Files](https://docs.kapiworks.com/build/reference/files) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# json_invalid

This file isn't valid JSON.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a file to add, replace or remove.

## How to fix it

Add, replace or remove the file the finding names.

[Files](https://docs.kapiworks.com/build/reference/files) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# schema_invalid

This value should be as the format says.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Files](https://docs.kapiworks.com/build/reference/files) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# unknown_key

"…" isn't part of the format. Remove it, or check its spelling.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Files](https://docs.kapiworks.com/build/reference/files) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# file_missing

The package needs this file.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a file to add, replace or remove.

## How to fix it

Add, replace or remove the file the finding names.

[Files](https://docs.kapiworks.com/build/reference/files) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# over_limit

This is over the limit of ….

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Limits](https://docs.kapiworks.com/build/reference/limits) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# family_not_available

Kapi doesn't have a … player yet. Courses play today.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you, with a choice that is yours to make.

## How to fix it

Decide, then change the course to match. The finding's `fixes` says what to decide and holds the change that follows.

[Files](https://docs.kapiworks.com/build/reference/files) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# sdk_too_new

The package needs a newer SDK than Kapi serves. Kapi serves SDK ….

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Files](https://docs.kapiworks.com/build/reference/files) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# player_line_unknown

There's no such player line. Use ….

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Files](https://docs.kapiworks.com/build/reference/files) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# id_duplicate

The … ID is used twice. Every ID must be unique.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Files](https://docs.kapiworks.com/build/reference/files) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# reference_unknown

This names …, which the package doesn't declare.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Blocks](https://docs.kapiworks.com/build/reference/blocks) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# role_default_missing

Mark exactly one role as the default, for people whose job role isn't mapped.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# word_missing

The words file has no text for ….

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Blocks](https://docs.kapiworks.com/build/reference/blocks) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# word_owner

…'s first part names nothing in the package. Start a text ID with its lesson, page or question ID, or course, common, role or assessment.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Blocks](https://docs.kapiworks.com/build/reference/blocks) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# word_unused

… isn't used anywhere. Remove it, or use it.

- Severity: **Warning**. It doesn't block approval. The approver sees it.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Blocks](https://docs.kapiworks.com/build/reference/blocks) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# markup_not_allowed

These words use …. Words take only \*\*strong\*\*, \_emphasis\_, \[label\](https://host/path) links and line breaks.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Blocks](https://docs.kapiworks.com/build/reference/blocks) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# link_not_https

The link to … must start with https://.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Blocks](https://docs.kapiworks.com/build/reference/blocks) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# link_host_undeclared

These words link to …, which kapi-works.json doesn't list in links. Add the host if people may open it.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you, with a choice that is yours to make.

## How to fix it

Decide, then change the course to match. The finding's `fixes` says what to decide and holds the change that follows.

[Blocks](https://docs.kapiworks.com/build/reference/blocks) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# placeholder_unknown

… isn't a placeholder Kapi fills. Use {company.name}, {contacts.\<key\>.name}, .email, .phone, .url or {learner.firstName}.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Placeholders](https://docs.kapiworks.com/build/reference/placeholders) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# placeholder_undeclared

These words use a placeholder, but kapi-works.json doesn't declare … in context.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Placeholders](https://docs.kapiworks.com/build/reference/placeholders) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# placeholder_in_link

A link address can't hold a placeholder. Kapi checks every address before a learner opens it.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Placeholders](https://docs.kapiworks.com/build/reference/placeholders) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# first_name_twin_missing

These words use {learner.firstName}, so they need a twin, …, for people whose first name isn't given.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Placeholders](https://docs.kapiworks.com/build/reference/placeholders) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# contact_missing_word

This contact is optional, so write … for companies that haven't filled it in.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Placeholders](https://docs.kapiworks.com/build/reference/placeholders) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# claim_word

"…" is a claim Kapi can't stand behind. Say what the course does instead.

- Severity: **Warning**. It doesn't block approval. The approver sees it.
- In a course Kapi makes from your documents: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# closing_names_ending

The closing words name "…". Endings are the company's rules, so the closing should only say the learning is finished.

- Severity: **Warning**. It doesn't block approval. The approver sees it.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# answer_key_invalid

The answer key ….

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Questions](https://docs.kapiworks.com/build/reference/questions) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# explanation_missing

This question has no explanation of why the answer is right.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Questions](https://docs.kapiworks.com/build/reference/questions) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# feedback_missing

Choice … has no feedback. Every choice says why it's right or wrong.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Questions](https://docs.kapiworks.com/build/reference/questions) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# held_question_on_page

This question is in …'s pool, so it can't also sit on a page. Kapi's test would show it again.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Questions](https://docs.kapiworks.com/build/reference/questions) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# held_kind_not_allowed

Kapi's test takes choice and multi questions only.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Questions](https://docs.kapiworks.com/build/reference/questions) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# pool_too_small

The pool holds fewer questions than the test draws (…).

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Questions](https://docs.kapiworks.com/build/reference/questions) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# pool_small

The pool holds less than one and a half times the draw (…), so retakes repeat questions.

- Severity: **Warning**. It doesn't block approval. The approver sees it.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Questions](https://docs.kapiworks.com/build/reference/questions) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# question_unused

No page or pool uses this question.

- Severity: **Warning**. It doesn't block approval. The approver sees it.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Questions](https://docs.kapiworks.com/build/reference/questions) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# media_file_missing

The package has no file ….

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a file to add, replace or remove.

## How to fix it

Add, replace or remove the file the finding names.

[Blocks](https://docs.kapiworks.com/build/reference/blocks) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# media_sha256_mismatch

This file's SHA-256 doesn't match the one kapi-works.json lists for it. Use the file it lists, or list this file's SHA-256.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a file to add, replace or remove.

## How to fix it

Add, replace or remove the file the finding names.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# media_not_listed

This media file isn't listed in kapi-works.json.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Blocks](https://docs.kapiworks.com/build/reference/blocks) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# alt_missing

This picture needs alt text, or mark it decorative.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Blocks](https://docs.kapiworks.com/build/reference/blocks) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# captions_missing

Sound or video with speech needs captions.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Blocks](https://docs.kapiworks.com/build/reference/blocks) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# media_too_large

This file is over 25 MB, the most a page can carry. Make it smaller.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a file to add, replace or remove.

## How to fix it

Add, replace or remove the file the finding names.

[Limits](https://docs.kapiworks.com/build/reference/limits) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# context_not_allowed

… can't be required for customers. Kapi never gives it in a customer door.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Placeholders](https://docs.kapiworks.com/build/reference/placeholders) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# starter_words_left

The starter's sample words are still here (…). Replace them with your own.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# starter_media_left

This is still the starter's sample file. Replace it with your own.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a file to add, replace or remove.

## How to fix it

Add, replace or remove the file the finding names.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# support_missing

This answer key has no quote from a source in support.json.

- Severity: **Warning**. It doesn't block approval. The approver sees it.
- In a course Kapi makes from your documents: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# support_target_unknown

support.json names …, which is neither a question nor a text in the package.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# source_not_linked

Kapi can't check this quote until its source is linked to the draft.

- Severity: **Warning**. It doesn't block approval. The approver sees it.
- Course types: every type.
- Who fixes it: you, with a choice that is yours to make.

## How to fix it

Decide, then change the course to match. The finding's `fixes` says what to decide and holds the change that follows.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# quote_not_found

This quote isn't in its source, word for word.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# fact_not_in_source

… isn't in any source this cites. Check it against the source.

- Severity: **Warning**. It doesn't block approval. The approver sees it.
- In a course Kapi makes from your documents: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# lesson_long

This lesson runs about … minutes. People keep more from lessons of 4 to 7.

- Severity: **Tip**. Advice. It doesn't block approval.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# sentence_long

… Shorter sentences are easier to read, especially in a second language.

- Severity: **Tip**. Advice. It doesn't block approval.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# few_situations

… Questions set in a situation check that people can use what they learned.

- Severity: **Tip**. Advice. It doesn't block approval.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Questions](https://docs.kapiworks.com/build/reference/questions) explains this part of the format.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# film_sdk

This package has a film, so kapi-works.json needs "sdk": "2.1".

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# narration_placeholder

Narration can't hold a placeholder. Kapi records it once for every company, so say "your company" or "your IT team" instead.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# pause_question_kind

A film can stop only for a choice or multi question.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# pause_question_elsewhere

This question also …. A question a film stops for belongs to that film only.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# drawing_target_unknown

This drawing's target … names no choice of the question the scene stops for.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# drawing_target_missing

The choice … of the question this scene stops for has no target in the drawing, so nobody could tap it.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: every type.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# lesson_without_question

… has no practice question. A question in each lesson helps people keep what they read.

- Severity: **Warning**. It doesn't block approval. The approver sees it.
- Course types: [Training course](https://docs.kapiworks.com/build/course-types/training-course) only.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Training course](https://docs.kapiworks.com/build/course-types/training-course) gives the shape this type needs.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# scenario_opening_missing

… doesn't open with a situation to choose from. In scenario practice, each lesson starts with a situation and a choice.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: [Scenario practice](https://docs.kapiworks.com/build/course-types/scenario-course) only.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Scenario practice](https://docs.kapiworks.com/build/course-types/scenario-course) gives the shape this type needs.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# refresher_question_first

This page doesn't start with its question. In a quick refresher, every page asks first and the feedback teaches.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: [Quick refresher](https://docs.kapiworks.com/build/course-types/quick-refresher) only.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Quick refresher](https://docs.kapiworks.com/build/course-types/quick-refresher) gives the shape this type needs.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# refresher_too_long

This refresher takes about … minutes. A quick refresher takes 8 to 12.

- Severity: **Warning**. It doesn't block approval. The approver sees it.
- Course types: [Quick refresher](https://docs.kapiworks.com/build/course-types/quick-refresher) only.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Quick refresher](https://docs.kapiworks.com/build/course-types/quick-refresher) gives the shape this type needs.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# certificate_pool_small

A certificate test needs a pool at least twice the size of its draw (…), so each retake asks different questions.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: [Certificate course](https://docs.kapiworks.com/build/course-types/certificate-course) only.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Certificate course](https://docs.kapiworks.com/build/course-types/certificate-course) gives the shape this type needs.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# certificate_pass_mark_missing

The test suggests no pass mark. The company can change it, but a certificate course should suggest one.

- Severity: **Warning**. It doesn't block approval. The approver sees it.
- Course types: [Certificate course](https://docs.kapiworks.com/build/course-types/certificate-course) only.
- Who fixes it: you or your AI, with a change to one value.

## How to fix it

Change the value the finding points to. Its `where` names the file and gives a JSON Pointer to the place. When Kapi knows the exact change, the finding's `fixes` holds it as JSON Patch operations.

[Certificate course](https://docs.kapiworks.com/build/course-types/certificate-course) gives the shape this type needs.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# walkthrough_steps_missing

… has no numbered steps. A walkthrough shows each step in order.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: [Step-by-step walkthrough](https://docs.kapiworks.com/build/course-types/walkthrough) only.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Step-by-step walkthrough](https://docs.kapiworks.com/build/course-types/walkthrough) gives the shape this type needs.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# walkthrough_picture_missing

These steps have no picture. A screenshot of each step helps people follow along.

- Severity: **Tip**. Advice. It doesn't block approval.
- Course types: [Step-by-step walkthrough](https://docs.kapiworks.com/build/course-types/walkthrough) only.
- Who fixes it: you or your AI, with a file to add, replace or remove.

## How to fix it

Add, replace or remove the file the finding names.

[Step-by-step walkthrough](https://docs.kapiworks.com/build/course-types/walkthrough) gives the shape this type needs.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# change_before_missing

… doesn't show the old rule. Show it once, starting "Before" and the date it changed.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: [What changed](https://docs.kapiworks.com/build/course-types/what-changed) only.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[What changed](https://docs.kapiworks.com/build/course-types/what-changed) gives the shape this type needs.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# change_question_missing

… has no situation question about the change.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: [What changed](https://docs.kapiworks.com/build/course-types/what-changed) only.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[What changed](https://docs.kapiworks.com/build/course-types/what-changed) gives the shape this type needs.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# video_opening_missing

… doesn't open with a film. In a video, each lesson starts with its film.

- Severity: **Error**. It blocks approval until it is fixed.
- Course types: [Video](https://docs.kapiworks.com/build/course-types/video) only.
- Who fixes it: you or your AI, with words to write.

## How to fix it

Write what the finding asks for: words in the words file, or the blocks and questions they belong to. When Kapi knows which text it needs, the finding's `fixes` names the text ID and what it should say.

[Video](https://docs.kapiworks.com/build/course-types/video) gives the shape this type needs.

[Every check](https://docs.kapiworks.com/build/reference/checks), with what each one says.


# Policies

Make Kapi Works policies that people acknowledge or sign. Write one with Kapi or with your own AI, start from an example, or upload HTML, Word or PDF.

A Kapi Works policy is one HTML file in Kapi's [policy format](https://docs.kapiworks.com/build/policies/format): headings, paragraphs, lists, tables and links, with a place to sign. Employees acknowledge a policy with one tick and one button. Partners and customers acknowledge it the same way, or sign it with their signature. Everyone gets a signed copy as a PDF.

Policies are not training. They stay out of courses lists, results, certificates and the training register.

## Make a policy

In Works Studio, press **Create**, then **Policy**. **New policy** opens with three ways in:

* **Write it with Kapi.** Describe the policy, or add your documents, and Kapi writes it in the policy format.
* **Copy prompt for your AI.** Copies [the prompt](#the-prompt) with Kapi's example code of conduct below it, for ChatGPT, Claude, Gemini or any AI. Paste it into your AI, answer its questions, then upload what it makes.
* **Upload your policy.** Paste HTML, or choose an HTML, Word or PDF file. Your browser turns a Word or PDF file into the policy format with code, not AI.

Below them are Kapi's six [example policies](#examples). **Have a look** shows one as people will see it, **Use this** starts a draft from it, and **Copy prompt** copies a prompt for a policy like it.

Every way in opens the editor. It shows the policy as people will see it, place to sign included, at desktop or phone width. **HTML** opens the file beside it to edit, and clicking a part of the policy selects its HTML. Ask Kapi for bigger changes in words, such as "add a section on gifts". Kapi's checks list what Kapi changed in the file and anything that stops publishing. A policy Kapi wrote, or one started from an example, shows "Written by Kapi. Check it with your adviser before you publish." in the editor only. **Continue** opens the policy's page.

## Publish and share

The policy's page has three tabs: **Document**, **People** and **Settings**. On **Settings**, choose:

* what people do: **Acknowledge**, or **Sign**;
* the statement they agree to;
* who may receive it: employees, partners or customers;
* whether to ask again every year, every 2 years or every 3 years;
* when it takes effect.

The [two tags](https://docs.kapiworks.com/build/policies/format#who-receives-it-and-what-they-do) in a file suggest what people do and who receives it. You decide before you publish.

**Publish** makes the policy live. When you publish a later version, choose whether everyone signs again or it is a small fix that nobody signs again. Then share it from the **People** tab with people or groups. Each audience has a group called **Everyone**, which new starters join as they arrive. A policy is always required. Its deadline is a number of days after it reaches each person, 14 unless you change it, or a date you choose.

## Acknowledging and signing

People find the policy in Works Learn, on Home and in My learning. They read it, then act where the policy puts its place to sign.

* **Acknowledge.** They tick the statement, then press **Acknowledge**.
* **Sign.** **Sign here** opens **Your signature**. They draw it with a mouse, finger or pen, or type their name, and can save it for next time. Their name, their company and today's date fill in, and **Sign** completes it.

Each person acknowledges or signs for themselves. Kapi records no reading time and sets no timers.

## The signed copy

Each act gives a signed copy as a PDF: the policy as the person read it, with their tick or signature where the policy puts its place to sign, then a **Signing record** page. The record lists the policy, the company, the version, the person and their email, their company, what they did, when it happened in their time zone and in UTC, how they signed in, the statement, the [document fingerprint](https://docs.kapiworks.com/build/policies/format#the-canonical-file) and the receipt. The same receipt always gives the same PDF.

People download their copy when they finish, and find it later in **Your records**. The company sees who has acknowledged or signed, downloads each signed copy and reminds the rest. Auditors read the same records in their portal, and your own systems read them through the Works API with the `acknowledgements:read` scope, starting with [`GET /v1/acknowledgements`](https://docs.kapiworks.com/reference/list-acknowledgements).

## Examples

Each example is written for a UK company of 50 to 250 people, in plain words, with its sources. Each file is the canonical file, exactly as Kapi stores it.

| Example | Who and what | File |
| --- | --- | --- |
| Code of conduct | Employees · Acknowledge · About 5 minutes | [`code-of-conduct.html`](https://docs.kapiworks.com/build/examples/policies/code-of-conduct.html) |
| Preventing sexual harassment policy | Employees · Acknowledge · About 5 minutes | [`preventing-sexual-harassment.html`](https://docs.kapiworks.com/build/examples/policies/preventing-sexual-harassment.html) |
| Using AI at work policy | Employees · Acknowledge · About 4 minutes | [`using-ai-at-work.html`](https://docs.kapiworks.com/build/examples/policies/using-ai-at-work.html) |
| Data protection at work policy | Employees · Acknowledge · About 5 minutes | [`data-protection-at-work.html`](https://docs.kapiworks.com/build/examples/policies/data-protection-at-work.html) |
| Partner code of conduct | Partners · Sign · About 4 minutes | [`partner-code-of-conduct.html`](https://docs.kapiworks.com/build/examples/policies/partner-code-of-conduct.html) |
| Customer terms of use | Customers · Acknowledge · About 4 minutes | [`customer-terms-of-use.html`](https://docs.kapiworks.com/build/examples/policies/customer-terms-of-use.html) |

## The prompt

**Copy prompt for your AI** copies this prompt, with Kapi's example code of conduct below it, shortened to fit. An example's **Copy prompt** copies the same prompt for a policy like that example. Your AI asks you up to five questions, then writes one HTML file.

```text
Kapi Works policy prompt · any policy · format 2

Write a policy for Kapi Works, my company's learning platform, where people acknowledge or sign it. Answer with one complete HTML file in one code block, in Kapi's policy format. Kapi reads it, shows it as people will see it, and I check it before I publish.

THE FORMAT
- One HTML file: <!doctype html>, <html lang="en-GB">, then a head with <meta charset="utf-8">, the two tags below and a <title>.
- <meta name="kapi:act" content="acknowledge"> when people tick to confirm they have read it, or content="sign" when they sign it with their signature. <meta name="kapi:signers" content="employees"> says who receives it: any of employees, partners and customers.
- The body uses only h1 to h4, p, ul, ol, li, blockquote, table with caption, tr, th and td, hr, strong, em, a href and br. Kapi leaves out styles, classes, scripts, pictures, forms and frames.
- One h1, the title. Then short sections, each under an h2.
- <kapi-sign></kapi-sign> once, where people acknowledge or sign: usually at the end, after a sentence that says what they confirm. Kapi draws a tick box there, or a signature box with the person's name and the date.
- Links start with https:// or mailto:.

RULES
1. Plain UK English: short sentences, "you" for the reader and "we" for my company.
2. Take rules, numbers and contacts only from my documents and my answers. If they don't say, ask me.
3. Link official sources over https, such as gov.uk, acas.org.uk, ico.org.uk and legislation.gov.uk. Never invent a law, a date, a case or a source.
4. Never say the policy or the company is compliant, certified or legally binding, or that signing proves anything. Say what people do.
5. Name roles and team contacts, such as "your manager" or a team's email address, not individual people.
6. Give the whole file. Never shorten it or write "…".

If you can open web pages, read https://docs.kapiworks.com/build/policies/llms.txt first.
Ask me up to five questions first, such as what the policy covers, who receives it, whether they acknowledge or sign it, and who they contact with questions. Then write the file.
```

For your AI, the whole policy format is one plain text file at `https://docs.kapiworks.com/build/policies/llms.txt`. [For AI agents](https://docs.kapiworks.com/build/ai) lists everything else.

## Find your way

- [Policy format](https://docs.kapiworks.com/build/policies/format): Every element Kapi keeps, the place to sign, the two tags and the canonical file.
- [For AI agents](https://docs.kapiworks.com/build/ai): Prompts, examples and plain text files for your AI.


# Policy format

What Kapi reads in a policy file. The elements it keeps, the place to sign, the two tags, what it leaves out, the limits and the canonical file.

A policy is one HTML file. Kapi reads any HTML into its policy format, `kapi.works.policy/2`, says in plain words what it changed, and stores the result as one canonical file. People read that file, sign it and get it back as a PDF, so what someone signs is exactly what they saw.

## A whole policy

A short policy, as your AI writes it:

```html
<!doctype html>
<html lang="en-GB">
<head>
<meta charset="utf-8">
<meta name="kapi:act" content="acknowledge">
<meta name="kapi:signers" content="employees">
<title>Gifts and hospitality policy</title>
</head>
<body>
<h1>Gifts and hospitality policy</h1>
<p>Gifts and hospitality must not influence a decision, or look as though they could.</p>
<h2>What to do</h2>
<table>
  <caption>Gifts and hospitality, given or received</caption>
  <tr><th>What</th><th>What to do</th></tr>
  <tr><td>Worth up to £50</td><td>You may give or accept it.</td></tr>
  <tr><td>Worth more than £50</td><td>Ask your manager first, and record it in the gifts register.</td></tr>
</table>
<h2>Find out more</h2>
<ul>
  <li><a href="https://www.gov.uk/government/publications/bribery-act-2010-guidance">GOV.UK: Bribery Act 2010 guidance</a></li>
  <li>Questions: <a href="mailto:hr@example.com">hr@example.com</a></li>
</ul>
<h2>Confirming you have read this policy</h2>
<p>Confirm below that you have read this policy.</p>
<kapi-sign></kapi-sign>
</body>
</html>
```

## What Kapi keeps

| Element                              | For                                                                                                 |
| ------------------------------------ | --------------------------------------------------------------------------------------------------- |
| `h1`                                 | The title. The first `h1` is the policy's title.                                                    |
| `h2`, `h3`, `h4`                     | Section headings. Kapi reads `h5` and `h6` as `h4`.                                                 |
| `p`                                  | Paragraphs.                                                                                         |
| `ul`, `ol`, `li`                     | Lists, up to four levels deep. An `ol` keeps its `start` and its `type`: `1`, `a`, `A`, `i` or `I`. |
| `blockquote`                         | Quoted words.                                                                                       |
| `table`, `caption`, `tr`, `th`, `td` | Tables. Header cells are `th`.                                                                      |
| `hr`                                 | A line between parts.                                                                               |
| `strong` or `b`, `em` or `i`         | Bold and italic words.                                                                              |
| `a href`                             | Links to `https://` pages and `mailto:` addresses.                                                  |
| `br`                                 | A line break.                                                                                       |
| `kapi-sign`                          | The place to sign.                                                                                  |

Containers such as `div`, `section`, `article`, `header` and `footer` keep what they hold. Every other element keeps its words.

## The place to sign

`<kapi-sign></kapi-sign>` marks where people acknowledge or sign. Kapi draws the place to sign there: the statement, then a tick and **Acknowledge**, or a signature, name, company and date and **Sign**. Put it after a sentence that says what people confirm, usually at the end.

A file without one gets one at the end. With more than one, Kapi keeps the first. One inside a sentence, a list or a table moves to just after it.

## Who receives it and what they do

Two optional tags in the head suggest how the policy starts:

```html
<meta name="kapi:act" content="acknowledge">
<meta name="kapi:signers" content="employees, partners, customers">
```

* `kapi:act` is `acknowledge`, for a tick and **Acknowledge**, or `sign`, for a signature.
* `kapi:signers` names any of `employees`, `partners` and `customers`.

Kapi starts the policy's settings from them, and you decide before you publish. The tags stay out of the canonical file.

## Title and language

The title is the first `h1`, else the file's `title`, else the file's name. The language is the `lang` of `html`, else `en-GB`.

## What Kapi leaves out

Kapi leaves out scripts, styles and classes, pictures and media, frames, form fields, and link targets that do not start with `https://` or `mailto:`. It keeps the words people should read, and shows hidden words. Kapi's checks list each change in these words:

| In the file | What Kapi says |
| --- | --- |
| Scripts | Kapi left out a script. Policies don't run code. |
| Styles, stylesheets and classes | Kapi left out the file's styling. Policies use Kapi's reading style, with text size and Listen. |
| Pictures, video, sound and embedded frames | Kapi left out a picture or embedded item. Policies hold words only. |
| Form fields and buttons | Kapi left out a form field. People sign in Kapi's own place to sign. |
| Links that do not start with https:// or mailto: | Kapi kept the words of a link that didn't start with https:// or mailto:, without the link. |
| Hidden words | Some words were hidden in the file. Kapi shows them, so people see everything they sign. |
| Merged table cells | Kapi split merged table cells, so each cell holds its own words. |
| Lists more than four levels deep | Kapi kept lists 4 levels deep and joined deeper levels to the level above. |
| A second place to sign | Kapi kept the first place to sign and left out the other one. |
| A title but no main heading | Kapi added the title as the main heading at the top. |
| No place to sign | Kapi added the place to sign at the end. |

These stop publishing until they are fixed:

| In the file | What Kapi says |
| --- | --- |
| No words | The policy has no words yet. |
| No main heading and no title | Add a title: a main heading at the top of the policy. |
| A main heading over 300 characters | Shorten the main heading to 300 characters or fewer. |
| More than 250,000 characters of words | This policy is too long. A policy holds at most 250,000 characters of words. |
| More than 2,000,000 characters of HTML | This file is too large for a policy. A policy holds at most 2 MB of HTML. |
| A file that is not a web page, such as a Word file renamed .html | Kapi couldn't read this as a web page. Save it as HTML, or upload it as Word or PDF. |

## Limits

| Limit | Value |
| --- | --- |
| HTML Kapi reads | 2,000,000 characters, about 2 MB |
| Words in a policy | 250,000 characters |
| Main heading | 300 characters |
| Levels in a list | 4 |

## The canonical file

Kapi stores only canonical files: `<!doctype html>`, `<html lang>`, a head with the charset and the title, then one block per line, with nested list items indented by two spaces. The same document always gives the same bytes. The policy above, as Kapi stores it:

```html
<!doctype html>
<html lang="en-GB">
<head>
<meta charset="utf-8">
<title>Gifts and hospitality policy</title>
</head>
<body>
<h1>Gifts and hospitality policy</h1>
<p>Gifts and hospitality must not influence a decision, or look as though they could.</p>
<h2>What to do</h2>
<table>
  <caption>Gifts and hospitality, given or received</caption>
  <tr><th>What</th><th>What to do</th></tr>
  <tr><td>Worth up to £50</td><td>You may give or accept it.</td></tr>
  <tr><td>Worth more than £50</td><td>Ask your manager first, and record it in the gifts register.</td></tr>
</table>
<h2>Find out more</h2>
<ul>
  <li><a href="https://www.gov.uk/government/publications/bribery-act-2010-guidance">GOV.UK: Bribery Act 2010 guidance</a></li>
  <li>Questions: <a href="mailto:hr@example.com">hr@example.com</a></li>
</ul>
<h2>Confirming you have read this policy</h2>
<p>Confirm below that you have read this policy.</p>
<kapi-sign></kapi-sign>
</body>
</html>
```

The document fingerprint is the lower-case hex SHA-256 of the canonical file's UTF-8 bytes. Each receipt and each signed copy records it, so a copy can be matched to the version it was signed against. Kapi's [example code of conduct](https://docs.kapiworks.com/build/examples/policies/code-of-conduct.html) has the fingerprint `710e4f0ccc6f0e414a3b6f51a35dc1ee93f9fb9afbd121933f3f1d6270c842bd`. To check it yourself:

```sh
curl -s https://docs.kapiworks.com/build/examples/policies/code-of-conduct.html | shasum -a 256
```


# For AI agents

The prompt and example course for each type, the policy prompt and example policies, the Build section as plain text, the JSON Schemas and the docs MCP server.

Everything here is public and needs no key. An AI that writes a course or a policy reads the same rules and checks as Works Studio.

## Prompts and example courses

Each course type has a prompt for your own AI and an example course: a whole course of that type for a made-up company, as one `kapi.works.bundle/1` bundle. Give your AI both. It copies the example's layout, not its words.

| Course type | Prompt | Example course |
| --- | --- | --- |
| Training course | [The prompt](https://docs.kapiworks.com/build/course-types/training-course#the-prompt) | [`https://docs.kapiworks.com/build/examples/training-course.json`](https://docs.kapiworks.com/build/examples/training-course.json) |
| Scenario practice | [The prompt](https://docs.kapiworks.com/build/course-types/scenario-course#the-prompt) | [`https://docs.kapiworks.com/build/examples/scenario-course.json`](https://docs.kapiworks.com/build/examples/scenario-course.json) |
| Quick refresher | [The prompt](https://docs.kapiworks.com/build/course-types/quick-refresher#the-prompt) | [`https://docs.kapiworks.com/build/examples/quick-refresher.json`](https://docs.kapiworks.com/build/examples/quick-refresher.json) |
| Certificate course | [The prompt](https://docs.kapiworks.com/build/course-types/certificate-course#the-prompt) | [`https://docs.kapiworks.com/build/examples/certificate-course.json`](https://docs.kapiworks.com/build/examples/certificate-course.json) |
| Step-by-step walkthrough | [The prompt](https://docs.kapiworks.com/build/course-types/walkthrough#the-prompt) | [`https://docs.kapiworks.com/build/examples/walkthrough.json`](https://docs.kapiworks.com/build/examples/walkthrough.json) |
| What changed | [The prompt](https://docs.kapiworks.com/build/course-types/what-changed#the-prompt) | [`https://docs.kapiworks.com/build/examples/what-changed.json`](https://docs.kapiworks.com/build/examples/what-changed.json) |
| Video | [The prompt](https://docs.kapiworks.com/build/course-types/video#the-prompt) | [`https://docs.kapiworks.com/build/examples/video.json`](https://docs.kapiworks.com/build/examples/video.json) |

## Plain text

* [/build/llms.txt](https://docs.kapiworks.com/build/llms.txt) lists every page of this section with a one-line description, following [llmstxt.org](https://llmstxt.org/).
* [/build/llms-full.txt](https://docs.kapiworks.com/build/llms-full.txt) holds the whole section in one file: the course types and their prompts, the format reference, every check and the addresses of the example courses. Each prompt asks the AI to read it when it can open web pages.
* Add `.md` to any page's address for its Markdown, such as [/build/quickstart.md](https://docs.kapiworks.com/build/quickstart.md), or send `Accept: text/markdown`. **Copy page** copies it.

## Policies

[Policies](https://docs.kapiworks.com/build/policies#the-prompt) have one prompt for any policy, and Kapi's six [example policies](https://docs.kapiworks.com/build/policies#examples), each the canonical file exactly as Kapi stores it. [/build/policies/llms.txt](https://docs.kapiworks.com/build/policies/llms.txt) holds the whole policy format in one file: the elements Kapi keeps, the place to sign, the two tags, what Kapi leaves out, the prompt, the examples' addresses and Kapi's example code of conduct in full. The prompt asks the AI to read it when it can open web pages.

## JSON Schemas

Each data file can name its schema in `"$schema"`, so editors and tools check it as you type. Any site may fetch them.

| Schema | For |
| --- | --- |
| [`https://docs.kapiworks.com/schemas/package-2.json`](https://docs.kapiworks.com/schemas/package-2.json) | Kapi Works package (kapi-works.json) |
| [`https://docs.kapiworks.com/schemas/content-2.json`](https://docs.kapiworks.com/schemas/content-2.json) | Kapi Works content (content.json) |
| [`https://docs.kapiworks.com/schemas/questions-2.json`](https://docs.kapiworks.com/schemas/questions-2.json) | Kapi Works questions (questions.json) |
| [`https://docs.kapiworks.com/schemas/words-1.json`](https://docs.kapiworks.com/schemas/words-1.json) | Kapi Works words (words/<language>.json) |
| [`https://docs.kapiworks.com/schemas/support-1.json`](https://docs.kapiworks.com/schemas/support-1.json) | Kapi Works support (support.json) |
| [`https://docs.kapiworks.com/schemas/theme-1.json`](https://docs.kapiworks.com/schemas/theme-1.json) | Kapi Works theme (look/theme.json) |
| [`https://docs.kapiworks.com/schemas/bundle-1.json`](https://docs.kapiworks.com/schemas/bundle-1.json) | Kapi Works bundle |

For code, [`kapi-works-package.d.ts`](https://docs.kapiworks.com/schemas/kapi-works-package.d.ts) holds the types of the data files.

## Docs MCP server

The [docs MCP server](https://docs.kapiworks.com/ai-tools) at `https://docs.kapiworks.com/api/mcp` has three tools for courses and one for policies:

| Tool                | What it does                                                                    |
| ------------------- | ------------------------------------------------------------------------------- |
| `get_course_type`   | Returns a course type's page, with its prompt, and its example course.          |
| `get_schema`        | Returns the JSON Schema of one data file, or of a bundle.                       |
| `get_check`         | Returns a check's page: what its finding means and how to fix it.               |
| `get_policy_format` | Returns the whole policy format, the prompt and Kapi's example code of conduct. |
