kapi WorksDocs
Format reference

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.

FileHoldsSchema
kapi-works.jsonWhat the package is, its language, how it plays, and the roles, tests, context, links, media and sources it declarespackage-2.json
content.jsonA course's lessons, pages and blocks, in reading ordercontent-2.json
words/<language>.jsonEvery text in the package, by text ID, up to 1 MiBwords-1.json
questions.jsonEvery question, with its answer, feedback and explanationquestions-2.json
support.jsonWhere each answer key and fact comes from, quoted word for word from its sourcesupport-1.json
look/theme.jsonThe package's look, which starts from the company's brandtheme-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.

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.

  • 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.
  • 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.

  • 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.

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.

  • <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.

  • 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.

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.

  • 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.

  • 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.

  • 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

CheckSeverityWhat Kapi says
file_not_allowedErrorThis file isn't a file a package holds. Remove it, or move it where the docs say it goes.
unsafe_pathErrorThis path isn't safe. Use lower-case relative paths with no "..", backslashes or hidden parts.
file_typeErrorThis file isn't the kind of file its place says. Kapi reads a file's first bytes, not its name.
not_utf8ErrorThis file isn't saved as UTF-8 text. Save it again as UTF-8.
json_invalidErrorThis file isn't valid JSON.
schema_invalidErrorThis value should be as the format says.
unknown_keyError"…" isn't part of the format. Remove it, or check its spelling.
file_missingErrorThe package needs this file.
id_duplicateErrorThe … ID is used twice. Every ID must be unique.
family_not_availableErrorKapi doesn't have a … player yet. Courses play today.
sdk_too_newErrorThe package needs a newer SDK than Kapi serves. Kapi serves SDK ….
player_line_unknownErrorThere's no such player line. Use ….

On this page