Skip to content

ulams topics

Generated from front/cli (ulams schema)

Clone topic.

Kind: write. Stability: stable. MCP tool: topics_clone. Scopes: courses:write.

Endpoints: POST /api/admin/topics/{id}/clone.

Flag Type Required Description
--id (positional) integer yes id of Topic
--body unknown Request body (JSON)
Terminal window
# Clone topic
ulams topics clone 1 --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "id of Topic"
},
"body": {
"description": "Request body (JSON)"
}
},
"required": [
"id"
],
"additionalProperties": {}
}

Create a topic of any registered type from raw fields (project, LTI, custom types).

Escape hatch for types without a dedicated command: pass topicable (the class name from ulams topics types), value and any extra fields in –input.

Kind: write. Stability: stable. MCP tool: topics_create. Scopes: courses:write.

Endpoints: POST /api/admin/topics.

Flag Type Required Description
--lesson integer yes Lesson id (from ulams lessons list --course-id <id>).
--title string yes Topic title.
--order integer Position in the lesson; default: after the last topic.
--summary string Short summary.
--preview boolean Visible without access to the course.
--active boolean Visible to learners (default true).
--can-skip boolean Learners may skip the topic.
--duration string Estimated duration, e.g. ‘10 min’.
--topicable string yes Topic content class, e.g. Ulams\TopicTypeProject\Models\Project.
--value unknown
Terminal window
# A project topic
ulams topics create --lesson 12 --title Capstone --topicable 'Ulams\TopicTypeProject\Models\Project' --value 'Build X' --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"lesson": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lesson id (from `ulams lessons list --course-id <id>`)."
},
"title": {
"type": "string",
"description": "Topic title."
},
"order": {
"description": "Position in the lesson; default: after the last topic.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"summary": {
"description": "Short summary.",
"type": "string"
},
"preview": {
"description": "Visible without access to the course.",
"type": "boolean"
},
"active": {
"description": "Visible to learners (default true).",
"type": "boolean"
},
"canSkip": {
"description": "Learners may skip the topic.",
"type": "boolean"
},
"duration": {
"description": "Estimated duration, e.g. '10 min'.",
"type": "string"
},
"topicable": {
"type": "string",
"description": "Topic content class, e.g. Ulams\\TopicTypeProject\\Models\\Project."
},
"value": {}
},
"required": [
"lesson",
"title",
"topicable"
],
"additionalProperties": {}
}

Create a cmi5 topic from a package .zip.

Uploads the cmi5 package and creates a topic for its assignable unit (the only one, or –au).

Kind: write. Stability: stable. MCP tool: topics_create_cmi5. Scopes: courses:write.

Endpoints: POST /api/admin/cmi5, POST /api/admin/topics.

Flag Type Required Description
--lesson integer yes Lesson id (from ulams lessons list --course-id <id>).
--title string yes Topic title.
--order integer Position in the lesson; default: after the last topic.
--summary string Short summary.
--preview boolean Visible without access to the course.
--active boolean Visible to learners (default true).
--can-skip boolean Learners may skip the topic.
--duration string Estimated duration, e.g. ‘10 min’.
--package string yes Local cmi5 .zip.
--au integer Assignable unit id when there are several.
Terminal window
# A cmi5 package
ulams topics create-cmi5 --lesson 12 --title Module --package ./au.zip --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"lesson": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lesson id (from `ulams lessons list --course-id <id>`)."
},
"title": {
"type": "string",
"description": "Topic title."
},
"order": {
"description": "Position in the lesson; default: after the last topic.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"summary": {
"description": "Short summary.",
"type": "string"
},
"preview": {
"description": "Visible without access to the course.",
"type": "boolean"
},
"active": {
"description": "Visible to learners (default true).",
"type": "boolean"
},
"canSkip": {
"description": "Learners may skip the topic.",
"type": "boolean"
},
"duration": {
"description": "Estimated duration, e.g. '10 min'.",
"type": "string"
},
"package": {
"type": "string",
"description": "Local cmi5 .zip."
},
"au": {
"description": "Assignable unit id when there are several.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"lesson",
"title",
"package"
]
}

Create a PDF, image or audio topic from a local file.

The topic type follows the extension: .pdf, .png .jpg .jpeg .gif .webp .svg, .mp3 .ogg.

Kind: write. Stability: stable. MCP tool: topics_create_file. Scopes: courses:write.

Endpoints: POST /api/admin/topics.

Flag Type Required Description
--lesson integer yes Lesson id (from ulams lessons list --course-id <id>).
--title string yes Topic title.
--order integer Position in the lesson; default: after the last topic.
--summary string Short summary.
--preview boolean Visible without access to the course.
--active boolean Visible to learners (default true).
--can-skip boolean Learners may skip the topic.
--duration string Estimated duration, e.g. ‘10 min’.
--file string yes Local file.
Terminal window
# A PDF topic
ulams topics create-file --lesson 12 --title Handout --file ./handout.pdf --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"lesson": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lesson id (from `ulams lessons list --course-id <id>`)."
},
"title": {
"type": "string",
"description": "Topic title."
},
"order": {
"description": "Position in the lesson; default: after the last topic.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"summary": {
"description": "Short summary.",
"type": "string"
},
"preview": {
"description": "Visible without access to the course.",
"type": "boolean"
},
"active": {
"description": "Visible to learners (default true).",
"type": "boolean"
},
"canSkip": {
"description": "Learners may skip the topic.",
"type": "boolean"
},
"duration": {
"description": "Estimated duration, e.g. '10 min'.",
"type": "string"
},
"file": {
"type": "string",
"description": "Local file."
}
},
"required": [
"lesson",
"title",
"file"
]
}

Create an H5P topic from a .h5p package.

Uploads the package to the H5P service (POST /h5p/contents/upload, field h5p_file) and creates a topic for the new content.

Kind: write. Stability: stable. MCP tool: topics_create_h5p. Scopes: courses:write.

Endpoints: POST /api/admin/topics.

Flag Type Required Description
--lesson integer yes Lesson id (from ulams lessons list --course-id <id>).
--title string yes Topic title.
--order integer Position in the lesson; default: after the last topic.
--summary string Short summary.
--preview boolean Visible without access to the course.
--active boolean Visible to learners (default true).
--can-skip boolean Learners may skip the topic.
--duration string Estimated duration, e.g. ‘10 min’.
--package string yes Local .h5p file.
Terminal window
# An H5P activity
ulams topics create-h5p --lesson 12 --title Quiz --package ./quiz.h5p --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"lesson": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lesson id (from `ulams lessons list --course-id <id>`)."
},
"title": {
"type": "string",
"description": "Topic title."
},
"order": {
"description": "Position in the lesson; default: after the last topic.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"summary": {
"description": "Short summary.",
"type": "string"
},
"preview": {
"description": "Visible without access to the course.",
"type": "boolean"
},
"active": {
"description": "Visible to learners (default true).",
"type": "boolean"
},
"canSkip": {
"description": "Learners may skip the topic.",
"type": "boolean"
},
"duration": {
"description": "Estimated duration, e.g. '10 min'.",
"type": "string"
},
"package": {
"type": "string",
"description": "Local .h5p file."
}
},
"required": [
"lesson",
"title",
"package"
]
}

Create an Interactive topic from a package .zip (or an uploaded package).

An Interactive topic plays an uploaded web app (3D scene, map, simulation) in a sandbox, inline or as the background of the page. Pass –file to upload a package (a .zip with ulams-interactive.json) or –package to use an uploaded one. The topic pins the package’s current version unless –version is given; –follow-latest plays every new upload instead. –start-step and –end-step choose the steps (ids from the manifest); the topic completes by –completion (default on_range_end). A manifest that lists network origins needs –accept-network.

Kind: write. Stability: stable. MCP tool: topics_create_interactive. Scopes: courses:write.

Endpoints: POST /api/admin/interactive, POST /api/admin/topics.

Flag Type Required Description
--lesson integer yes Lesson id (from ulams lessons list --course-id <id>).
--title string yes Topic title.
--order integer Position in the lesson; default: after the last topic.
--summary string Short summary.
--preview boolean Visible without access to the course.
--active boolean Visible to learners (default true).
--can-skip boolean Learners may skip the topic.
--duration string Estimated duration, e.g. ‘10 min’.
--file string Local .zip of a new package.
--package integer Id of an uploaded package (from ulams interactive list).
--version integer Pin this version of the package (default: the current one).
--follow-latest boolean Play the package’s current version instead of pinning one.
--start-step string First step id of the range.
--end-step string Last step id of the range.
--completion string When the topic completes.
--pass-score integer Pass percentage for –completion on_score.
--display string Inline in the lesson, or the background of the page.
--height integer Frame height in px (inline).
--text string Lesson text in Markdown, or @path.
--accept-network boolean Accept the network origins the manifest lists.
Terminal window
# A step of a 3D scene as the page background
ulams topics create-interactive --lesson 12 --title "Too slow" --file gravity.zip --start-step too-slow --end-step too-slow --display background --json
# Another topic on an uploaded package
ulams topics create-interactive --lesson 12 --title "Too fast" --package 3 --start-step too-fast --end-step too-fast --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"lesson": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lesson id (from `ulams lessons list --course-id <id>`)."
},
"title": {
"type": "string",
"description": "Topic title."
},
"order": {
"description": "Position in the lesson; default: after the last topic.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"summary": {
"description": "Short summary.",
"type": "string"
},
"preview": {
"description": "Visible without access to the course.",
"type": "boolean"
},
"active": {
"description": "Visible to learners (default true).",
"type": "boolean"
},
"canSkip": {
"description": "Learners may skip the topic.",
"type": "boolean"
},
"duration": {
"description": "Estimated duration, e.g. '10 min'.",
"type": "string"
},
"file": {
"description": "Local .zip of a new package.",
"type": "string"
},
"package": {
"description": "Id of an uploaded package (from `ulams interactive list`).",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"version": {
"description": "Pin this version of the package (default: the current one).",
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991
},
"followLatest": {
"description": "Play the package's current version instead of pinning one.",
"type": "boolean"
},
"startStep": {
"description": "First step id of the range.",
"type": "string"
},
"endStep": {
"description": "Last step id of the range.",
"type": "string"
},
"completion": {
"default": "on_range_end",
"description": "When the topic completes.",
"type": "string",
"enum": [
"on_open",
"on_range_end",
"on_complete",
"on_score"
]
},
"passScore": {
"description": "Pass percentage for --completion on_score.",
"type": "integer",
"minimum": 0,
"maximum": 100
},
"display": {
"default": "inline",
"description": "Inline in the lesson, or the background of the page.",
"type": "string",
"enum": [
"inline",
"background"
]
},
"height": {
"description": "Frame height in px (inline).",
"type": "integer",
"minimum": 240,
"maximum": 2000
},
"text": {
"fileInput": true,
"description": "Lesson text in Markdown, or @path.",
"type": "string"
},
"acceptNetwork": {
"description": "Accept the network origins the manifest lists.",
"type": "boolean"
}
},
"required": [
"lesson",
"title"
]
}

Create a Layout topic from a document of learning components (flip cards, timelines, practice activities).

A Layout topic is a lesson body built from approved learning components instead of prose: Callout, Steps, ComparisonTable, H5PFrame, LiaScriptLesson, Timeline, FlipCards, CodeBlock and PracticeActivity (practice must use PracticeActivity). –document is a JSON (or YAML) list of nodes, [{ “component”: “Timeline”, “props”: {…}, “id”: “optional” }, …], inline or @path; the props of every component are listed in the learner layout manifest (front/ui/catalogue/learner-layout-manifest.json). –fallback is the Markdown shown by clients that do not render layouts and when the document cannot be rendered (inline or @path); leave hints and worked solutions out of it. The API validates the document and answers 422 with the node and prop path of every problem. The topic completes when the learner has viewed it, or after the first checked attempt when it holds a PracticeActivity.

Kind: write. Stability: stable. MCP tool: topics_create_layout. Scopes: courses:write.

Endpoints: POST /api/admin/topics.

Flag Type Required Description
--lesson integer yes Lesson id (from ulams lessons list --course-id <id>).
--title string yes Topic title.
--order integer Position in the lesson; default: after the last topic.
--summary string Short summary.
--preview boolean Visible without access to the course.
--active boolean Visible to learners (default true).
--can-skip boolean Learners may skip the topic.
--duration string Estimated duration, e.g. ‘10 min’.
--document array yes Layout nodes: a JSON list of { component, props, id? }, inline or @path.
--fallback string yes Markdown fallback, or @path to a Markdown file.
Terminal window
# Flip cards and a timeline for a chapter
ulams topics create-layout --lesson 12 --title "Coffee through time" --document @layout.json --fallback @layout.md --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"lesson": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lesson id (from `ulams lessons list --course-id <id>`)."
},
"title": {
"type": "string",
"description": "Topic title."
},
"order": {
"description": "Position in the lesson; default: after the last topic.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"summary": {
"description": "Short summary.",
"type": "string"
},
"preview": {
"description": "Visible without access to the course.",
"type": "boolean"
},
"active": {
"description": "Visible to learners (default true).",
"type": "boolean"
},
"canSkip": {
"description": "Learners may skip the topic.",
"type": "boolean"
},
"duration": {
"description": "Estimated duration, e.g. '10 min'.",
"type": "string"
},
"document": {
"minItems": 1,
"type": "array",
"items": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"description": "Layout nodes: a JSON list of { component, props, id? }, inline or @path."
},
"fallback": {
"type": "string",
"minLength": 1,
"fileInput": true,
"description": "Markdown fallback, or @path to a Markdown file."
}
},
"required": [
"lesson",
"title",
"document",
"fallback"
]
}

Create a LiaScript topic from Markdown or a .zip.

Kind: write. Stability: stable. MCP tool: topics_create_liascript. Scopes: courses:write.

Endpoints: POST /api/admin/liascript, POST /api/admin/topics.

Flag Type Required Description
--lesson integer yes Lesson id (from ulams lessons list --course-id <id>).
--title string yes Topic title.
--order integer Position in the lesson; default: after the last topic.
--summary string Short summary.
--preview boolean Visible without access to the course.
--active boolean Visible to learners (default true).
--can-skip boolean Learners may skip the topic.
--duration string Estimated duration, e.g. ‘10 min’.
--markdown string LiaScript Markdown, or @path.
--file string Local .zip with the course and its assets.
Terminal window
# A LiaScript course
ulams topics create-liascript --lesson 12 --title Lia --markdown @course.md --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"lesson": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lesson id (from `ulams lessons list --course-id <id>`)."
},
"title": {
"type": "string",
"description": "Topic title."
},
"order": {
"description": "Position in the lesson; default: after the last topic.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"summary": {
"description": "Short summary.",
"type": "string"
},
"preview": {
"description": "Visible without access to the course.",
"type": "boolean"
},
"active": {
"description": "Visible to learners (default true).",
"type": "boolean"
},
"canSkip": {
"description": "Learners may skip the topic.",
"type": "boolean"
},
"duration": {
"description": "Estimated duration, e.g. '10 min'.",
"type": "string"
},
"markdown": {
"fileInput": true,
"description": "LiaScript Markdown, or @path.",
"type": "string"
},
"file": {
"description": "Local .zip with the course and its assets.",
"type": "string"
}
},
"required": [
"lesson",
"title"
]
}

Create a topic that embeds a URL (YouTube, Vimeo and other oEmbed providers).

Kind: write. Stability: stable. MCP tool: topics_create_oembed. Scopes: courses:write.

Endpoints: POST /api/admin/topics.

Flag Type Required Description
--lesson integer yes Lesson id (from ulams lessons list --course-id <id>).
--title string yes Topic title.
--order integer Position in the lesson; default: after the last topic.
--summary string Short summary.
--preview boolean Visible without access to the course.
--active boolean Visible to learners (default true).
--can-skip boolean Learners may skip the topic.
--duration string Estimated duration, e.g. ‘10 min’.
--url string yes Page URL of the video or content.
Terminal window
# Embed a YouTube video
ulams topics create-oembed --lesson 12 --title Demo --url https://www.youtube.com/watch?v=abc --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"lesson": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lesson id (from `ulams lessons list --course-id <id>`)."
},
"title": {
"type": "string",
"description": "Topic title."
},
"order": {
"description": "Position in the lesson; default: after the last topic.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"summary": {
"description": "Short summary.",
"type": "string"
},
"preview": {
"description": "Visible without access to the course.",
"type": "boolean"
},
"active": {
"description": "Visible to learners (default true).",
"type": "boolean"
},
"canSkip": {
"description": "Learners may skip the topic.",
"type": "boolean"
},
"duration": {
"description": "Estimated duration, e.g. '10 min'.",
"type": "string"
},
"url": {
"type": "string",
"description": "Page URL of the video or content."
}
},
"required": [
"lesson",
"title",
"url"
]
}

Create a quiz topic with questions from a YAML or JSON file.

Input: { value?, maxAttempts?, minPassScore?, questions: [{ prompt, options: [{ text, correct }], score? } | { gift, score? }] }. Multiple choice questions are converted to GIFT; raw gift strings pass through.

Kind: write. Stability: stable. MCP tool: topics_create_quiz. Scopes: courses:write.

Endpoints: POST /api/admin/topics, POST /api/admin/gift-questions.

Flag Type Required Description
--lesson integer yes Lesson id (from ulams lessons list --course-id <id>).
--title string yes Topic title.
--order integer Position in the lesson; default: after the last topic.
--summary string Short summary.
--preview boolean Visible without access to the course.
--active boolean Visible to learners (default true).
--can-skip boolean Learners may skip the topic.
--duration string Estimated duration, e.g. ‘10 min’.
--max-attempts integer
--min-pass-score number
--questions array yes Questions (see the command description).
Terminal window
# A quiz
ulams topics create-quiz --lesson 12 --title Check --input @quiz.yaml --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"lesson": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lesson id (from `ulams lessons list --course-id <id>`)."
},
"title": {
"type": "string",
"description": "Topic title."
},
"order": {
"description": "Position in the lesson; default: after the last topic.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"summary": {
"description": "Short summary.",
"type": "string"
},
"preview": {
"description": "Visible without access to the course.",
"type": "boolean"
},
"active": {
"description": "Visible to learners (default true).",
"type": "boolean"
},
"canSkip": {
"description": "Learners may skip the topic.",
"type": "boolean"
},
"duration": {
"description": "Estimated duration, e.g. '10 min'.",
"type": "string"
},
"maxAttempts": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"minPassScore": {
"type": "number"
},
"questions": {
"type": "array",
"items": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"description": "Questions (see the command description)."
}
},
"required": [
"lesson",
"title",
"questions"
]
}

Create a rich text topic from Markdown or HTML.

Use for text lessons. Pass –markdown (inline text or @file.md) or –html. Markdown is converted to HTML on the client.

Kind: write. Stability: stable. MCP tool: topics_create_richtext. Scopes: courses:write.

Endpoints: POST /api/admin/topics.

Flag Type Required Description
--lesson integer yes Lesson id (from ulams lessons list --course-id <id>).
--title string yes Topic title.
--order integer Position in the lesson; default: after the last topic.
--summary string Short summary.
--preview boolean Visible without access to the course.
--active boolean Visible to learners (default true).
--can-skip boolean Learners may skip the topic.
--duration string Estimated duration, e.g. ‘10 min’.
--markdown string Markdown text, or @path to a Markdown file.
--html string HTML text, or @path to an HTML file.
Terminal window
# A text topic from a file
ulams topics create-richtext --lesson 12 --title Intro --markdown @intro.md --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"lesson": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lesson id (from `ulams lessons list --course-id <id>`)."
},
"title": {
"type": "string",
"description": "Topic title."
},
"order": {
"description": "Position in the lesson; default: after the last topic.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"summary": {
"description": "Short summary.",
"type": "string"
},
"preview": {
"description": "Visible without access to the course.",
"type": "boolean"
},
"active": {
"description": "Visible to learners (default true).",
"type": "boolean"
},
"canSkip": {
"description": "Learners may skip the topic.",
"type": "boolean"
},
"duration": {
"description": "Estimated duration, e.g. '10 min'.",
"type": "string"
},
"markdown": {
"fileInput": true,
"description": "Markdown text, or @path to a Markdown file.",
"type": "string"
},
"html": {
"fileInput": true,
"description": "HTML text, or @path to an HTML file.",
"type": "string"
}
},
"required": [
"lesson",
"title"
]
}

Create a SCORM topic from a package .zip.

Uploads the package, picks its SCO (the only one, or –sco), then creates the topic. Several SCOs without –sco exit 2 with details.choices.

Kind: write. Stability: stable. MCP tool: topics_create_scorm. Scopes: courses:write.

Endpoints: POST /api/admin/scorm/upload, POST /api/admin/topics.

Flag Type Required Description
--lesson integer yes Lesson id (from ulams lessons list --course-id <id>).
--title string yes Topic title.
--order integer Position in the lesson; default: after the last topic.
--summary string Short summary.
--preview boolean Visible without access to the course.
--active boolean Visible to learners (default true).
--can-skip boolean Learners may skip the topic.
--duration string Estimated duration, e.g. ‘10 min’.
--package string yes Local SCORM .zip.
--sco integer SCO id when the package has several.
Terminal window
# A SCORM package
ulams topics create-scorm --lesson 12 --title Safety --package ./pkg.zip --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"lesson": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lesson id (from `ulams lessons list --course-id <id>`)."
},
"title": {
"type": "string",
"description": "Topic title."
},
"order": {
"description": "Position in the lesson; default: after the last topic.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"summary": {
"description": "Short summary.",
"type": "string"
},
"preview": {
"description": "Visible without access to the course.",
"type": "boolean"
},
"active": {
"description": "Visible to learners (default true).",
"type": "boolean"
},
"canSkip": {
"description": "Learners may skip the topic.",
"type": "boolean"
},
"duration": {
"description": "Estimated duration, e.g. '10 min'.",
"type": "string"
},
"package": {
"type": "string",
"description": "Local SCORM .zip."
},
"sco": {
"description": "SCO id when the package has several.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"lesson",
"title",
"package"
]
}

Create a video topic from a local file, or from a YouTube URL.

–file uploads the video (mp4, ogg, webm, mov; processed in the background: use ulams operations wait video:<topic id>). –youtube-url creates an embedded topic.

Kind: write. Stability: stable. MCP tool: topics_create_video. Scopes: courses:write.

Endpoints: POST /api/admin/topics.

Flag Type Required Description
--lesson integer yes Lesson id (from ulams lessons list --course-id <id>).
--title string yes Topic title.
--order integer Position in the lesson; default: after the last topic.
--summary string Short summary.
--preview boolean Visible without access to the course.
--active boolean Visible to learners (default true).
--can-skip boolean Learners may skip the topic.
--duration string Estimated duration, e.g. ‘10 min’.
--file string Local video file.
--youtube-url string YouTube URL (embedded, no upload).
Terminal window
# Upload a video
ulams topics create-video --lesson 12 --title Intro --file ./intro.mp4 --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"lesson": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lesson id (from `ulams lessons list --course-id <id>`)."
},
"title": {
"type": "string",
"description": "Topic title."
},
"order": {
"description": "Position in the lesson; default: after the last topic.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"summary": {
"description": "Short summary.",
"type": "string"
},
"preview": {
"description": "Visible without access to the course.",
"type": "boolean"
},
"active": {
"description": "Visible to learners (default true).",
"type": "boolean"
},
"canSkip": {
"description": "Learners may skip the topic.",
"type": "boolean"
},
"duration": {
"description": "Estimated duration, e.g. '10 min'.",
"type": "string"
},
"file": {
"description": "Local video file.",
"type": "string"
},
"youtubeUrl": {
"description": "YouTube URL (embedded, no upload).",
"type": "string"
}
},
"required": [
"lesson",
"title"
]
}

Remove the specified Topic from storage.

Kind: destructive (idempotent). Stability: stable. MCP tool: topics_delete. Scopes: courses:write.

Endpoints: DELETE /api/admin/topics/{id}.

Flag Type Required Description
--id (positional) integer yes id of Topic
Terminal window
# Remove the specified Topic from storage
ulams topics delete 1 --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "id of Topic"
}
},
"required": [
"id"
],
"additionalProperties": {}
}

Display the specified Topic.

Kind: read (idempotent). Stability: stable. MCP tool: topics_get. Scopes: courses:read.

Endpoints: GET /api/admin/topics/{id}.

Flag Type Required Description
--id (positional) integer yes id of Topic
Terminal window
# Display the specified Topic
ulams topics get 1 --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "id of Topic"
}
},
"required": [
"id"
],
"additionalProperties": {}
}

Get a listing of the Topics.

Kind: read (idempotent). Stability: stable. MCP tool: topics_list. Scopes: courses:read.

Endpoints: GET /api/admin/topics.

Terminal window
# Get a listing of the Topics
ulams topics list --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {},
"additionalProperties": {}
}

Post new resource.

Kind: write. Stability: stable. MCP tool: topics_resources_add. Scopes: courses:write.

Endpoints: POST /api/admin/topics/{topic_id}/resources/.

Flag Type Required Description
--topic-id (positional) integer yes id of Topic
--resource string resource (path of a local file)
Terminal window
# Post new resource
ulams topics resources-add 1 --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"topic_id": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "id of Topic"
},
"resource": {
"type": "string",
"description": "resource (path of a local file)"
}
},
"required": [
"topic_id"
],
"additionalProperties": {}
}

Delete resource.

Kind: destructive (idempotent). Stability: stable. MCP tool: topics_resources_delete. Scopes: courses:write.

Endpoints: DELETE /api/admin/topics/{topic_id}/resources/{resource_id}.

Flag Type Required Description
--topic-id (positional) integer yes id of Topic
--resource-id (positional) integer yes id of Resource
Terminal window
# Delete resource
ulams topics resources-delete 1 1 --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"topic_id": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "id of Topic"
},
"resource_id": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "id of Resource"
}
},
"required": [
"topic_id",
"resource_id"
],
"additionalProperties": {}
}

Get list of resources.

Kind: read (idempotent). Stability: stable. MCP tool: topics_resources_list. Scopes: courses:read.

Endpoints: GET /api/admin/topics/{topic_id}/resources/.

Flag Type Required Description
--topic-id (positional) integer yes id of Topic
Terminal window
# Get list of resources
ulams topics resources-list 1 --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"topic_id": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "id of Topic"
}
},
"required": [
"topic_id"
],
"additionalProperties": {}
}

Rename resource.

Kind: write. Stability: stable. MCP tool: topics_resources_update. Scopes: courses:write.

Endpoints: PATCH /api/admin/topics/{topic_id}/resources/{resource_id}.

Flag Type Required Description
--topic-id (positional) integer yes id of Topic
--resource-id (positional) integer yes id of Resource
--name string
Terminal window
# Rename resource
ulams topics resources-update 1 1 --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"topic_id": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "id of Topic"
},
"resource_id": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "id of Resource"
},
"name": {
"type": "string"
}
},
"required": [
"topic_id",
"resource_id"
],
"additionalProperties": {}
}

Get a listing of the Availabe Topic Content Types Classes.

Kind: read (idempotent). Stability: stable. MCP tool: topics_types. Scopes: courses:read.

Endpoints: GET /api/admin/topics/types.

Terminal window
# Get a listing of the Availabe Topic Content Types Classes
ulams topics types --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {},
"additionalProperties": {}
}

Update the specified Topic in storage.

Kind: write (idempotent). Stability: stable. MCP tool: topics_update. Scopes: courses:write.

Endpoints: PUT /api/admin/topics/{id}.

Flag Type Required Description
--id (positional) integer yes id of Topic
--active boolean active
--can-skip boolean can skip
--description string description
--duration string duration
--introduction string introduction
--json object json
--lesson-id integer lesson_id
--order integer order
--preview boolean preview
--summary string summary
--title string title
--topicable-id integer topicable_id
--topicable-type string topicable_type
--value string value
Terminal window
# Update the specified Topic in storage
ulams topics update 1 --json
Input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "id of Topic"
},
"active": {
"type": "boolean",
"description": "active"
},
"can_skip": {
"type": "boolean",
"description": "can skip"
},
"description": {
"type": "string",
"description": "description"
},
"duration": {
"type": "string",
"description": "duration"
},
"introduction": {
"type": "string",
"description": "introduction"
},
"json": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {},
"description": "json"
},
"lesson_id": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "lesson_id"
},
"order": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "order"
},
"preview": {
"type": "boolean",
"description": "preview"
},
"summary": {
"type": "string",
"description": "summary"
},
"title": {
"type": "string",
"description": "title"
},
"topicable_id": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "topicable_id"
},
"topicable_type": {
"type": "string",
"description": "topicable_type"
},
"value": {
"type": "string",
"description": "value"
}
},
"required": [
"id"
],
"additionalProperties": {}
}