add_cards
ChatGPTAdds one or more cards to a deck, in order. Free. Each card is a JSON object: {template?, front:{prompt, hint?}, back:{answer, image?, imageAlt?, analogy?, points?, readMore?}, difficulty?, tags?, order?}. template is one of basic, concept, interview (defaults to basic when adding; omit to leave unchanged when updating). front.prompt and back.answer are required plain text; back.image is an image URL returned by upload_card_image (a /cards/images/{name} path) or omitted; back.points is an array of short strings. difficulty is 1-5 or omitted. Rich text markers usable in prompt, hint, back.answer, back.analogy, back.points items and back.readMore: code (backticks for inline code), <b>bold</b>, <hl>highlighted</hl>, <color c="red">text</color> (c is one of red, green, blue, amber, purple), and <icon name="star" /> (a small icon by name). Only back.answer additionally understands line-level lists: lines starting with "- ", "* " or "• " render as a bullet list; other line breaks stack as separate lines. back.answer may instead be a small block document, one block tag per line: <paragraph>, <heading>, <nutshell>, <analogy>, <example>, <callout style="key|tip|warning">, <points><item>...</item><item depth="1">sub-bullet</item></points>, <table><row header="true"><cell>...</cell></row><row><cell>...</cell></row></table> (cells hold inline text only) and <code>verbatim code</code> (escape < > & in block text as < > &; no diagrams (D2 or Mermaid) on cards - those are course-chapter only). Any other HTML-looking tag is stripped on save. Full reference with examples: get_formatting_guide(topic="card"). Returns a JSON array of the created cards (see get_deck for the card shape).
add_chapter
ChatGPTAdds one empty chapter to a course. Free, no AI. Fill it in afterward with update_chapter. Returns the new chapter.
add_course_note
ChatGPTAdds a note to a course, optionally attached to one chapter. Free, manual (not AI). Returns the created note.
check_diagram
ChatGPTCompiles D2 diagram source - the text of a chapter code block with lang "d2", Lernoa's diagram language - with the same renderer the course reader uses, and says whether it draws. Free, changes nothing. Call it for every diagram you write, before update_chapter or import_course_file, and fix what it reports. Returns {valid, error}: error is the compiler's message with line numbers when valid is false. D2 syntax and rules: get_formatting_guide(topic="diagram").
create_course
ChatGPTCreates a blank course (no AI) with just a title. Free, synchronous. Add chapters afterward with add_chapter and update_chapter. Returns the created course summary.
create_deck
ChatGPTCreates a new empty deck. Free. Returns the created deck's detail JSON (see get_deck). defaultTemplate, if set, should be one of "basic", "concept", "interview".
create_subject
ChatGPTCreates a new subject folder. Free. Returns the created subject.
delete_card
ChatGPTPermanently deletes one card and its review history. Free, irreversible.
delete_card_image
ChatGPTPermanently deletes one uploaded card image. Free, irreversible. Any card still referencing it in back.image will show a broken image.
delete_chapter
ChatGPTDeletes one chapter: its quiz, notes, highlights and cached narration, and renumbers the remaining chapters. Free, irreversible.
delete_course
ChatGPTPermanently deletes a course: its chapters, quizzes, exam, notes, highlights and cached narration. Free, irreversible. Does not delete the source document or any linked deck.
delete_course_note
ChatGPTDeletes a course note. Free, irreversible.
delete_deck
ChatGPTPermanently deletes a deck and all of its cards and review history. Free (no credits involved), but irreversible.
delete_material
ChatGPTPermanently deletes a document and its stored file. Free, irreversible. Courses already built from it are NOT deleted.
delete_subject
ChatGPTPermanently deletes a subject folder AND every course filed under it, including those courses' chapters, quizzes, exam, notes, highlights and cached narration. Free, irreversible. Decks and documents are NOT deleted; their subject association is removed.
export_course
ChatGPTExports a ready course as a Lernoa course file (.md, format lernoa-course/v2). Returns the raw file text, not JSON. The course file format ("lernoa-course/v2") is an XML-like tag document, not real markdown, despite the .md extension. Root: <course format="lernoa-course/v2" subject="..." level="beginner|intermediate|advanced|exam" language="..." icon="..." tags="a,b"> containing exactly one <title>...</title> (required), one optional <summary>...</summary>, 1 to 50 <chapter title="...">...</chapter> elements (required), and an optional single <exam>...</exam>. A <chapter> contains an optional <summary>, an optional <content> with block tags (<paragraph>, <heading>, <nutshell>, <analogy>, <example>, <callout style="key|tip|warning">, <code> verbatim (or <code lang="d2"> for a diagram whose body is D2 source - Lernoa's diagram language, check it with check_diagram - drawn as a diagram when read; <code lang="mermaid"> with Mermaid source is still accepted), <points><item>...</item>...</points> (<item depth="1"> to "3" nests an item as a sub-bullet under the item above), <table><row header="true"><cell>...</cell>...</row><row><cell>...</cell>...</row></table> (header="true" marks the heading row; at most 12 columns and 60 rows; cells hold inline text only), and self-closing <image src="/cards/images/..." alt="..." />), and an optional <quiz> with <question kind="mcq|multi"> elements, each holding one <prompt>, 2 to 10 <choice correct="true|false">...</choice>, and an optional <explanation>; a <question kind="ordering"> lists 2 to 10 <item>...</item> in the CORRECT order instead of choices (learners see them shuffled), and a <question kind="matching"> holds 2 to 10 <pair><item>...</item><match>...</match></pair> plus optional extra <choice> options that match nothing. Text inside title/summary/prompt/choice/explanation/block text/item/cell accepts backtick code, bold or <b>bold</b>, ==highlight== or <hl>highlight</hl>, {red|green|blue|amber|purple}text{/color} or <color c="red">text</color>, <icon name="star" />, and (inside chapter <content> only) <note>tip text</note> which becomes an adjacent tip callout. Malformed inline markup degrades to literal text with a warning rather than failing the import; missing required structure (no title, no chapters, unknown top-level tags) is a hard error. Full format with limits and examples: get_formatting_guide(topic="course_file").
export_deck
ChatGPTExports a deck to CSV (columns: front, back, hint, difficulty, tags). Returns the raw CSV text, not JSON.
fetch
ChatGPTGets one item by the id returned from search: deck questions and answers, course chapter text, document metadata and outline (not the document body), or a subject summary. Free. May compute and save missing course study-time estimates or detect and save a missing document language. Returns {id, title, text, url, metadata}.
generate_cards_from_material
ChatGPTSpends AI credits: generates flashcards from an uploaded document (the whole document, a page range, a pasted selection, or the document's highlights) and appends them to that document's deck. Cost is ceil(count/25) credits, clamped 1-10 (an account's first AI deck of up to 60 cards is free); for source="selection" a null/zero count lets the AI pick how many. Returns {deckId, deckSlug, deckTitle, createdCount, skippedDuplicateCount, cards: [...]} - not the full deck.
generate_course_ai
ChatGPTSpends AI credits: starts building a structured course (chapters, quizzes, exam) from a topic - no source document. Cost is 1 credit per chapter (3-20 chapters), built on the Standard AI model, never more than 20, charged as the background build runs. Returns immediately with a build job {id, status, courseId, error, quotaExceeded} - poll get_course_build_status with its id until status is "done" or "failed". courseId appears as soon as the course outline exists, while its chapters are still being written (get_course shows each chapter's buildStatus); only status "done" means the whole course is finished.
generate_course_from_material
ChatGPTSpends AI credits: starts building a structured course (chapters, quizzes, exam) from an uploaded document. Cost is 1 credit per chapter (3-20 chapters), built on the Standard AI model, never more than 20, charged as the background build runs. Returns immediately with a build job {id, status, courseId, error, quotaExceeded} - poll get_course_build_status with its id until status is "done" or "failed". courseId appears as soon as the course outline exists, while its chapters are still being written (get_course shows each chapter's buildStatus); only status "done" means the whole course is finished.
generate_deck_ai
ChatGPTSpends AI credits: generates a new flashcard deck on a topic. Cost is ceil(count/25) credits, clamped 1-10 (25 cards = 1 credit, up to 250 cards = 10 credits); an account's first AI deck of up to 60 cards is free and takes no credits. Fails with a credits error and charges nothing if the balance is too low. Time grows with size (roughly a minute per 50 cards, up to about 4-5 minutes for 250); if the call times out the deck may still appear, so check list_decks before retrying. Returns the created deck detail (see get_deck).
get_chapter
ChatGPTGets one chapter of a course WITH its content blocks. May compute and save missing study-time estimates for its course while retrieving it. A chapter's content is {blocks: [block, ...]} (at most 180 blocks). Each block has a "type": heading, paragraph, nutshell (key takeaway), analogy or example (all {type, text, align?}); callout ({type, style: "key"|"tip"|"warning", text, align?}); points ({type, items: [string, ...]} - a bulleted list; start an item with one TAB character (\t) per level to make it a sub-bullet of the item above, up to 3 levels, e.g. ["Service models", "\tIaaS", "\t\tYou manage the OS"]); table ({type, rows: [{cells: [string, ...], header?: true}, ...]} - header:true renders that row as the heading row; at most 12 columns and 60 rows; cells hold inline text only, no lists or code; ragged rows are padded, so give every row the same number of cells); code ({type, text, lang?} - verbatim source with real newlines, no rich markers; the optional lang "d2" makes the block a DIAGRAM drawn from the D2 (d2lang.com) source in text - D2 is Lernoa's diagram language, e.g. {"type":"code","lang":"d2","text":"direction: right\nstart: Start\nready: \"Ready?\" {shape: diamond}\ndone: Done\nstart -> ready\nready -> done: Yes"} - declare each shape as id: Label, connect ids with -> and an optional : label, pick a shape with {shape: diamond|cylinder|person|queue|cloud|...}, nest shapes in a container (vpc: VPC {web: Web}) reached as vpc.web, use shape: sequence_diagram on the first line for messages over time; keep it to about 12 shapes with short labels, double-quote labels containing ; { } | or quotes, never use a D2 keyword (shape, label, style, direction, icon, link, class, vars...) as an id, no markdown fences and no style/classes/vars (the app themes it); compile it first with check_diagram. lang "mermaid" (Mermaid source) is still accepted for existing diagrams; any other lang is ignored and the block stays plain code); or image ({type, url, alt} - url MUST be a /cards/images/{name} path from upload_card_image, no external URLs allowed). align is optional: "left", "center" or "right". Text is one paragraph per block (line breaks collapse to spaces - use another block or points for new lines); text, items and cells use the same inline grammar as cards: code (backticks), <b>bold</b>, <hl>highlighted</hl>, <color c="red">text</color> (red, green, blue, amber or purple), <icon name="star" />. No markdown (no #, **, | tables or - bullets inside text), no links, no other HTML. Full reference with a worked example and the valid icon names: get_formatting_guide(topic="chapter").
get_course
ChatGPTGets a course's metadata and its chapter OUTLINE (id, order, title, summary, quizQuestionCount, estimatedMinutes) with chapter content blocks stripped, to save context on long courses. May compute and save missing study-time estimates for an older course. Course-level estimatedMinutes/examEstimatedMinutes give the whole course's estimated study time. Call get_chapter for one chapter's full content. While the AI is still building the course (status "generating") a chapter that is not written yet has buildStatus "writing" ("failed" if it could not be written; absent = written), and the final exam appears when the course turns "ready"; get_chapter on an unwritten chapter returns a short message instead of content.
get_course_build_status
ChatGPTPolls the status of a course build started by generate_course_ai or generate_course_from_material. Free - polling itself never spends credits; the background build charges credits independently when it runs. Returns {id, status, courseId, error, quotaExceeded, createdAt, updatedAt}; status is queued, building, done, or failed. courseId is set as soon as the course outline exists, before the build is finished: while status is still building, the course is already readable but some chapters have buildStatus "writing"; only done means every chapter and the exam are written.
get_credit_balance
ChatGPTReads the user's current AI credit balance. Free - checking never spends credits. Returns {creditsAvailable, freeCreditsAvailable, hasUnlimited, unlimitedExpiresAt, fairUseDailyScans, fairUseUsedToday, premiumUnlocked} from GET /wallet. premiumUnlocked says whether the account has bought credits at least once, which unlocks the Premium and Frontier AI models in the Lernoa app (these tools always use the Standard model).
get_deck
ChatGPTGets one deck with all of its cards. Returns the JSON from GET /decks/{id}: id, slug, name, description, icon, difficultyLevel, defaultTemplate, source, language, ttsAvailable, and cards (each card has id, sourceKey, template, content {front:{prompt,hint}, back:{answer,image,imageAlt,analogy,points,readMore}}, difficulty, tags, order).
get_formatting_guide
ChatGPTReturns Lernoa's content formatting reference. Free, read-only. Lernoa text is a small closed tag grammar, not Markdown or HTML: call this before writing chapter content (update_chapter), flashcards (add_cards, update_card), a course file (import_course_file) or notes whenever you are unsure of a shape or a value. topic: overview (default - which tool takes which shape, the inline tags and the rules that hold everywhere), inline, chapter (the JSON blocks with a worked example), card, diagram (D2 — Lernoa's diagram language; Mermaid still accepted), course_file (the complete lernoa-course/v2 format), or all. Returns {topic, topics, guide (Markdown text for that topic), vocabulary} - vocabulary holds the ONLY valid values for colors, calloutStyles, alignments, icons (inline <icon> tags and a course's icon), deckIcons, levels, languages, cardTemplates, questionKinds, chapterBlockTypes, diagramLanguages, d2Shapes and mermaidTypes.
get_material
ChatGPTGets one document's detail: title, kind, status, page count/outline, reading progress, bookmarks, annotations, and linked decks. May detect and save a missing document language for an older document. Returns the JSON from GET /materials/{id}.
get_quiz
ChatGPTGets one chapter's quiz questions - prompt and choices only, no correct answers or explanations (grading is server-authoritative). Returns a JSON array of {id, chapterId, order, kind, prompt, choices, items} - items are what a matching question's choices are matched to (empty for every other kind); an ordering question's choices are shuffled.
get_study_settings
ChatGPTReads the user's study settings. Free. Returns {dailyNewLimit, maxReviews, reminderFrequency, reminderTime, theme, srsOverrides, reminderSchedule, preferences} from GET /study/settings.
get_study_stats
ChatGPTReads one day's study activity: reviews done and new cards introduced per deck. Free. Returns {day, reviewsDone, introducedByDeck} from GET /study/daily.
get_tts_voices
ChatGPTLists every audio-narration language's accent choices and the user's current pick. Free. Returns a JSON array of {language, selected, options: [{voiceId, label, isDefault}]}.
import_course_file
ChatGPTImports one Lernoa course file into a new course. Free, no AI. The course file format ("lernoa-course/v2") is an XML-like tag document, not real markdown, despite the .md extension. Root: <course format="lernoa-course/v2" subject="..." level="beginner|intermediate|advanced|exam" language="..." icon="..." tags="a,b"> containing exactly one <title>...</title> (required), one optional <summary>...</summary>, 1 to 50 <chapter title="...">...</chapter> elements (required), and an optional single <exam>...</exam>. A <chapter> contains an optional <summary>, an optional <content> with block tags (<paragraph>, <heading>, <nutshell>, <analogy>, <example>, <callout style="key|tip|warning">, <code> verbatim (or <code lang="d2"> for a diagram whose body is D2 source - Lernoa's diagram language, check it with check_diagram - drawn as a diagram when read; <code lang="mermaid"> with Mermaid source is still accepted), <points><item>...</item>...</points> (<item depth="1"> to "3" nests an item as a sub-bullet under the item above), <table><row header="true"><cell>...</cell>...</row><row><cell>...</cell>...</row></table> (header="true" marks the heading row; at most 12 columns and 60 rows; cells hold inline text only), and self-closing <image src="/cards/images/..." alt="..." />), and an optional <quiz> with <question kind="mcq|multi"> elements, each holding one <prompt>, 2 to 10 <choice correct="true|false">...</choice>, and an optional <explanation>; a <question kind="ordering"> lists 2 to 10 <item>...</item> in the CORRECT order instead of choices (learners see them shuffled), and a <question kind="matching"> holds 2 to 10 <pair><item>...</item><match>...</match></pair> plus optional extra <choice> options that match nothing. Text inside title/summary/prompt/choice/explanation/block text/item/cell accepts backtick code, bold or <b>bold</b>, ==highlight== or <hl>highlight</hl>, {red|green|blue|amber|purple}text{/color} or <color c="red">text</color>, <icon name="star" />, and (inside chapter <content> only) <note>tip text</note> which becomes an adjacent tip callout. Malformed inline markup degrades to literal text with a warning rather than failing the import; missing required structure (no title, no chapters, unknown top-level tags) is a hard error. Full format with limits and examples: get_formatting_guide(topic="course_file"). Returns {files: [{fileName, ok, courseId, title, chapters, questions, error, warning}]} - check ok and error/warning on the single result.
list_card_images
ChatGPTLists the user's own previously uploaded card illustrations, most recent first. Returns a JSON array of {fileName, url, ...}.
list_courses
ChatGPTLists the user's courses. May compute and save missing study-time estimates for older courses. Returns a JSON array from GET /courses: id, title, summary, status, level, icon, chapterCount, hasExam, sourceMaterialId, percentComplete, examPassed, subjectId, tags, linkedDeckId, estimatedMinutes (estimated study time for the whole course), remainingMinutes (that estimate minus what the user has already completed), etc. A course still being built by the AI has status "generating" (and chaptersReady = how many chapters are written so far); status "failed" comes with a statusMessage; status "ready" is a finished course.
list_decks
ChatGPTLists the signed-in user's flashcard decks with per-deck due/new card counts. Returns the JSON array from GET /decks: each item has id, slug, name, description, icon, difficultyLevel, source, cardCount, dueCount, newCount, subjectId, subjectName, subjectColor, linkedCourseId, linkedCourseTitle.
list_materials
ChatGPTLists the user's uploaded documents. Returns a JSON array from GET /materials: id, title, kind, status, pageCount, sizeBytes, subjectId, tags, deckCount, percentRead, etc.
list_subjects
ChatGPTLists the user's subject folders. Returns a JSON array of {id, name, color, materialCount, sortOrder, isArchived}. Archived subjects are hidden from the app's course list by default but remain fully intact.
reorder_cards
ChatGPTPersists a full drag-and-drop reorder of a deck's cards. cardIds must be exactly the deck's current card ids, in the desired order. Free. Returns the deck's cards in their new order.
reorder_chapters
ChatGPTPersists a full reorder of a course's chapters. chapterIds must be exactly the course's current chapter ids, in the desired order. Free. Returns the chapters in their new order (outline only - see get_course).
search
ChatGPTSearches the user's own decks, courses, documents and subjects by title/name and description/summary. Free. May compute and save missing study-time estimates while listing older courses. Returns {results: [{id, title, url}]}, best match first (at most 25). Any of the query's words can match, so natural phrasing works. ids are prefixed by kind: "deck:{guid}", "course:{guid}", "material:{guid}" (an uploaded document), "subject:{guid}" - pass one straight to fetch.
set_tts_voice
ChatGPTSets (or clears) the narration accent for one language. Free - this is a preference, not generation; audio for the newly picked voice is synthesized lazily the next time it's listened to. Applies to both course and flashcard narration for that language.
update_card
ChatGPTEdits one card. Free. IMPORTANT: content and difficulty are FULL REPLACEMENTS, not a partial patch - call get_deck first and pass back every field of content you want to keep (an omitted content field is cleared, and omitting difficulty entirely clears it to none). template, tags and order ARE partial: omit any of those three to leave them unchanged. Each card is a JSON object: {template?, front:{prompt, hint?}, back:{answer, image?, imageAlt?, analogy?, points?, readMore?}, difficulty?, tags?, order?}. template is one of basic, concept, interview (defaults to basic when adding; omit to leave unchanged when updating). front.prompt and back.answer are required plain text; back.image is an image URL returned by upload_card_image (a /cards/images/{name} path) or omitted; back.points is an array of short strings. difficulty is 1-5 or omitted. Rich text markers usable in prompt, hint, back.answer, back.analogy, back.points items and back.readMore: code (backticks for inline code), <b>bold</b>, <hl>highlighted</hl>, <color c="red">text</color> (c is one of red, green, blue, amber, purple), and <icon name="star" /> (a small icon by name). Only back.answer additionally understands line-level lists: lines starting with "- ", "* " or "• " render as a bullet list; other line breaks stack as separate lines. back.answer may instead be a small block document, one block tag per line: <paragraph>, <heading>, <nutshell>, <analogy>, <example>, <callout style="key|tip|warning">, <points><item>...</item><item depth="1">sub-bullet</item></points>, <table><row header="true"><cell>...</cell></row><row><cell>...</cell></row></table> (cells hold inline text only) and <code>verbatim code</code> (escape < > & in block text as < > &; no diagrams (D2 or Mermaid) on cards - those are course-chapter only). Any other HTML-looking tag is stripped on save. Full reference with examples: get_formatting_guide(topic="card"). Returns the updated card.
update_chapter
ChatGPTEdits a chapter's title, summary and/or content blocks. Free, no AI - always manual editing. Null title/summary/content are left unchanged (an empty summary clears it); content, if provided, REPLACES the whole blocks array. A chapter's content is {blocks: [block, ...]} (at most 180 blocks). Each block has a "type": heading, paragraph, nutshell (key takeaway), analogy or example (all {type, text, align?}); callout ({type, style: "key"|"tip"|"warning", text, align?}); points ({type, items: [string, ...]} - a bulleted list; start an item with one TAB character (\t) per level to make it a sub-bullet of the item above, up to 3 levels, e.g. ["Service models", "\tIaaS", "\t\tYou manage the OS"]); table ({type, rows: [{cells: [string, ...], header?: true}, ...]} - header:true renders that row as the heading row; at most 12 columns and 60 rows; cells hold inline text only, no lists or code; ragged rows are padded, so give every row the same number of cells); code ({type, text, lang?} - verbatim source with real newlines, no rich markers; the optional lang "d2" makes the block a DIAGRAM drawn from the D2 (d2lang.com) source in text - D2 is Lernoa's diagram language, e.g. {"type":"code","lang":"d2","text":"direction: right\nstart: Start\nready: \"Ready?\" {shape: diamond}\ndone: Done\nstart -> ready\nready -> done: Yes"} - declare each shape as id: Label, connect ids with -> and an optional : label, pick a shape with {shape: diamond|cylinder|person|queue|cloud|...}, nest shapes in a container (vpc: VPC {web: Web}) reached as vpc.web, use shape: sequence_diagram on the first line for messages over time; keep it to about 12 shapes with short labels, double-quote labels containing ; { } | or quotes, never use a D2 keyword (shape, label, style, direction, icon, link, class, vars...) as an id, no markdown fences and no style/classes/vars (the app themes it); compile it first with check_diagram. lang "mermaid" (Mermaid source) is still accepted for existing diagrams; any other lang is ignored and the block stays plain code); or image ({type, url, alt} - url MUST be a /cards/images/{name} path from upload_card_image, no external URLs allowed). align is optional: "left", "center" or "right". Text is one paragraph per block (line breaks collapse to spaces - use another block or points for new lines); text, items and cells use the same inline grammar as cards: code (backticks), <b>bold</b>, <hl>highlighted</hl>, <color c="red">text</color> (red, green, blue, amber or purple), <icon name="star" />. No markdown (no #, **, | tables or - bullets inside text), no links, no other HTML. Full reference with a worked example and the valid icon names: get_formatting_guide(topic="chapter"). Replacing content re-anchors the chapter's highlights to the new text; highlights whose text no longer appears are permanently deleted. Returns the updated chapter.
update_course
ChatGPTRenames a course and/or moves it to a subject, sets tags, sets a display course number, and/or links its deck. Free. Null fields are left unchanged; clearSubject/clearCourseNumber/clearDeck remove those values (clearDeck wins over deckId). Overwrites the previous value of every field it changes: tags REPLACE the whole tag list; courseNumber (or moving to another subject) renumbers the other courses in the affected subject(s); and deckId moves the deck's link away from any other course that holds it. Chapters, quizzes, notes and progress are never touched. Returns the updated course summary.
update_course_note
ChatGPTEdits a course note's text. Free. The new text REPLACES the whole note. Returns the updated note.
update_deck
ChatGPTEdits a deck's name, description, icon, difficulty, subject folder, and/or linked course. Free. Null fields are left unchanged; set clearSubject=true to un-file it, or clearCourse=true to unlink its course (clearCourse wins over courseId). Overwrites the previous value of every field it changes: the new name and description replace the old text (get_deck shows the current values, so read them first if they may be needed), and because a deck links to at most one course, courseId moves the deck's link away from any other course that held it. The deck's cards and review history are never touched. Returns the updated deck summary.
update_material
ChatGPTRenames a document, files it under a subject, and/or replaces its tags. Free. Null fields are left unchanged; clearSubject removes its subject folder. Overwrites the previous value of every field it changes: the new title replaces the old one and tags REPLACE the whole tag list (list_materials shows the current values, so read them first if they may be needed). The file itself, its pages, highlights, notes, bookmarks, reading progress, linked decks and built courses are never touched. Returns the updated document summary.
update_study_settings
ChatGPTReplaces the user's study settings. Free. IMPORTANT: this is a FULL REPLACE, not a partial patch - call get_study_settings first and pass back every field, changing only what you want to change. Returns the saved settings.
update_subject
ChatGPTRenames a subject, changes its color, and/or archives or restores it. Free. Overwrites the previous value of every field it changes: the new name replaces the old one (list_subjects shows the current values, so read them first if they may be needed). Archiving a subject that holds a whole certification's courses and nothing else also archives that certification, and restoring it brings the certification back. The courses, decks and documents filed under it are never deleted. Returns the updated subject.
upload_card_image
ChatGPTUploads a small image (fair-use capped at 5 MB) to use as a card's back.image. Free. Send the raw file content base64-encoded. Returns {fileName, url, ...} - url is a /cards/images/{fileName} path; put that exact string in a card's back.image field when calling add_cards or update_card.
upload_material
ChatGPTUploads a document (PDF or DOCX, decoded size capped at 15 MB) to the Learning Center. Free, fair-use capped (250 MB/file, 200 documents, 2 GB total account-wide). Send the raw file content base64-encoded. The document itself is view/download only - use generate_course_from_material to build a studyable course from it. Returns the created document summary.