{"openapi":"3.1.0","info":{"title":"ScormStack API","version":"1.0.0","description":"The ScormStack API allows you to programmatically create, manage, and export learning courses.\n\n## Authentication\n\nAll API endpoints require authentication using a Personal Access Token (PAT):\n\n```bash\ncurl -H \"Authorization: Bearer pat_xxxxxxxxxxxxxxxxxxxxx\" \\\n  https://app.scormstack.com/api/v1/courses\n```\n\n### Getting a Token\n\n1. Log into the ScormStack web application\n2. Navigate to **Settings → API Tokens**\n3. Click **Create Token** and select the required scopes\n4. Copy the token immediately (it won't be shown again)\n\n### Token Scopes\n\nTokens can be created with specific scopes to limit access:\n\n| Scope | Description |\n|-------|-------------|\n| `api:*` | Full access to all API endpoints |\n| `courses:read` | Read course information |\n| `courses:create` | Create new courses |\n| `courses:update` | Edit and publish courses, including starting package exports |\n| `courses:delete` | Delete courses |\n| `sections:*` | Full access to sections |\n| `slides:*` | Full access to slides |\n| `blocks:*` | Full access to blocks |\n| `assets:read` | List and view assets |\n| `assets:create` | Upload new assets |\n| `assets:delete` | Delete assets |\n| `locales:read` | List locales and export translations |\n| `locales:write` | Import translations |\n| `analytics:read` | List and export course learner analytics |\n| `analytics:delete` | Delete course learner analytics |\n\n## Rate Limiting\n\nAPI requests are limited to **100 requests per minute** per token. Rate limit headers are included in all responses:\n\n- `X-RateLimit-Limit`: Maximum requests per window\n- `X-RateLimit-Remaining`: Requests remaining in current window\n- `X-RateLimit-Reset`: Unix timestamp when the window resets\n\n## Errors\n\nThe API uses standard HTTP status codes and returns error details in JSON format:\n\n```json\n{\n  \"error\": \"Validation failed\",\n  \"code\": \"VALIDATION_ERROR\",\n  \"details\": {\n    \"field\": \"title\",\n    \"reason\": \"Title is required\"\n  }\n}\n```\n\n## Block Types and Content Schemas\n\nEach block type has a specific content structure. Use the appropriate schema based on the `type` field:\n\n| Block Type | Content Schema | Description |\n|------------|----------------|-------------|\n| `text` | TextBlockContent | Text content with heading and paragraphs |\n| `image` | ImageBlockContent | Image with caption and positioning options |\n| `video` | VideoBlockContent | YouTube, Vimeo, or uploaded video |\n| `audio` | AudioBlockContent | Audio player with visualization |\n| `flow` | FlowBlockContent | Step-by-step guided experience |\n| `timeline` | TimelineBlockContent | Chronological events with expandable details |\n| `flashcards` | FlashcardsBlockContent | Interactive flashcard deck |\n| `accordion` | AccordionBlockContent | Collapsible content sections |\n| `tabs` | TabsBlockContent | Tabbed content panels |\n| `assessment` | AssessmentBlockContent | Multi-question quiz assessment |\n| `fill_in_blank` | FillInBlankBlockContent | Fill-in-the-blank assessment |\n| `matching` | MatchingBlockContent | Match items between columns |\n| `click_on_image` | ClickOnImageBlockContent | Click on correct image areas |\n| `interactive_image` | InteractiveImageBlockContent | Image with clickable hotspots |\n| `web_simulation` | WebSimulationBlockContent | Interactive app walkthrough |\n| `success_meter` | SuccessMeterBlockContent | Scenario-based assessment |\n| `categorization` | CategorizationBlockContent | Sort items into categories |\n| `sorting` | SortingBlockContent | Sort items into a sequence |\n| `open_response` | OpenResponseBlockContent | Free-text response |\n| `callout` | CalloutBlockContent | Highlighted info/tip/warning box |\n| `list` | ListBlockContent | Bullet, numbered, or icon list |\n| `separator` | SeparatorBlockContent | Visual divider between sections |\n| `resources` | ResourcesBlockContent | Downloadable resources list |\n| `embed` | EmbedBlockContent | Embedded iframe content |\n| `pdf` | PdfBlockContent | PDF viewer |\n| `slide_intro` | SlideIntroBlockContent | Lesson introduction slide |\n| `navigation_button` | NavigationButtonBlockContent | Navigation control button |\n| `reactions` | ReactionsBlockContent | Single-choice learner reaction feedback |\n\nSee the **Schemas** section below for detailed content structure of each block type.\n","contact":{"name":"ScormStack Support","url":"https://scormstack.com/support"}},"servers":[{"url":"/api/v1","description":"V1 API"}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"PAT","description":"Personal Access Token (format: pat_xxx...)"}},"schemas":{"Error":{"type":"object","description":"Represents an API error response.","properties":{"error":{"type":"string","description":"A human-readable error message describing what went wrong.","example":"Course not found"},"code":{"type":"string","description":"A machine-readable error code for programmatic handling.","example":"RESOURCE_NOT_FOUND"},"details":{"type":"object","description":"Additional context about the error, such as validation failures.","example":{"field":"title","reason":"Title is required"}}},"required":["error"],"example":{"error":"Validation failed","code":"VALIDATION_ERROR","details":{"field":"title","reason":"Title must be between 1 and 255 characters"}}},"Pagination":{"type":"object","description":"Pagination metadata for list responses.","properties":{"page":{"type":"integer","description":"Current page number (1-indexed).","example":1},"limit":{"type":"integer","description":"Number of items per page.","example":20},"total":{"type":"integer","description":"Total number of items across all pages.","example":42},"totalPages":{"type":"integer","description":"Total number of pages available.","example":3}},"example":{"page":1,"limit":20,"total":42,"totalPages":3}},"LearnerAnalytics":{"type":"object","description":"A learner's current course analytics and aggregated session data.","properties":{"id":{"type":"string","format":"uuid"},"learner_id":{"type":"string","example":"learner-1042"},"learner_email":{"type":["string","null"],"format":"email","example":"ada@example.com"},"learner_name":{"type":["string","null"],"example":"Ada Lovelace"},"learner_pseudo":{"type":["string","null"],"example":"ada-l"},"score":{"type":["number","null"],"example":92},"progress":{"type":"number","example":100},"completion_status":{"type":["string","null"],"example":"completed"},"success_status":{"type":"string","example":"passed"},"lesson_status":{"type":["string","null"],"example":"passed"},"session_count":{"type":"integer","example":3},"session_time_seconds":{"type":"integer","example":2840},"last_slide_id":{"type":["string","null"],"example":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012"},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"suspend_data":{"description":"Raw learner suspend data. Present only when includeFullData=true."}},"required":["id","learner_id","learner_email","learner_name","learner_pseudo","score","progress","completion_status","success_status","lesson_status","session_count","session_time_seconds","last_slide_id","created_at","updated_at"]},"LearnerAnalyticsSummary":{"type":"object","properties":{"totalLearners":{"type":"integer","example":42},"completedCount":{"type":"integer","example":31},"successCount":{"type":"integer","example":27},"averageTimeSpentSeconds":{"type":"integer","example":2135}},"required":["totalLearners","completedCount","successCount","averageTimeSpentSeconds"]},"LearnerAnalyticsDeleteRequest":{"type":"object","additionalProperties":false,"properties":{"learner_ids":{"type":"array","minItems":1,"maxItems":1000,"items":{"type":"string"},"example":["learner-1042","learner-1043"]}},"required":["learner_ids"]},"WebhookCoursePublished":{"type":"object","description":"Payload delivered when a course export has completed.","properties":{"course_id":{"type":"string","format":"uuid","description":"ID of the exported course.","example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},"title":{"type":"string","description":"Course title at export time.","example":"Introduction to JavaScript"},"lms_course_id":{"type":"string","nullable":true,"description":"Optional LMS course identifier configured in course settings.","example":"LMS-COURSE-1024"},"download_url":{"type":"string","format":"uri","description":"Signed URL to download the export package.","example":"https://exports.scormstack.com/exports/req_123/course_scorm2004_with_assets.zip?X-Amz-Signature=..."},"expiration_date":{"type":"string","format":"date-time","description":"UTC timestamp when the download URL expires.","example":"2024-01-22T14:45:00.000Z"},"export_type":{"type":"string","description":"Export format.","enum":["scorm","xapi","cmi5","html"],"example":"scorm"},"request_id":{"type":"string","nullable":true,"description":"Internal export request identifier.","example":"req_1234567890abcdef"}},"required":["course_id","title","download_url","expiration_date","export_type"]},"CoursePublishRequest":{"type":"object","description":"Options used to publish or export a course.","properties":{"format":{"type":"string","enum":["scorm","xapi","cmi5","html","public_link"],"default":"scorm","description":"`cmi5` creates a cmi5 course package. `html` creates a downloadable HTML package. `public_link` publishes a hosted learner URL."},"version":{"type":"string","enum":["1.2","2004"],"description":"SCORM version. Ignored for xAPI, cmi5, HTML package, and public links."},"include_assets":{"type":"boolean","description":"Bundle media assets into the SCORM/xAPI/cmi5 package. This makes the export asynchronous.","default":false},"locale":{"type":"string","nullable":true,"description":"Locale code to export, `all` for multi-locale packages, or null for the course default.","example":"fr"},"slide_selection":{"type":"string","enum":["all","select"],"default":"all"},"slide_range":{"type":"string","description":"Slide range when `slide_selection` is `select`, e.g. `1,3,5-8`.","example":"1-5,8"},"track_progress":{"type":"boolean","description":"Enable ScormStack learner progress tracking where supported."},"learner_identification_type":{"type":"string","enum":["none","email","pseudo","name"],"default":"none"},"publish_mode":{"type":"string","enum":["default","new","update"],"description":"Public link mode. `update` requires `target_embed_id`."},"target_embed_id":{"type":"string","nullable":true,"description":"Existing public link embed ID to update."},"share_option":{"type":"string","enum":["link","embed","email","linkedin"],"default":"link"},"password_protection":{"type":"object","properties":{"enabled":{"type":"boolean","default":false},"mode":{"type":"string","enum":["auto","manual"],"default":"auto"},"password":{"type":"string","nullable":true,"description":"Required when mode is `manual`."}}}},"example":{"format":"scorm","version":"2004","include_assets":true,"locale":"fr","slide_selection":"select","slide_range":"1-8","track_progress":true,"learner_identification_type":"email"}},"CoursePublishResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"request_id":{"type":"string","example":"req_1234567890abcdef"},"status":{"type":"string","enum":["pending","processing","completed","failed"],"example":"completed"},"format":{"type":"string","enum":["scorm","xapi","cmi5","html","public_link"]},"download_url":{"type":"string","format":"uri","description":"Signed package URL for completed package exports."},"url":{"type":"string","format":"uri","description":"Hosted learner URL for public link publishes."},"status_url":{"type":"string","description":"Polling URL returned for asynchronous package exports."},"expires_at":{"type":"string","format":"date-time"},"embed_id":{"type":"string"}}}}},"CoursePublishStatus":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"request_id":{"type":"string"},"course_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","processing","completed","failed"]},"format":{"type":"string","enum":["scorm","xapi","cmi5","html","public_link"]},"progress":{"type":"number"},"current_step":{"type":"string"},"download_url":{"type":"string","format":"uri"},"url":{"type":"string","format":"uri"},"error":{"type":"string"}}}}},"WebhookEvent":{"type":"object","description":"Standard webhook event envelope (Stripe-style).","properties":{"id":{"type":"string","description":"Unique event identifier.","example":"evt_1a2b3c4d5e6f7g8h9i0j"},"object":{"type":"string","description":"Object type.","example":"event"},"type":{"type":"string","description":"Event type.","example":"course_published"},"created":{"type":"integer","description":"Unix timestamp when the event was created.","example":1705327800},"livemode":{"type":"boolean","description":"Whether this event was generated in live mode.","example":false},"data":{"type":"object","properties":{"object":{"$ref":"#/components/schemas/WebhookCoursePublished"}},"required":["object"]}},"required":["id","object","type","created","livemode","data"],"example":{"id":"evt_1a2b3c4d5e6f7g8h9i0j","object":"event","type":"course_published","created":1705327800,"livemode":false,"data":{"object":{"course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","title":"Introduction to JavaScript","lms_course_id":"LMS-COURSE-1024","download_url":"https://exports.scormstack.com/exports/req_123/course_scorm2004_with_assets.zip?X-Amz-Signature=...","expiration_date":"2024-01-22T14:45:00.000Z","export_type":"scorm","request_id":"req_1234567890abcdef"}}}},"Course":{"type":"object","description":"Represents a learning course in ScormStack.\n\nA course is the top-level container for learning content. It contains sections (optional organizational units) and slides (the actual content pages).","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the course.","example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},"title":{"type":"string","description":"The display title of the course shown to learners.","example":"Introduction to JavaScript"},"description":{"type":"string","nullable":true,"description":"A brief description of the course content and objectives.","example":"Learn the fundamentals of JavaScript programming, from variables to functions."},"cover_image":{"type":"string","nullable":true,"description":"URL to the course cover image displayed in course listings.","example":"https://assets.scormstack.com/courses/js-intro/cover.jpg"},"user_id":{"type":"string","format":"uuid","description":"ID of the user who owns this course.","example":"usr_e5f6a7b8-c9d0-1234-ef12-345678901234"},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the course was created.","example":"2024-01-15T10:30:00.000Z"},"updated_at":{"type":"string","format":"date-time","description":"Timestamp when the course was last modified.","example":"2024-01-20T14:45:00.000Z"},"settings":{"type":"object","nullable":true,"description":"Course-level settings and configuration.","properties":{"grading_policy":{"type":"object","description":"Advanced grading policy. Omit unless configuring weighted grading; an enabled policy must include GRADER and GRADE_CUTOFFS.","additionalProperties":true,"properties":{"enabled":{"type":"boolean","description":"Whether grading is enabled for this course.","example":false}}},"navigation":{"type":"object","description":"Navigation behavior settings.","properties":{"allow_skip":{"type":"boolean","description":"Whether learners can skip ahead in the course.","example":false}}}},"example":{"navigation":{"allow_skip":false}}}},"example":{"id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","title":"Introduction to JavaScript","description":"Learn the fundamentals of JavaScript programming, from variables to functions.","cover_image":"https://assets.scormstack.com/courses/js-intro/cover.jpg","user_id":"usr_e5f6a7b8-c9d0-1234-ef12-345678901234","created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-20T14:45:00.000Z","settings":null}},"CourseCreate":{"type":"object","description":"Request body for creating a new course.","properties":{"owner_email":{"type":"string","format":"email","maxLength":254,"description":"Optional owner email. Must match one existing member of the token workspace (or its owner), ignoring case and surrounding whitespace. Does not invite or create a user. Use either owner_email or owner_id, not both. If neither is provided, the token user owns the course. The response exposes the owner as user_id.","example":"jordan@example.com"},"owner_id":{"type":"string","format":"uuid","description":"Optional UUID alternative to owner_email. Must identify an existing member of the token workspace (or its owner). Use one selector only. If neither is provided, the token user owns the course. The assigned owner is returned as user_id. Does not change the course workspace.","example":"e5f6a7b8-c9d0-4234-af12-345678901234"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"The display title for the course. Required.","example":"Introduction to JavaScript"},"description":{"type":"string","description":"Optional description of the course.","example":"Learn the fundamentals of JavaScript programming."},"cover_image":{"type":"string","format":"uri","description":"URL to the course cover image.","example":"https://example.com/cover.jpg"},"settings":{"type":"object","description":"Optional course settings.","additionalProperties":true,"properties":{"grading_policy":{"type":"object","additionalProperties":true,"description":"Advanced grading policy. Omit unless configuring weighted grading; an enabled policy must include GRADER and GRADE_CUTOFFS.","properties":{"enabled":{"type":"boolean","example":false}}},"navigation":{"type":"object","description":"Navigation behavior settings.","properties":{"allow_skip":{"type":"boolean","description":"Whether learners can skip ahead in the course.","example":false}}}}},"default_locale":{"oneOf":[{"type":"string","description":"Language code for the course source/default locale.","example":"fr"},{"type":"object","description":"Detailed default locale configuration. `language_code` is required; missing names and direction are inferred from the locale dictionary when possible.","properties":{"language_code":{"type":"string","description":"Language code, e.g. `fr`, `en`, `pt-BR`.","example":"fr"},"language_name":{"type":"string","description":"English display name. Inferred if omitted.","example":"French"},"native_name":{"type":"string","description":"Native display name. Inferred if omitted.","example":"Français"},"text_direction":{"type":"string","enum":["ltr","rtl"],"description":"Text direction. Inferred if omitted.","example":"ltr"},"system_labels":{"type":"object","description":"Optional system label overrides. If omitted, built-in labels for supported languages are used.","additionalProperties":true,"example":{"flow.start_again":"Recommencer"}}},"required":["language_code"],"additionalProperties":true}],"nullable":true,"description":"Creates or updates the matching `course_locales` row and marks it as the course default (`is_default=true`). Use this when the course source content is not English."}},"required":["title"],"example":{"title":"Introduction to JavaScript","description":"Learn the fundamentals of JavaScript programming.","default_locale":"fr"}},"CourseUpdate":{"type":"object","description":"Request body for updating course metadata. To set the course source/default language during creation, use `default_locale` on `POST /courses` or `POST /courses/import`.","properties":{"owner_email":{"type":"string","format":"email","maxLength":254,"description":"Assign ownership by an existing workspace member's email (case-insensitive; surrounding whitespace ignored). Use either owner_email or owner_id, not both. Omit both to keep the current owner. The new owner becomes course admin and the former owner remains an editor; ownership, roles and supplied metadata update atomically. No invitation is sent. The response exposes the owner as user_id.","example":"jordan@example.com"},"owner_id":{"type":"string","format":"uuid","description":"UUID alternative to owner_email for assigning an existing workspace member. Use one selector only; omit both to keep the current owner. The new owner becomes course admin; the previous owner remains an editor. Reassigning the same owner is supported. Ownership, roles and supplied metadata update atomically. The response exposes the owner as user_id.","example":"e5f6a7b8-c9d0-4234-af12-345678901234"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"The display title for the course.","example":"Introduction to JavaScript"},"description":{"type":"string","description":"Optional description of the course.","example":"Learn the fundamentals of JavaScript programming."},"cover_image":{"type":"string","format":"uri","nullable":true,"description":"URL to the course cover image.","example":"https://example.com/cover.jpg"},"settings":{"type":"object","description":"Optional course settings.","additionalProperties":true}},"example":{"title":"Updated JavaScript Course","description":"Updated course description."}},"Section":{"type":"object","description":"Represents a section within a course.\n\nSections are optional organizational units that group related slides together. They appear in the course navigation and help learners understand the course structure.","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the section.","example":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901"},"course_id":{"type":"string","format":"uuid","description":"ID of the course this section belongs to.","example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},"title":{"type":"string","description":"Display title of the section.","example":"Getting Started"},"description":{"type":"string","nullable":true,"description":"Brief description of what this section covers.","example":"Set up your development environment and write your first code."},"icon":{"type":"string","nullable":true,"description":"Icon name from the icon library (e.g., 'rocket', 'book', 'code').","example":"rocket"},"cover_image":{"type":"string","nullable":true,"description":"URL to an optional section cover image.","example":"https://assets.scormstack.com/sections/getting-started.jpg"},"order_index":{"type":"integer","description":"Position of this section in the course (0-indexed).","example":0},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the section was created.","example":"2024-01-15T10:30:00.000Z"},"updated_at":{"type":"string","format":"date-time","description":"Timestamp when the section was last modified.","example":"2024-01-20T14:45:00.000Z"}},"example":{"id":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901","course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","title":"Getting Started","description":"Set up your development environment and write your first code.","icon":"rocket","cover_image":null,"order_index":0,"created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-20T14:45:00.000Z"}},"SectionCreate":{"type":"object","description":"Request body for creating a new section.","properties":{"title":{"type":"string","minLength":1,"maxLength":255,"description":"Display title for the section. Required.","example":"Getting Started"},"description":{"type":"string","description":"Optional description of the section.","example":"Set up your development environment."},"icon":{"type":"string","description":"Optional icon name.","example":"rocket"},"cover_image":{"type":"string","format":"uri","description":"Optional cover image URL."},"order_index":{"type":"integer","description":"Position in the course. If omitted, appends to end.","example":0}},"required":["title"],"example":{"title":"Getting Started","description":"Set up your development environment.","icon":"rocket"}},"Slide":{"type":"object","description":"Represents a slide (content page) within a course.\n\nSlides are the main content containers. Each slide contains one or more blocks that make up the actual learning content.","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the slide.","example":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012"},"course_id":{"type":"string","format":"uuid","description":"ID of the course this slide belongs to.","example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},"section_id":{"type":"string","format":"uuid","nullable":true,"description":"ID of the section this slide belongs to (null if not in a section).","example":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901"},"title":{"type":"string","description":"Display title of the slide shown in navigation.","example":"Variables and Data Types"},"order_index":{"type":"integer","description":"Position of this slide within its section or course (0-indexed).","example":0},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the slide was created.","example":"2024-01-15T10:30:00.000Z"},"updated_at":{"type":"string","format":"date-time","description":"Timestamp when the slide was last modified.","example":"2024-01-20T14:45:00.000Z"}},"example":{"id":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012","course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","section_id":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901","title":"Variables and Data Types","order_index":0,"created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-20T14:45:00.000Z"}},"SlideCreate":{"type":"object","description":"Request body for creating a new slide.","properties":{"title":{"type":"string","minLength":1,"maxLength":255,"description":"Display title for the slide. Required.","example":"Variables and Data Types"},"section_id":{"type":"string","format":"uuid","description":"Optional section ID to place the slide in.","example":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901"},"order_index":{"type":"integer","description":"Position in the section/course. If omitted, appends to end.","example":0}},"required":["title"],"example":{"title":"Variables and Data Types","section_id":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901"}},"Block":{"type":"object","description":"Represents a content block on a slide.\n\nBlocks are the building blocks of course content. Each block has a type (text, image, video, quiz, etc.) and type-specific content.","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the block.","example":"blk_d4e5f6a7-b8c9-0123-def1-234567890123"},"type":{"type":"string","description":"The block type determines what content structure is expected.","example":"text","enum":["slide_intro","separator","text","image","audio","video","embed","pdf","callout","list","table","accordion","tabs","flashcards","timeline","flow","interactive_image","web_simulation","resources","assessment","fill_in_blank","matching","click_on_image","success_meter","categorization","sorting","open_response","navigation_button","reactions","time_requirements"]},"variant":{"type":"string","description":"Block variant for types that have multiple layouts (e.g., 'heading' vs 'paragraph' for text).","example":"heading"},"title":{"type":"string","nullable":true,"description":"Optional title for the block (used in some block types).","example":"Introduction"},"content":{"type":"object","nullable":true,"description":"Block content - structure varies by block type. See block content schemas."},"user_id":{"type":"string","format":"uuid","description":"ID of the user who created this block.","example":"usr_e5f6a7b8-c9d0-1234-ef12-345678901234"},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the block was created.","example":"2024-01-15T10:30:00.000Z"},"updated_at":{"type":"string","format":"date-time","description":"Timestamp when the block was last modified.","example":"2024-01-20T14:45:00.000Z"}},"example":{"id":"blk_d4e5f6a7-b8c9-0123-def1-234567890123","type":"text","variant":"heading","title":null,"content":{"heading":"Welcome to JavaScript","paragraph_1":"<p>In this lesson, you'll learn the fundamentals of JavaScript programming.</p>","options":{"headingSize":"large"}},"user_id":"usr_e5f6a7b8-c9d0-1234-ef12-345678901234","created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-20T14:45:00.000Z"}},"BlockCreate":{"type":"object","description":"Create a new content block.\n\nThe `content` structure depends on the block `type`. See the Block Content Schemas section for detailed structures for each type, or use `GET /blocks/defaults` to get real examples.","properties":{"type":{"type":"string","description":"Block type determines the content structure required.","enum":["slide_intro","separator","text","image","audio","video","embed","pdf","callout","list","table","accordion","tabs","flashcards","timeline","flow","interactive_image","web_simulation","resources","assessment","fill_in_blank","matching","click_on_image","success_meter","categorization","sorting","open_response","navigation_button","reactions","time_requirements"]},"variant":{"type":"string","default":"heading","description":"Block variant for types with multiple layouts. If omitted, the API uses the default variant from blockConfig.ts for the selected type.","example":"heading"},"content":{"type":"object","description":"Block content - see specific content schemas by block type."},"position":{"oneOf":[{"type":"integer","minimum":0},{"type":"string","enum":["end"]}],"description":"Position in the slide (0-indexed integer) or 'end' to append.","example":0}},"required":["type"]},"BlockUpdate":{"type":"object","description":"Update an existing block in place. Optionally change its variant without recreating the block or losing its content and comments. Use `content` to replace the full block content, or `content_patch` to deep-merge partial changes into the existing content. When both are provided, `content` wins.","properties":{"variant":{"type":"string","description":"Optional supported variant of the existing block type; see /blocks/defaults. For text, heading and subheading display only the title; use heading_with_paragraph or subheading_with_paragraph to also display and translate body text. Omit to keep the current variant. Linked library blocks cannot be switched through this endpoint.","example":"heading_with_paragraph"},"content":{"type":"object","description":"Full replacement block content. Structure depends on block type."},"content_patch":{"type":"object","description":"Partial content patch. Objects are merged recursively; arrays and scalar values are replaced. Useful for updating `content.format.paddingTop` or `content.settings.completionMode` without resending cards/questions."}},"examples":{"changeVariant":{"summary":"Display an existing heading and its paragraph without recreating the block","value":{"variant":"heading_with_paragraph"}},"replaceContent":{"summary":"Replace full content","value":{"content":{"heading":"Updated Heading","paragraph_1":"<p>Updated content here.</p>"}}},"patchSettings":{"summary":"Patch format and completion settings","value":{"content_patch":{"format":{"paddingTop":32,"textAlign":"center"},"settings":{"completionMode":"completed"}}}}}},"CourseImportRequest":{"type":"object","description":"Single payload to create a full course tree (course + sections + variants + slides + blocks + checkpoints). Payloads returned by `GET /courses/{courseId}/full` can be edited and posted here.","properties":{"course":{"allOf":[{"$ref":"#/components/schemas/CourseCreate"},{"type":"object","properties":{"theme_id":{"type":"string","format":"uuid","nullable":true},"theme_config":{"type":"object","nullable":true},"status":{"type":"string","example":"draft"}}}],"description":"Top-level course attributes. PAT imports are attached to the workspace associated with the token; request-supplied `workspace_id` is ignored."},"sections":{"type":"array","description":"Optional section list. Use `key` to reference sections from slides and checkpoints.","items":{"type":"object","properties":{"key":{"type":"string","description":"Client-defined stable key (e.g. `intro`) used by slide.section_key.","example":"core"},"source_id":{"type":"string","format":"uuid","description":"Optional original section ID from a full-course export. Ignored except as a reference alias during import."},"title":{"type":"string","example":"Core Concepts"},"description":{"type":"string","example":"Main concepts every learner must understand."},"icon":{"type":"string","example":"book-open"},"cover_image":{"type":"string","nullable":true},"order_index":{"type":"integer","example":0}},"required":["title"]}},"variants":{"type":"array","description":"Adaptive learning variants. Slides reference variants with `variant_keys`; checkpoints unlock variants with `unlock_variant_keys` in rules.","items":{"type":"object","properties":{"key":{"type":"string","example":"variant_fast_track"},"source_id":{"type":"string","format":"uuid","description":"Optional original variant ID from a full-course export."},"label":{"type":"string","example":"Fast Track"},"description":{"type":"string","nullable":true},"is_required":{"type":"boolean","example":false},"details":{"type":"object","example":{"color":"#2563eb"}},"order_index":{"type":"integer","example":0}},"required":["label"]}},"slides":{"type":"array","description":"Slides to create, each with an optional block list.","items":{"type":"object","properties":{"key":{"type":"string","description":"Optional stable slide key from a full-course export.","example":"slide_welcome"},"source_id":{"type":"string","format":"uuid","description":"Optional original slide ID from a full-course export."},"title":{"type":"string","example":"Welcome"},"slide_type":{"type":"string","description":"Slide type. Defaults to `content`.","example":"content"},"section_key":{"type":"string","nullable":true,"description":"Reference to a section `key` in the `sections` array.","example":"core"},"order_index":{"type":"integer","example":0},"content":{"type":"object","description":"Slide-level content/settings, including layoutGroups. Full-course exports use block keys in layoutGroups.blockIds; import remaps them to new block IDs."},"variant_keys":{"type":"array","nullable":true,"description":"Variant keys that gate this slide. Empty or omitted means the slide is core content.","items":{"type":"string"},"example":["variant_fast_track"]},"blocks":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Optional stable block key used by slide layout groups and checkpoint conditions.","example":"block_intro_text"},"source_id":{"type":"string","format":"uuid","nullable":true,"description":"Optional original block ID from a full-course export."},"title":{"type":"string","nullable":true,"example":"Intro text"},"type":{"type":"string","enum":["slide_intro","separator","text","image","audio","video","embed","pdf","callout","list","table","accordion","tabs","flashcards","timeline","flow","interactive_image","web_simulation","resources","assessment","fill_in_blank","matching","click_on_image","success_meter","categorization","sorting","open_response","navigation_button","reactions","time_requirements"],"example":"text"},"variant":{"type":"string","example":"heading"},"content":{"type":"object"},"position":{"oneOf":[{"type":"integer","minimum":0},{"type":"string","enum":["end"]}],"example":0}},"required":["type"]}}},"required":["title"]}},"checkpoints":{"type":"array","description":"Adaptive learning checkpoints. Conditions should reference blocks with `block_key`; rules should reference variants with `unlock_variant_keys`.","items":{"type":"object","properties":{"key":{"type":"string","example":"checkpoint_after_intro"},"source_id":{"type":"string","format":"uuid","description":"Optional original checkpoint ID from a full-course export."},"title":{"type":"string","example":"Readiness Check"},"section_key":{"type":"string","nullable":true,"example":"core"},"order_index":{"type":"integer","example":2},"rules":{"type":"array","items":{"type":"object"},"example":[{"id":"rule_1","conditions":[{"block_key":"block_quiz","field":"percentage","operator":">=","value":80}],"unlock_variant_keys":["variant_fast_track"]}]}}}}},"required":["course"],"example":{"course":{"title":"Onboarding Essentials","description":"Get learners operational in less than 10 minutes.","default_locale":"fr"},"sections":[{"key":"core","title":"Core Concepts","order_index":0}],"variants":[{"key":"variant_fast_track","label":"Fast Track","is_required":false,"order_index":0}],"slides":[{"key":"slide_welcome","title":"Welcome","slide_type":"content","section_key":"core","order_index":0,"variant_keys":null,"blocks":[{"key":"block_intro","type":"slide_intro","variant":"default","content":{"title":"Welcome to Onboarding Essentials","duration":180,"objectives":["Understand the key workflow","Complete a short validation check"]},"position":0},{"key":"block_quiz","type":"assessment","variant":"assessment_stack","content":{"title":"Readiness Check","description":"Validate the key workflow before continuing."},"position":1}]}],"checkpoints":[{"key":"checkpoint_readiness","title":"Readiness Check","section_key":"core","order_index":1,"rules":[{"id":"rule_1","conditions":[{"block_key":"block_quiz","field":"percentage","operator":">=","value":80}],"unlock_variant_keys":["variant_fast_track"]}]}]}},"CourseImportResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"course_id":{"type":"string","format":"uuid"},"sections_created":{"type":"integer","example":1},"variants_created":{"type":"integer","example":1},"slides_created":{"type":"integer","example":1},"blocks_created":{"type":"integer","example":2},"checkpoints_created":{"type":"integer","example":1}},"required":["course_id","sections_created","variants_created","slides_created","blocks_created","checkpoints_created"]}},"required":["success","data"]},"CourseFullExportResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/CourseImportRequest"}},"required":["success","data"]},"TextBlockContent":{"type":"object","description":"Text block content structure","properties":{"heading":{"type":"string"},"paragraph_1":{"type":"string"},"paragraph_2":{"type":"string"},"paragraph_3":{"type":"string"},"paragraph_4":{"type":"string"},"options":{"$ref":"#/components/schemas/TextBlockOptions"}},"additionalProperties":false},"ImageBlockContent":{"type":"object","description":"Image block content structure","properties":{"text":{"type":"string"},"images":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ImageContent"}},"options":{"$ref":"#/components/schemas/ImageBlockOptions"},"format":{"type":"object","properties":{"overlayColor":{"type":"string"},"overlayOpacity":{"type":"number"}},"additionalProperties":false}},"additionalProperties":false},"VideoBlockContent":{"type":"object","properties":{"url":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"caption":{"type":"string"},"poster":{"type":"string"},"subtitles":{"type":"array","items":{"type":"object","properties":{"src":{"type":"string"},"label":{"type":"string"},"language":{"type":"string"}},"required":["src","label","language"],"additionalProperties":false}},"aspectRatio":{"type":"number"},"quality":{"type":"string"},"startTime":{"type":"number"},"endTime":{"type":"number"},"autoplay":{"type":"boolean"},"controls":{"type":"boolean"},"loop":{"type":"boolean"},"muted":{"type":"boolean"},"provider":{"type":"string","enum":["youtube","vimeo","upload"]},"color":{"type":"string"},"showTitle":{"type":"boolean"},"showByline":{"type":"boolean"},"showPortrait":{"type":"boolean"},"showPlaybar":{"type":"boolean"},"showVolume":{"type":"boolean"},"showSpeed":{"type":"boolean"},"allowFullscreen":{"type":"boolean"},"allowPip":{"type":"boolean"},"enableKeyboard":{"type":"boolean"},"showCaptionsByDefault":{"type":"boolean"},"preload":{"type":"string","enum":["none","metadata","auto"]},"settings":{"$ref":"#/components/schemas/VideoBlockSettings"}},"additionalProperties":false},"AudioBlockContent":{"type":"object","properties":{"src":{"type":"string"},"title":{"type":"string"},"caption":{"type":"string"},"transcript":{"type":"string"},"autoplay":{"type":"boolean"},"showTitle":{"type":"boolean"},"showProgress":{"type":"boolean"},"showSpeed":{"type":"boolean"},"showVisualization":{"type":"boolean"},"loop":{"type":"boolean"},"settings":{"$ref":"#/components/schemas/AudioBlockSettings"}},"additionalProperties":false},"FlowBlockContent":{"type":"object","description":"Flow block content structure","properties":{"intro":{"$ref":"#/components/schemas/FlowIntroOutro"},"outro":{"$ref":"#/components/schemas/FlowIntroOutro"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/FlowStep"}},"format":{"type":"object","properties":{"width":{"type":"number","description":"Width percentage (0-100)"},"contentMaxWidth":{"type":"number","description":"Content max width (1-5 scale)"},"paddingTop":{"type":"number","description":"Top padding in pixels"},"paddingBottom":{"type":"number","description":"Bottom padding in pixels"},"paddingLeft":{"type":"number","description":"Left padding in pixels"},"paddingRight":{"type":"number","description":"Right padding in pixels"},"paddingLinked":{"type":"boolean","description":"Legacy flag for older top/bottom linked padding controls"},"marginTop":{"type":"number","description":"Internal top margin around the styled block surface in pixels"},"marginBottom":{"type":"number","description":"Internal bottom margin around the styled block surface in pixels"},"marginLeft":{"type":"number","description":"Internal left margin around the styled block surface in pixels"},"marginRight":{"type":"number","description":"Internal right margin around the styled block surface in pixels"},"borderRadius":{"type":["number","string"],"description":"Border radius for the styled block surface"},"textAlign":{"$ref":"#/components/schemas/TextAlign","description":"Text alignment using logical properties"},"backgroundType":{"$ref":"#/components/schemas/BackgroundType","description":"Background type"},"backgroundColor":{"type":"string","description":"Background color (hex or CSS var)"},"accentColor":{"type":"string","description":"Accent color (hex or CSS var)"},"gap":{"type":"number","description":"Gap between elements in pixels"},"height":{"type":"number","description":"Optional height in pixels"},"backgroundImageSrc":{"type":"string","description":"Background image URL (when backgroundType is IMAGE)"},"backgroundSize":{"type":"string","description":"Background image size"},"backgroundPosition":{"type":"string","description":"Background image position"},"backgroundRepeat":{"type":"string","description":"Background image repeat"}},"additionalProperties":false},"settings":{"$ref":"#/components/schemas/FlowBlockSettings"}},"additionalProperties":false},"TimelineBlockContent":{"type":"object","description":"Timeline block content structure","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/TimelineEvent"}},"format":{"type":"object","properties":{"width":{"type":"number","description":"Width percentage (0-100)"},"contentMaxWidth":{"type":"number","description":"Content max width (1-5 scale)"},"paddingTop":{"type":"number","description":"Top padding in pixels"},"paddingBottom":{"type":"number","description":"Bottom padding in pixels"},"paddingLeft":{"type":"number","description":"Left padding in pixels"},"paddingRight":{"type":"number","description":"Right padding in pixels"},"paddingLinked":{"type":"boolean","description":"Legacy flag for older top/bottom linked padding controls"},"marginTop":{"type":"number","description":"Internal top margin around the styled block surface in pixels"},"marginBottom":{"type":"number","description":"Internal bottom margin around the styled block surface in pixels"},"marginLeft":{"type":"number","description":"Internal left margin around the styled block surface in pixels"},"marginRight":{"type":"number","description":"Internal right margin around the styled block surface in pixels"},"borderRadius":{"type":["number","string"],"description":"Border radius for the styled block surface"},"textAlign":{"$ref":"#/components/schemas/TextAlign","description":"Text alignment using logical properties"},"backgroundType":{"$ref":"#/components/schemas/BackgroundType","description":"Background type"},"backgroundColor":{"type":"string","description":"Background color (hex or CSS var)"},"accentColor":{"type":"string","description":"Accent color (hex or CSS var)"},"gap":{"type":"number","description":"Gap between elements in pixels"},"height":{"type":"number","description":"Optional height in pixels"},"backgroundImageSrc":{"type":"string","description":"Background image URL (when backgroundType is IMAGE)"},"backgroundSize":{"type":"string","description":"Background image size"},"backgroundPosition":{"type":"string","description":"Background image position"},"backgroundRepeat":{"type":"string","description":"Background image repeat"}},"additionalProperties":false},"settings":{"$ref":"#/components/schemas/TimelineBlockSettings"}},"additionalProperties":false},"FlashcardsBlockContent":{"type":"object","description":"Flashcards block content structure","properties":{"cards":{"type":"array","items":{"$ref":"#/components/schemas/Flashcard"}},"settings":{"$ref":"#/components/schemas/FlashcardsBlockSettings"}},"additionalProperties":false},"AccordionBlockContent":{"type":"object","description":"Accordion block content structure","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AccordionTabItem"}},"options":{"$ref":"#/components/schemas/AccordionTabsOptions"},"settings":{"type":"object","properties":{"completionMode":{"type":"string","enum":["viewed","tried","completed"]}},"additionalProperties":false}},"additionalProperties":false},"TabsBlockContent":{"type":"object","description":"Tabs block content structure","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AccordionTabItem"}},"options":{"$ref":"#/components/schemas/AccordionTabsOptions"}},"additionalProperties":false},"AssessmentBlockContent":{"type":"object","description":"Assessment block content structure","properties":{"name":{"type":"string"},"description":{"type":"string"},"questions":{"type":"array","items":{"$ref":"#/components/schemas/QuizAssessmentQuestion"}},"problemSettings":{"$ref":"#/components/schemas/QuizAssessmentProblemSettings"},"settings":{"$ref":"#/components/schemas/AssessmentBlockSettings"},"grade_required":{"type":"number"},"weight":{"type":["number","null"]},"display_intro_page":{"type":"boolean"},"display_summary_page":{"type":"boolean"},"show_navigation":{"type":"boolean"},"show_question_number":{"type":"boolean"},"display_mode":{"type":"string","enum":["stacks","inline"]},"format":{"$ref":"#/components/schemas/BlockFormat"}},"additionalProperties":false},"FillInBlankBlockContent":{"type":"object","description":"Fill-in-blank block content structure","properties":{"title":{"type":"string"},"instructions":{"type":"string"},"passage":{"type":"string"},"blanks":{"type":"array","items":{"$ref":"#/components/schemas/BlankDefinition"}},"solution":{"type":"string"},"grade_required":{"type":"number"},"settings":{"$ref":"#/components/schemas/FillInBlankSettings"},"grading":{"$ref":"#/components/schemas/GradingConfig"}},"additionalProperties":false},"MatchingBlockContent":{"type":"object","description":"Matching block content structure","properties":{"title":{"type":"string"},"instructions":{"type":"string"},"leftColumn":{"type":"array","items":{"$ref":"#/components/schemas/MatchingItem"}},"rightColumn":{"type":"array","items":{"$ref":"#/components/schemas/MatchingItem"}},"correctMatches":{"type":"array","items":{"$ref":"#/components/schemas/MatchingPair"}},"idMode":{"type":"string","const":"stable"},"nextLeftId":{"type":"number"},"nextRightId":{"type":"number"},"leftColumnTitle":{"type":"string"},"rightColumnTitle":{"type":"string"},"solution":{"type":"string"},"grade_required":{"type":"number"},"settings":{"$ref":"#/components/schemas/MatchingBlockSettings"},"grading":{"$ref":"#/components/schemas/GradingConfig"}},"additionalProperties":false},"ClickOnImageBlockContent":{"type":"object","description":"Click-on-image block content structure","properties":{"title":{"type":"string"},"instructions":{"type":"string"},"imageUrl":{"type":"string"},"imageAlt":{"type":"string"},"hotspots":{"type":"array","items":{"$ref":"#/components/schemas/ClickOnImageHotspot"}},"solution":{"type":"string"},"grade_required":{"type":"number"},"settings":{"$ref":"#/components/schemas/ClickOnImageSettings"},"grading":{"$ref":"#/components/schemas/GradingConfig"}},"additionalProperties":false},"InteractiveImageBlockContent":{"type":"object","description":"Interactive image block content structure","properties":{"imageUrl":{"type":"string"},"imageAlt":{"type":"string"},"hotspots":{"type":"array","items":{"$ref":"#/components/schemas/InteractiveImageHotspot"}},"settings":{"type":"object","properties":{"showHotspotLabels":{"type":"boolean"},"hotSpotStyle":{"type":"string"},"hotspotStyle":{"type":"string"},"hotspotSize":{"type":["string","number"]},"hotspotColor":{"type":"string"},"showHotspotNumbers":{"type":"boolean"},"showHotspotNav":{"type":"boolean"},"clickBehavior":{"type":"string","enum":["modal","sidebar","tooltip"]},"completionMode":{"type":"string","enum":["viewed","tried","completed"]},"hotspotDisplayMode":{"type":"string","enum":["annotated","discovery"]}},"additionalProperties":false}},"additionalProperties":false},"WebSimulationBlockContent":{"type":"object","description":"Web simulation block content structure","properties":{"startText":{"type":"string"},"finishText":{"type":"string"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/WebSimulationStep"}},"settings":{"$ref":"#/components/schemas/WebSimulationSettings"}},"additionalProperties":false},"SuccessMeterBlockContent":{"type":"object","description":"Success meter block content structure","properties":{"assessment_title":{"type":"string"},"introduction":{"type":"string"},"core_questions":{"type":"array","items":{"$ref":"#/components/schemas/AssessmentQuestion"}},"extra_questions":{"type":"array","items":{"$ref":"#/components/schemas/AssessmentQuestion"}},"show_question_number":{"type":"boolean"},"results":{"$ref":"#/components/schemas/SuccessMeterResults"},"grade_required":{"type":"number"},"settings":{"$ref":"#/components/schemas/SuccessMeterSettings"},"grading":{"$ref":"#/components/schemas/GradingConfig"},"initial_points":{"type":"number"}},"additionalProperties":false},"CategorizationBlockContent":{"type":"object","description":"Categorization block content structure","properties":{"title":{"type":"string"},"instructions":{"type":"string"},"categories":{"type":"array","items":{"$ref":"#/components/schemas/CategorizationCategory"}},"items":{"type":"array","items":{"$ref":"#/components/schemas/CategorizationItem"}},"solution":{"type":"string"},"grade_required":{"type":"number"},"settings":{"$ref":"#/components/schemas/CategorizationSettings"},"grading":{"$ref":"#/components/schemas/GradingConfig"}},"additionalProperties":false},"SortingBlockContent":{"type":"object","description":"Sorting block content structure","properties":{"title":{"type":"string"},"instructions":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/SortingItem"}},"correctOrder":{"type":"array","items":{"type":"string"}},"solution":{"type":"string"},"grade_required":{"type":"number"},"settings":{"$ref":"#/components/schemas/SortingSettings"},"grading":{"$ref":"#/components/schemas/GradingConfig"}},"additionalProperties":false},"OpenResponseBlockContent":{"type":"object","description":"Open response block content structure","properties":{"title":{"type":"string"},"prompt":{"type":"string"},"instructions":{"type":"string"},"placeholder":{"type":"string"},"minLength":{"type":"number"},"maxLength":{"type":"number"},"modelAnswer":{"type":"string"},"rubric":{"type":"string"},"grade_required":{"type":"number"},"settings":{"type":"object","properties":{"showInstructions":{"type":"boolean"},"showCharacterCount":{"type":"boolean"},"maxCharacters":{"type":"number"},"showWordCount":{"type":"boolean"},"allowRichText":{"type":"boolean"},"showModelAnswer":{"type":"boolean"},"completionMode":{"$ref":"#/components/schemas/AssessmentCompletionModeSetting"}},"additionalProperties":false},"grading":{"$ref":"#/components/schemas/GradingConfig"}},"additionalProperties":false},"CalloutBlockContent":{"type":"object","description":"Callout block content structure","properties":{"title":{"type":"string"},"content":{"type":"string"},"icon":{"type":"string"},"type":{"type":"string","enum":["info","warning","success","error","tip","note","important","exercise"]},"iconPosition":{"type":"string","enum":["top","left","right","bottom"]},"color":{"type":"string"}},"additionalProperties":false},"ListBlockContent":{"type":"object","description":"List block content structure","properties":{"heading":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/ListItem"}},"options":{"$ref":"#/components/schemas/ListBlockOptions"}},"additionalProperties":false},"SeparatorBlockContent":{"type":"object","description":"Separator block content structure","properties":{"text":{"type":"string"},"shape":{"type":"string"},"extend_background":{"type":"boolean"},"flip_vertical":{"type":"boolean"},"gradient":{"type":"object","properties":{"direction":{"type":"string"}},"additionalProperties":false},"options":{"type":"object","properties":{"thickness":{"type":"number"},"opacity":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"},"top_color":{"type":"string"},"gradientEndColor":{"type":"string"},"gradientDirection":{"type":"string"},"gradientStartColor":{"type":"string"},"custom_shape_data":{"$ref":"#/components/schemas/SeparatorCustomShapeData"},"custom_shape_svg_path":{"type":"string"},"custom_shape_svg_viewbox":{"type":"string"},"custom_shape_svg_markup":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false},"ResourcesBlockContent":{"type":"object","description":"Resources block content structure","properties":{"title":{"type":"string"},"description":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/ResourceItem"}},"options":{"type":"object","properties":{"layout":{"type":"string","enum":["list","grid"]},"showIcons":{"type":"boolean"},"showDescriptions":{"type":"boolean"}},"additionalProperties":false}},"additionalProperties":false},"EmbedBlockContent":{"type":"object","description":"Embed block content structure","properties":{"url":{"type":"string"},"title":{"type":"string"},"height":{"type":["number","string"]},"completionBehavior":{"type":"string","enum":["auto","manual"]}},"additionalProperties":false},"PdfBlockContent":{"type":"object","description":"PDF block content structure","properties":{"url":{"type":"string"},"title":{"type":"string"},"height":{"type":"number"},"showDownload":{"type":"boolean"},"showPrint":{"type":"boolean"}},"additionalProperties":false},"SlideIntroBlockContent":{"type":"object","description":"Slide intro block content structure","properties":{"title":{"type":"string"},"duration":{"type":"number"},"objectives":{"type":"array","items":{"type":"string"}},"icon":{"type":"string"},"format":{"type":"object","additionalProperties":false,"properties":{"showLesson":{"type":"boolean"},"showObjectives":{"type":"boolean"},"showTableOfContent":{"type":"boolean"},"width":{"type":"number","description":"Width percentage (0-100)"},"contentMaxWidth":{"type":"number","description":"Content max width (1-5 scale)"},"paddingTop":{"type":"number","description":"Top padding in pixels"},"paddingBottom":{"type":"number","description":"Bottom padding in pixels"},"paddingLeft":{"type":"number","description":"Left padding in pixels"},"paddingRight":{"type":"number","description":"Right padding in pixels"},"paddingLinked":{"type":"boolean","description":"Legacy flag for older top/bottom linked padding controls"},"marginTop":{"type":"number","description":"Internal top margin around the styled block surface in pixels"},"marginBottom":{"type":"number","description":"Internal bottom margin around the styled block surface in pixels"},"marginLeft":{"type":"number","description":"Internal left margin around the styled block surface in pixels"},"marginRight":{"type":"number","description":"Internal right margin around the styled block surface in pixels"},"borderRadius":{"type":["number","string"],"description":"Border radius for the styled block surface"},"textAlign":{"$ref":"#/components/schemas/TextAlign","description":"Text alignment using logical properties"},"backgroundType":{"$ref":"#/components/schemas/BackgroundType","description":"Background type"},"backgroundColor":{"type":"string","description":"Background color (hex or CSS var)"},"accentColor":{"type":"string","description":"Accent color (hex or CSS var)"},"gap":{"type":"number","description":"Gap between elements in pixels"},"height":{"type":"number","description":"Optional height in pixels"},"backgroundImageSrc":{"type":"string","description":"Background image URL (when backgroundType is IMAGE)"},"backgroundSize":{"type":"string","description":"Background image size"},"backgroundPosition":{"type":"string","description":"Background image position"},"backgroundRepeat":{"type":"string","description":"Background image repeat"}}}},"additionalProperties":false},"NavigationButtonBlockContent":{"type":"object","description":"Navigation button block content structure","properties":{"label":{"type":"string"},"actionType":{"$ref":"#/components/schemas/NavigationActionType"},"targetSlideId":{"type":"string"},"externalUrl":{"type":"string"},"openInNewTab":{"type":"boolean"},"style":{"type":"string","enum":["primary","secondary","outline"]}},"additionalProperties":false},"ReactionsBlockContent":{"type":"object","properties":{"title":{"type":"string"},"settings":{"$ref":"#/components/schemas/ReactionsBlockSettings"}},"additionalProperties":false},"MediaContent":{"type":"object","description":"Media content structure (for Flow and Flashcards)","properties":{"url":{"type":"string"},"type":{"type":"string","enum":["image","video","audio"]},"width":{"type":"number"},"height":{"type":"number"},"caption":{"type":"string"},"position":{"type":"string","enum":["left","center","right","full_card"]},"verticalAlign":{"type":"string","enum":["top","middle","bottom"]}},"additionalProperties":false},"ImageContent":{"type":"object","description":"Image content structure","properties":{"src":{"type":"string"},"alt":{"type":"string"},"caption":{"type":"string"},"width":{"type":["number","string"]},"height":{"type":["number","string"]},"position":{"type":"string","enum":["left","center","right","full_card"]},"verticalAlign":{"type":"string","enum":["top","middle","bottom"]}},"required":["src"],"additionalProperties":false},"Flashcard":{"type":"object","description":"Flashcard","properties":{"id":{"type":"string"},"front":{"type":"object","properties":{"media":{"anyOf":[{"$ref":"#/components/schemas/MediaContent"},{"type":"null"}]},"content":{"type":"string"},"tipColor":{"type":"string","enum":["dark","light"]}},"required":["content"],"additionalProperties":false},"back":{"type":"object","properties":{"media":{"anyOf":[{"$ref":"#/components/schemas/MediaContent"},{"type":"null"}]},"content":{"type":"string"},"tipColor":{"type":"string","enum":["dark","light"]}},"required":["content"],"additionalProperties":false}},"required":["id","front","back"],"additionalProperties":false},"FlowStep":{"type":"object","description":"Flow step","properties":{"media":{"anyOf":[{"$ref":"#/components/schemas/MediaContent"},{"type":"null"}]},"title":{"type":"string"},"content":{"type":"string"}},"required":["content"],"additionalProperties":false},"FlowIntroOutro":{"type":"object","description":"Flow intro/outro","properties":{"media":{"anyOf":[{"$ref":"#/components/schemas/MediaContent"},{"type":"null"}]},"content":{"type":"string"},"startButtonText":{"type":"string"},"completionMessage":{"type":"string"}},"required":["content"],"additionalProperties":false},"TimelineEvent":{"type":"object","description":"Timeline event","properties":{"id":{"type":"string"},"date":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"icon":{"type":"string"},"image":{"anyOf":[{"$ref":"#/components/schemas/ImageContent"},{"type":"null"}]},"content":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"AccordionTabItem":{"type":"object","description":"Accordion/Tabs item","properties":{"id":{"type":"string"},"title":{"type":"string"},"content":{"type":"string"},"icon":{"type":"string"}},"required":["title","content"],"additionalProperties":false},"ResourceItem":{"type":"object","description":"Resource item","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["link","file"]},"url":{"type":"string"},"fileUrl":{"type":"string"},"fileName":{"type":"string"},"icon":{"type":"string"}},"required":["id","title","description","type","icon"],"additionalProperties":false},"BlankDefinition":{"type":"object","description":"Fill-in-blank definition","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["text","list"]},"correctAnswers":{"type":"array","items":{"type":"string"}},"options":{"type":"array","items":{"type":"string"}},"caseSensitive":{"type":"boolean"}},"required":["id","type","correctAnswers"],"additionalProperties":false},"MatchingItem":{"type":"object","description":"Matching item","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["text","image"]},"content":{"type":"string"},"alt":{"type":"string"}},"required":["id","type","content"],"additionalProperties":false},"MatchingPair":{"type":"object","description":"Matching pair","properties":{"leftId":{"type":"string"},"rightId":{"type":"string"},"explanation":{"type":"string"}},"required":["leftId","rightId","explanation"],"additionalProperties":false},"ClickOnImageHotspot":{"type":"object","description":"Click-on-image hotspot","properties":{"id":{"type":"string"},"name":{"type":"string"},"topPercent":{"type":"number"},"leftPercent":{"type":"number"},"rightPercent":{"type":"number"},"bottomPercent":{"type":"number"},"feedback":{"type":"string"},"isCorrect":{"type":"boolean"}},"required":["id","name","topPercent","leftPercent","rightPercent","bottomPercent","feedback","isCorrect"],"additionalProperties":false},"InteractiveImageHotspot":{"type":"object","description":"Interactive image hotspot","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["marker","area"]},"icon":{"type":"string"},"tooltip":{"type":"string"},"content":{"$ref":"#/components/schemas/HotspotContent"},"position":{"$ref":"#/components/schemas/HotspotPosition"},"leftPercent":{"type":"number"},"topPercent":{"type":"number"},"rightPercent":{"type":"number"},"bottomPercent":{"type":"number"}},"required":["id","content","position"],"additionalProperties":false},"AssessmentQuestion":{"type":"object","description":"Assessment question","properties":{"id":{"type":"string"},"prompt":{"type":"string"},"options":{"type":"array","items":{"$ref":"#/components/schemas/AssessmentOption"}}},"required":["id","prompt","options"],"additionalProperties":false},"AssessmentOption":{"type":"object","description":"Assessment question option","properties":{"label":{"type":"string"},"points":{"type":"number"},"rationale":{"type":"string"}},"required":["label","points","rationale"],"additionalProperties":false},"SortingItem":{"type":"object","description":"Sorting item","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["text","image"]},"textContent":{"type":"string"},"imageContent":{"type":"string"},"alt":{"type":"string"}},"required":["id","type"],"additionalProperties":false},"QuizAssessmentChoice":{"type":"object","description":"Quiz assessment choice (for Assessment block)","properties":{"id":{"type":"string"},"text":{"type":"string"},"correct":{"type":"boolean"},"hint":{"type":"string"}},"required":["id","text","correct"],"additionalProperties":false},"QuizAssessmentQuestion":{"description":"Quiz assessment question (for Assessment block)"},"QuizAssessmentProblemSettings":{"type":"object","description":"Quiz assessment problem settings (for Assessment block)","properties":{"maxAttempts":{"type":["number","null"]},"showAnswer":{"type":"string"},"weight":{"type":["number","null"]}},"additionalProperties":false},"GradingConfig":{"type":"object","description":"Grading configuration for assessment blocks","properties":{"partialCredit":{"type":"boolean"},"weight":{"type":"number"},"maxAttempts":{"type":["number","null"]},"caseSensitive":{"type":"boolean"},"max_attempts":{"type":"number"},"showAnswer":{"type":"string"}},"additionalProperties":false},"BlockFormat":{"type":"object","description":"Default block format configuration","properties":{"width":{"type":"number","description":"Width percentage (0-100)"},"contentMaxWidth":{"type":"number","description":"Content max width (1-5 scale)"},"paddingTop":{"type":"number","description":"Top padding in pixels"},"paddingBottom":{"type":"number","description":"Bottom padding in pixels"},"paddingLeft":{"type":"number","description":"Left padding in pixels"},"paddingRight":{"type":"number","description":"Right padding in pixels"},"paddingLinked":{"type":"boolean","description":"Legacy flag for older top/bottom linked padding controls"},"marginTop":{"type":"number","description":"Internal top margin around the styled block surface in pixels"},"marginBottom":{"type":"number","description":"Internal bottom margin around the styled block surface in pixels"},"marginLeft":{"type":"number","description":"Internal left margin around the styled block surface in pixels"},"marginRight":{"type":"number","description":"Internal right margin around the styled block surface in pixels"},"borderRadius":{"type":["number","string"],"description":"Border radius for the styled block surface"},"textAlign":{"$ref":"#/components/schemas/TextAlign","description":"Text alignment using logical properties"},"backgroundType":{"$ref":"#/components/schemas/BackgroundType","description":"Background type"},"backgroundColor":{"type":"string","description":"Background color (hex or CSS var)"},"accentColor":{"type":"string","description":"Accent color (hex or CSS var)"},"gap":{"type":"number","description":"Gap between elements in pixels"},"height":{"type":"number","description":"Optional height in pixels"},"backgroundImageSrc":{"type":"string","description":"Background image URL (when backgroundType is IMAGE)"},"backgroundSize":{"type":"string","description":"Background image size"},"backgroundPosition":{"type":"string","description":"Background image position"},"backgroundRepeat":{"type":"string","description":"Background image repeat"}},"required":["width","contentMaxWidth","paddingTop","paddingBottom","paddingLinked","textAlign","backgroundType","backgroundColor","accentColor","gap"],"additionalProperties":false},"TextBlockOptions":{"type":"object","description":"Text block content options","properties":{"headingSize":{"type":"string","enum":["small","medium","large"]},"headingFormat":{"type":"string","enum":["simple","numbered","icon"]},"columnCount":{"type":"number","enum":[2,3,4]}},"additionalProperties":false},"ImageBlockOptions":{"type":"object","description":"Image block options","properties":{"box_shadow":{"type":"boolean"},"grid_columns":{"type":"number"},"show_caption":{"type":"boolean"},"carousel_loop":{"type":"boolean"},"carousel_autoplay":{"type":"boolean"},"carousel_autoplay_delay":{"type":"number"},"carousel_show_navigation":{"type":"boolean"},"carousel_show_pagination":{"type":"boolean"},"carousel_effect":{"type":"string"}},"additionalProperties":false},"FlowBlockSettings":{"type":"object","description":"Flow block settings","properties":{"allowSkip":{"type":"boolean"},"autoPlayAudio":{"type":"boolean"},"showNavigation":{"type":"boolean"},"showNextButton":{"type":"boolean"},"navigationStyle":{"type":"string"},"showProgressBar":{"type":"boolean"},"showStepNumbers":{"type":"boolean"},"transitionEffect":{"type":"string"},"showPreviousButton":{"type":"boolean"},"defaultNextButtonText":{"type":"string"},"defaultPreviousButtonText":{"type":"string"},"showIntro":{"type":"boolean"},"showOutro":{"type":"boolean"},"completionMode":{"type":"string","enum":["viewed","tried","completed"]}},"additionalProperties":false},"TimelineBlockSettings":{"type":"object","description":"Timeline block settings","properties":{"layout":{"type":"string","enum":["vertical","compact","horizontal_cards"]},"displayMode":{"type":"string","enum":["expandable","static"]},"completionMode":{"type":"string","enum":["viewed","tried","completed"]},"showConnectors":{"type":"boolean"},"connectorColor":{"type":"string"}},"additionalProperties":false},"FlashcardsBlockSettings":{"type":"object","description":"Flashcards block settings","properties":{"height":{"type":["string","number"]},"gridColumns":{"type":"number"},"completionMode":{"type":"string","enum":["viewed","tried","completed"]},"allowShuffle":{"type":"boolean"},"showProgress":{"type":"boolean"},"flipDirection":{"type":"string","enum":["horizontal","vertical"]},"autoFlip":{"type":"boolean"},"autoFlipDelay":{"type":"number"}},"additionalProperties":false},"AccordionTabsOptions":{"type":"object","description":"Accordion/Tabs block options","properties":{"type":{"type":"string","enum":["single","multiple"]},"defaultTab":{"type":"number"},"tabsDisplay":{"type":"string","enum":["compact","full"]},"tabHeight":{"type":["number","null"]},"completionMode":{"type":"string","enum":["viewed","tried","completed"]}},"additionalProperties":false},"FillInBlankSettings":{"type":"object","description":"Fill-in-blank block settings","properties":{"showProgress":{"type":"boolean"},"showInstructions":{"type":"boolean"},"completionMode":{"$ref":"#/components/schemas/AssessmentCompletionModeSetting"}},"additionalProperties":false},"MatchingBlockSettings":{"type":"object","description":"Matching block settings","properties":{"showProgress":{"type":"boolean"},"showInstructions":{"type":"boolean"},"shuffleLeft":{"type":"boolean"},"shuffleRight":{"type":"boolean"},"allowMultipleConnections":{"type":"boolean"},"columnsRatio":{"type":"string"},"completionMode":{"$ref":"#/components/schemas/AssessmentCompletionModeSetting"}},"additionalProperties":false},"ClickOnImageSettings":{"type":"object","description":"Click-on-image block settings","properties":{"showInstructions":{"type":"boolean"},"maxUserAreas":{"type":"number"},"highlightCorrectOnComplete":{"type":"boolean"},"completionMode":{"$ref":"#/components/schemas/AssessmentCompletionModeSetting"}},"additionalProperties":false},"WebSimulationStep":{"type":"object","description":"Web simulation step","properties":{"id":{"type":"string"},"title":{"type":"string"},"backgroundImage":{"type":"object","properties":{"src":{"type":"string"},"alt":{"type":"string"}},"required":["src"],"additionalProperties":false},"areas":{"type":"array","items":{"$ref":"#/components/schemas/WebSimulationArea"}},"isEndStep":{"type":"boolean"}},"required":["id"],"additionalProperties":false},"WebSimulationArea":{"type":"object","description":"Web simulation step area","properties":{"id":{"type":"string"},"label":{"type":"string"},"topPercent":{"type":"number"},"leftPercent":{"type":"number"},"rightPercent":{"type":"number"},"bottomPercent":{"type":"number"},"targetStepId":{"type":"string"}},"required":["id","topPercent","leftPercent","rightPercent","bottomPercent"],"additionalProperties":false},"WebSimulationSettings":{"type":"object","description":"Web simulation block settings","properties":{"showClickableAreas":{"type":"boolean"},"showProgress":{"type":"boolean"},"showBrowser":{"type":"boolean"},"deviceType":{"type":"string","enum":["desktop","tablet","mobile"]},"areaColor":{"type":"string"},"showIntro":{"type":"boolean"},"showOutro":{"type":"boolean"},"navigationStyle":{"type":"string","enum":["hide","dots","numbers"]},"completionMode":{"type":"string","enum":["viewed","tried","completed"]}},"additionalProperties":false},"SuccessMeterResults":{"type":"object","description":"Success meter results configuration","properties":{"high":{"type":"object","properties":{"range":{"type":"string"},"message":{"type":"string"}},"required":["range","message"],"additionalProperties":false},"medium":{"type":"object","properties":{"range":{"type":"string"},"message":{"type":"string"}},"required":["range","message"],"additionalProperties":false},"low":{"type":"object","properties":{"range":{"type":"string"},"message":{"type":"string"}},"required":["range","message"],"additionalProperties":false}},"additionalProperties":false},"SuccessMeterSettings":{"type":"object","description":"Success meter block settings","properties":{"show_progress_meter":{"type":"boolean"},"completionMode":{"$ref":"#/components/schemas/AssessmentCompletionModeSetting"}},"additionalProperties":false},"CategorizationCategory":{"type":"object","description":"Categorization category","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"CategorizationItem":{"type":"object","description":"Categorization item","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["text","image"]},"textContent":{"type":"string"},"imageContent":{"type":"string"},"correctCategoryId":{"type":"string"},"feedback":{"type":"string"}},"required":["id","type","correctCategoryId"],"additionalProperties":false},"CategorizationSettings":{"type":"object","description":"Categorization block settings","properties":{"showInstructions":{"type":"boolean"},"shuffleItems":{"type":"boolean"},"showFeedback":{"type":"boolean"},"allowRetry":{"type":"boolean"},"completionMode":{"$ref":"#/components/schemas/AssessmentCompletionModeSetting"}},"additionalProperties":false},"SortingSettings":{"type":"object","description":"Sorting block settings","properties":{"showInstructions":{"type":"boolean"},"shuffleItems":{"type":"boolean"},"showPositionInputs":{"type":"boolean"},"showMoveButtons":{"type":"boolean"},"direction":{"type":"string","enum":["vertical","horizontal"]},"completionMode":{"$ref":"#/components/schemas/AssessmentCompletionModeSetting"}},"additionalProperties":false},"ReactionsBlockSettings":{"type":"object","properties":{"completionMode":{"type":"string","enum":["viewed","tried"]},"displayMode":{"type":"string","enum":["large","compact"]},"showCommentBox":{"type":"boolean"},"hideIfNotEnabled":{"type":"boolean"},"enablementCondition":{"type":"string","enum":["no_condition","previous_block","all_previous_blocks"]}},"additionalProperties":false},"ListItem":{"type":"object","description":"List item structure","properties":{"id":{"type":"string"},"text":{"type":"string"},"icon":{"type":"string"}},"required":["text"],"additionalProperties":false},"ListBlockOptions":{"type":"object","description":"List block options","properties":{"iconSize":{"type":"number"},"markerSize":{"type":"number"},"startNumber":{"type":"number"},"columns":{"type":"number"},"showDividers":{"type":"boolean"}},"additionalProperties":false}}},"security":[{"BearerAuth":[]}],"paths":{"/courses":{"get":{"summary":"List all courses","description":"Retrieves all courses in the workspace associated with the Personal Access Token, including courses owned by other workspace members regardless of dashboard folder or collaborator access. Requires courses:read (or api:*). Results are sorted by creation date (newest first), then ID for stable pagination. Follow pagination.totalPages to retrieve the complete list (up to 100 courses per page).","operationId":"listCourses","tags":["Courses"],"parameters":[{"name":"page","in":"query","description":"Page number for pagination (1-indexed).","schema":{"type":"integer","default":1,"minimum":1},"example":1},{"name":"limit","in":"query","description":"Number of items per page (max 100).","schema":{"type":"integer","default":20,"minimum":1,"maximum":100},"example":20}],"responses":{"200":{"description":"Successfully retrieved list of courses.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Course"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"example":{"success":true,"data":[{"id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","title":"Introduction to JavaScript","description":"Learn the fundamentals of JavaScript programming.","cover_image":"https://assets.scormstack.com/courses/js-intro/cover.jpg","user_id":"usr_e5f6a7b8-c9d0-1234-ef12-345678901234","created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-20T14:45:00.000Z","settings":{"navigation":{"allow_skip":false}}},{"id":"crs_f6a7b8c9-d0e1-2345-f678-90abcdef1234","title":"Advanced React Patterns","description":"Master advanced React techniques and patterns.","cover_image":null,"user_id":"usr_e5f6a7b8-c9d0-1234-ef12-345678901234","created_at":"2024-02-01T09:00:00.000Z","updated_at":"2024-02-05T16:30:00.000Z","settings":null}],"pagination":{"page":1,"limit":20,"total":2,"totalPages":1}}}}},"401":{"description":"Authentication required. Provide a valid Bearer token.","content":{"application/json":{"example":{"error":"Unauthorized","code":"UNAUTHORIZED"}}}}}},"post":{"summary":"Create a new course","description":"Creates a new course in the token workspace. By default it is owned by the token user; optionally provide owner_email (or owner_id) to assign an existing workspace member. Use one selector only. Requires courses:create (or api:*).","operationId":"createCourse","tags":["Courses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CourseCreate"},"examples":{"minimal":{"summary":"Minimal course","description":"Create a course with just a title.","value":{"title":"My New Course"}},"assignedOwner":{"summary":"Create a course for a workspace member","value":{"title":"My New Course","owner_email":"jordan@example.com"}},"complete":{"summary":"Complete course","description":"Create a course with all optional fields.","value":{"title":"Introduction to JavaScript","description":"Learn the fundamentals of JavaScript programming.","cover_image":"https://example.com/cover.jpg","settings":{"navigation":{"allow_skip":false}},"default_locale":"fr"}}}}}},"responses":{"201":{"description":"Course created successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Course"}}},"example":{"success":true,"data":{"id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","title":"Introduction to JavaScript","description":"Learn the fundamentals of JavaScript programming.","cover_image":null,"user_id":"usr_e5f6a7b8-c9d0-1234-ef12-345678901234","created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-15T10:30:00.000Z","settings":{"navigation":{"allow_skip":false}},"default_locale":{"language_code":"fr","language_name":"French","native_name":"Français","is_default":true,"text_direction":"ltr"}}}}}},"400":{"description":"Validation error in request body, or invalid/ambiguous owner selectors (INVALID_COURSE_OWNER). Provide only owner_email or owner_id, matching an existing member of the token workspace.","content":{"application/json":{"example":{"error":"Validation failed","code":"VALIDATION_ERROR","details":{"field":"title","reason":"Title is required"}}}}},"401":{"description":"Unauthorized"}}}},"/courses/import":{"post":{"summary":"Import full course in one request","description":"Creates a complete course tree (course, optional sections, variants, slides, blocks, and checkpoints) from a single payload. Courses are attached to the token workspace. Optional course.owner_email (or course.owner_id) assigns ownership to an existing workspace member; provide one selector only. Otherwise the token user owns the course.","operationId":"importCourse","tags":["Courses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CourseImportRequest"}}}},"responses":{"201":{"description":"Course imported successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CourseImportResponse"},"example":{"success":true,"data":{"course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","sections_created":1,"variants_created":1,"slides_created":1,"blocks_created":2,"checkpoints_created":1}}}}},"400":{"description":"Validation error in payload.","content":{"application/json":{"example":{"error":"Validation error","details":[{"path":["slides",0,"section_key"],"message":"Invalid section reference"}]}}}},"403":{"description":"Insufficient scopes or quota exceeded.","content":{"application/json":{"example":{"error":"Insufficient permissions. Missing scopes: sections:create, slides:create, blocks:create","code":"FORBIDDEN"}}}}}}},"/courses/{courseId}":{"get":{"summary":"Retrieve a course","description":"Retrieves details of a specific course by ID.","operationId":"getCourse","tags":["Courses"],"parameters":[{"name":"courseId","in":"path","required":true,"description":"Unique identifier of the course.","schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"responses":{"200":{"description":"Course retrieved successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Course"}}}}}},"404":{"description":"Course not found.","content":{"application/json":{"example":{"error":"Course not found","code":"RESOURCE_NOT_FOUND"}}}}}},"put":{"summary":"Update a course","description":"Updates an existing course in the token workspace. Only supplied fields change. Set owner_email (or owner_id) to assign an existing workspace member as owner; use one selector only. Ownership and supplied metadata update atomically. The former owner remains an editor and the new owner becomes course admin. Requires courses:update (or api:*).","operationId":"updateCourse","tags":["Courses"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CourseUpdate"},"example":{"title":"Updated Course Title","description":"Updated description for the course.","owner_email":"jordan@example.com"}}}},"responses":{"200":{"description":"Course updated successfully.","content":{"application/json":{"example":{"success":true,"data":{"id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","title":"Updated Course Title","description":"Updated description for the course.","updated_at":"2024-01-25T10:00:00.000Z"}}}}},"400":{"description":"Invalid request body or owner selectors (INVALID_COURSE_OWNER). Provide only owner_email or owner_id, matching an existing member of the token workspace."},"403":{"description":"Token is missing courses:update permission."},"404":{"description":"Course not found in the token workspace"}}},"delete":{"summary":"Delete a course","description":"Permanently deletes a course and all its contents (sections, slides, blocks).","operationId":"deleteCourse","tags":["Courses"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"responses":{"200":{"description":"Course deleted successfully.","content":{"application/json":{"example":{"success":true,"message":"Course deleted"}}}},"404":{"description":"Course not found"}}}},"/courses/{courseId}/analytics/learners":{"get":{"summary":"List course learners and analytics","description":"Returns the same learner rows and summary metrics shown in Courses Analytics → Learners. Search applies to learner ID, email, name, and nickname.","operationId":"listCourseLearnerAnalytics","tags":["Analytics"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"page","in":"query","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":100}},{"name":"search","in":"query","schema":{"type":"string","maxLength":500}},{"name":"sortBy","in":"query","schema":{"type":"string","default":"updated_at","enum":["learner_id","learner_email","learner_name","learner_pseudo","score","progress","completion_status","success_status","lesson_status","session_time","created_at","updated_at"]}},{"name":"sortOrder","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"includeFullData","in":"query","description":"Include each learner's raw suspend_data field.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Learner analytics retrieved successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/LearnerAnalytics"}},"summary":{"$ref":"#/components/schemas/LearnerAnalyticsSummary"},"pagination":{"$ref":"#/components/schemas/Pagination"},"sorting":{"type":"object","properties":{"sortBy":{"type":"string"},"sortOrder":{"type":"string","enum":["asc","desc"]}}},"filters":{"type":"object","properties":{"search":{"type":"string"},"includeFullData":{"type":"boolean"}}}},"required":["success","data","summary","pagination","sorting","filters"]}}}},"400":{"description":"Invalid query parameters"},"401":{"description":"Invalid or missing Personal Access Token"},"403":{"description":"Token is missing the analytics:read scope"},"404":{"description":"Course not found in the token workspace"},"429":{"description":"Rate limit exceeded"}}},"delete":{"summary":"Delete learner analytics","description":"Permanently deletes one or more learners and their course sessions and interactions, matching the bulk delete action in Courses Analytics → Learners.","operationId":"deleteCourseLearnerAnalytics","tags":["Analytics"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearnerAnalyticsDeleteRequest"}}}},"responses":{"200":{"description":"Learner analytics deleted successfully.","content":{"application/json":{"example":{"success":true,"data":{"learner_ids":["learner-1042","learner-1043"]}}}}},"400":{"description":"Invalid or missing JSON request body"},"401":{"description":"Invalid or missing Personal Access Token"},"403":{"description":"Token is missing the analytics:delete scope"},"404":{"description":"Course or learner not found"},"429":{"description":"Rate limit exceeded"}}}},"/courses/{courseId}/full":{"get":{"summary":"Get full course structure","description":"Retrieves an import-compatible full course payload including course settings, default locale, sections, variants, slides, blocks, and checkpoints. The response `data` object can be edited externally and posted to `POST /courses/import` to create a new copy.","operationId":"getFullCourse","tags":["Courses"],"parameters":[{"name":"courseId","in":"path","required":true,"description":"Unique identifier of the course.","schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"responses":{"200":{"description":"Full course payload retrieved successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CourseFullExportResponse"},"example":{"success":true,"data":{"course":{"title":"Onboarding Essentials","description":"Get learners operational in less than 10 minutes.","settings":{"navigation":{"allow_skip":false}},"status":"draft"},"sections":[{"key":"section_core","source_id":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901","title":"Core Concepts","order_index":0}],"variants":[{"key":"variant_fast_track","label":"Fast Track","is_required":false,"details":{},"order_index":0}],"slides":[{"key":"slide_welcome","source_id":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012","title":"Welcome","slide_type":"content","section_key":"section_core","order_index":0,"variant_keys":null,"blocks":[{"key":"block_intro","source_id":"blk_d4e5f6a7-b8c9-0123-def1-234567890123","type":"text","variant":"heading","content":{"heading":"Welcome","paragraph_1":"<p>Start here.</p>"},"position":0}]}],"checkpoints":[]}}}}},"403":{"description":"Missing one of the required read scopes: courses:read, sections:read, slides:read, blocks:read."},"404":{"description":"Course not found."}}}},"/courses/{courseId}/publish":{"post":{"summary":"Publish a course","description":"Starts publication of a course using the same export options exposed in the app.\n\nPackage exports return either a signed download URL immediately or a `request_id` plus `status_url` when background processing is required. When a package is ready, configured workspace webhooks receive a signed `course_published` event.\n\nThe `courseId` must belong to the workspace associated with the Personal Access Token.\n\nUse `format: \"public_link\"` to publish a hosted learner URL immediately.","operationId":"publishCourse","x-mcp-open-world":true,"tags":["Publishing"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoursePublishRequest"},"examples":{"scormAsync":{"summary":"SCORM package with bundled assets","value":{"format":"scorm","version":"2004","include_assets":true,"locale":"fr","track_progress":true,"learner_identification_type":"email"}},"publicLink":{"summary":"Public hosted link","value":{"format":"public_link","publish_mode":"new","share_option":"link","locale":"en"}},"xapi":{"summary":"xAPI package","value":{"format":"xapi","include_assets":true}},"cmi5":{"summary":"cmi5 package","value":{"format":"cmi5","include_assets":true}}}}}},"responses":{"200":{"description":"Publication completed synchronously.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoursePublishResponse"}}}},"202":{"description":"Publication started in the background.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoursePublishResponse"},"example":{"success":true,"data":{"request_id":"req_1234567890abcdef","status":"pending","format":"scorm","version":"2004","status_url":"/api/v1/courses/crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890/publish/req_1234567890abcdef","asset_count":12,"estimated_size_formatted":"48.2 MB","webhook_delivery":"course_published will be sent when the package is ready"}}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions or plan limit"},"404":{"description":"Course not found"}}}},"/courses/{courseId}/publish/{requestId}":{"get":{"summary":"Retrieve publish status","description":"Retrieves the status and result URL for a publication request.","operationId":"getPublishStatus","tags":["Publishing"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"requestId","in":"path","required":true,"schema":{"type":"string"},"example":"req_1234567890abcdef"}],"responses":{"200":{"description":"Publish request status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoursePublishStatus"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Course or publish request not found"}}}},"/courses/{courseId}/sections":{"get":{"summary":"List course sections","description":"Retrieves all sections in a course, ordered by their position.","operationId":"listSections","tags":["Sections"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"responses":{"200":{"description":"Sections retrieved successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Section"}}}},"example":{"success":true,"data":[{"id":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901","course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","title":"Getting Started","description":"Set up your development environment.","icon":"rocket","order_index":0,"created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-20T14:45:00.000Z"},{"id":"sec_c3d4e5f6-a7b8-9012-cdef-234567890123","course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","title":"Core Concepts","description":"Learn the fundamental concepts.","icon":"book","order_index":1,"created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-20T14:45:00.000Z"}]}}}}}},"post":{"summary":"Create a section","description":"Creates a new section in the course.","operationId":"createSection","tags":["Sections"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SectionCreate"},"example":{"title":"Getting Started","description":"Set up your development environment.","icon":"rocket"}}}},"responses":{"201":{"description":"Section created successfully.","content":{"application/json":{"example":{"success":true,"data":{"id":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901","course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","title":"Getting Started","description":"Set up your development environment.","icon":"rocket","order_index":0,"created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-15T10:30:00.000Z"}}}}}}}},"/courses/{courseId}/sections/{sectionId}":{"get":{"summary":"Retrieve a section","description":"Retrieves details of a specific section.","operationId":"getSection","tags":["Sections"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"sectionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901"}],"responses":{"200":{"description":"Section retrieved successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Section"}}}}}},"404":{"description":"Section not found"}}},"put":{"summary":"Update a section","description":"Updates an existing section.","operationId":"updateSection","tags":["Sections"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"sectionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SectionCreate"},"example":{"title":"Updated Section Title"}}}},"responses":{"200":{"description":"Section updated"}}},"delete":{"summary":"Delete a section","description":"Deletes a section. Slides in this section will be moved out of the section.","operationId":"deleteSection","tags":["Sections"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"sectionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901"}],"responses":{"200":{"description":"Section deleted"}}}},"/courses/{courseId}/slides":{"get":{"summary":"List course slides","description":"Retrieves all slides in a course, optionally filtered by section.","operationId":"listSlides","tags":["Slides"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"section_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Filter slides by section ID.","example":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901"}],"responses":{"200":{"description":"Slides retrieved successfully.","content":{"application/json":{"example":{"success":true,"data":[{"id":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012","course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","section_id":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901","title":"Variables and Data Types","order_index":0,"created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-20T14:45:00.000Z"},{"id":"sld_d4e5f6a7-b8c9-0123-def1-345678901234","course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","section_id":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901","title":"Functions and Scope","order_index":1,"created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-20T14:45:00.000Z"}],"pagination":{"page":1,"limit":20,"total":2,"totalPages":1}}}}}}},"post":{"summary":"Create a slide","description":"Creates a new slide in the course.","operationId":"createSlide","tags":["Slides"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlideCreate"},"examples":{"inSection":{"summary":"Slide in a section","value":{"title":"Variables and Data Types","section_id":"sec_b2c3d4e5-f6a7-8901-bcde-f12345678901"}},"standalone":{"summary":"Standalone slide","value":{"title":"Introduction"}}}}}},"responses":{"201":{"description":"Slide created"}}}},"/courses/{courseId}/slides/{slideId}":{"get":{"summary":"Retrieve a slide","description":"Retrieves details of a specific slide.","operationId":"getSlide","tags":["Slides"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"slideId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012"}],"responses":{"200":{"description":"Slide details"},"404":{"description":"Slide not found"}}},"put":{"summary":"Update a slide","description":"Updates an existing slide.","operationId":"updateSlide","tags":["Slides"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"slideId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012"}],"responses":{"200":{"description":"Slide updated"}}},"delete":{"summary":"Delete a slide","description":"Permanently deletes a slide and all its blocks.","operationId":"deleteSlide","tags":["Slides"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"slideId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012"}],"responses":{"200":{"description":"Slide deleted"}}}},"/courses/{courseId}/slides/{slideId}/blocks":{"get":{"summary":"List slide blocks","description":"Retrieves all blocks on a slide, in display order.","operationId":"listBlocks","tags":["Blocks"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"slideId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012"}],"responses":{"200":{"description":"Blocks retrieved successfully.","content":{"application/json":{"example":{"success":true,"data":[{"id":"blk_d4e5f6a7-b8c9-0123-def1-234567890123","type":"text","variant":"heading","content":{"heading":"Variables and Data Types","paragraph_1":"<p>In this lesson, you'll learn about JavaScript variables.</p>"},"created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-20T14:45:00.000Z"},{"id":"blk_e5f6a7b8-c9d0-1234-ef12-456789012345","type":"flashcards","variant":"stack","content":{"cards":[{"id":"c1","front":{"content":"<p>What is let?</p>"},"back":{"content":"<p>A block-scoped variable declaration.</p>"}}]},"created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-20T14:45:00.000Z"}]}}}}}},"post":{"summary":"Create a block","description":"Creates a new content block and adds it to the slide.\n\nThe `content` structure varies by block type. See the examples below or use `GET /blocks/defaults` to get templates for each block type.","operationId":"createBlock","tags":["Blocks"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"slideId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlockCreate"},"examples":{"textHeading":{"summary":"Text block (heading variant)","description":"Creates a text block with a large heading and paragraph content.","value":{"type":"text","variant":"heading","content":{"heading":"Welcome to JavaScript","paragraph_1":"<p>JavaScript is a versatile programming language that powers the modern web.</p>","options":{"headingSize":"large","headingFormat":"simple"}}}},"textParagraph":{"summary":"Text block (paragraph variant)","description":"Creates a text block focused on paragraph content.","value":{"type":"text","variant":"paragraph","content":{"heading":"","paragraph_1":"<p>This is a paragraph of text content. You can use <strong>bold</strong>, <em>italic</em>, and other HTML formatting.</p>"}}},"image":{"summary":"Image block","description":"Creates an image block with caption and styling options.","value":{"type":"image","variant":"image","content":{"text":"<p>A diagram showing the JavaScript event loop</p>","images":{"image_1":{"src":"https://example.com/images/event-loop.png","alt":"JavaScript event loop diagram","caption":"The JavaScript event loop processes tasks from the queue","position":"center"}},"options":{"box_shadow":true,"show_caption":true,"rounded_corners":true}}}},"video":{"summary":"Video block (YouTube)","description":"Creates a video block embedding a YouTube video.","value":{"type":"video","variant":"youtube","content":{"url":"https://www.youtube.com/watch?v=W6NZfCO5SIk","provider":"youtube","autoplay":false,"controls":true,"loop":false,"muted":false}}},"flashcards":{"summary":"Flashcards block","description":"Creates an interactive flashcard deck for memorization.","value":{"type":"flashcards","variant":"stack","content":{"cards":[{"id":"card-1","front":{"content":"<p>What is a variable in JavaScript?</p>"},"back":{"content":"<p>A variable is a container for storing data values. You declare variables using <code>let</code>, <code>const</code>, or <code>var</code>.</p>"}},{"id":"card-2","front":{"content":"<p>What is the difference between <code>let</code> and <code>const</code>?</p>"},"back":{"content":"<p><code>let</code> allows reassignment, while <code>const</code> creates a read-only reference that cannot be reassigned.</p>"}},{"id":"card-3","front":{"content":"<p>What are the primitive data types in JavaScript?</p>"},"back":{"content":"<p>String, Number, BigInt, Boolean, Undefined, Null, and Symbol.</p>"}}],"settings":{"showProgress":true,"flipDirection":"horizontal","shuffleCards":false}}}},"accordion":{"summary":"Accordion block","description":"Creates collapsible content sections.","value":{"type":"accordion","variant":"accordion_with_icon","content":{"items":[{"id":"item-1","title":"What is JavaScript?","content":"<p>JavaScript is a high-level, interpreted programming language that conforms to the ECMAScript specification.</p>","icon":"code"},{"id":"item-2","title":"Where can JavaScript run?","content":"<p>JavaScript runs in web browsers, on servers (Node.js), in mobile apps (React Native), and even on desktop applications (Electron).</p>","icon":"globe"},{"id":"item-3","title":"Is JavaScript the same as Java?","content":"<p>No! Despite the similar name, JavaScript and Java are completely different languages with different syntax and use cases.</p>","icon":"help-circle"}],"options":{"type":"single","defaultOpen":"item-1"}}}},"tabs":{"summary":"Tabs block","description":"Creates tabbed content panels.","value":{"type":"tabs","variant":"tabs_with_icon","content":{"items":[{"id":"tab-1","title":"Variables","content":"<p>Use <code>let</code> for values that change, <code>const</code> for constants.</p>"},{"id":"tab-2","title":"Functions","content":"<p>Functions are reusable blocks of code: <code>function greet(name) { return 'Hello ' + name; }</code></p>"},{"id":"tab-3","title":"Arrays","content":"<p>Arrays store multiple values: <code>const fruits = ['apple', 'banana', 'orange'];</code></p>"}],"options":{"type":"horizontal","defaultTab":"tab-1"}}}},"fillInBlank":{"summary":"Fill-in-the-blank assessment","description":"Creates a fill-in-the-blank quiz question.","value":{"type":"fill_in_blank","variant":"default","content":{"text":"<p>In JavaScript, you use the {{blank_1}} keyword to declare a variable that cannot be reassigned, and the {{blank_2}} keyword for variables that can change.</p>","blanks":[{"id":"blank_1","correctAnswers":["const"],"caseSensitive":false},{"id":"blank_2","correctAnswers":["let","var"],"caseSensitive":false}],"settings":{"showCorrectAnswers":true,"allowRetry":true},"grading":{"enabled":true,"points":10,"partialCredit":true}}}},"matching":{"summary":"Matching assessment","description":"Creates a drag-and-drop matching exercise.","value":{"type":"matching","variant":"default","content":{"instructions":"<p>Match each JavaScript concept with its description.</p>","pairs":[{"id":"pair-1","left":{"id":"l1","content":"<p><code>let</code></p>"},"right":{"id":"r1","content":"<p>Block-scoped, reassignable variable</p>"}},{"id":"pair-2","left":{"id":"l2","content":"<p><code>const</code></p>"},"right":{"id":"r2","content":"<p>Block-scoped, non-reassignable variable</p>"}},{"id":"pair-3","left":{"id":"l3","content":"<p><code>var</code></p>"},"right":{"id":"r3","content":"<p>Function-scoped, reassignable variable</p>"}}],"settings":{"shuffleItems":true,"showFeedback":true},"grading":{"enabled":true,"points":15}}}},"callout":{"summary":"Callout block","description":"Creates a highlighted info/tip/warning box.","value":{"type":"callout","variant":"tip","content":{"type":"tip","title":"Pro Tip","content":"<p>Always use <code>const</code> by default, and only use <code>let</code> when you know the variable needs to be reassigned.</p>"}}},"list":{"summary":"List block","description":"Creates a bulleted, numbered, or icon list.","value":{"type":"list","variant":"bullet","content":{"items":[{"id":"item-1","content":"<p>Variables store data values</p>","icon":"check"},{"id":"item-2","content":"<p>Functions are reusable code blocks</p>","icon":"check"},{"id":"item-3","content":"<p>Arrays hold multiple values</p>","icon":"check"},{"id":"item-4","content":"<p>Objects store key-value pairs</p>","icon":"check"}],"options":{"listType":"bullet","showIcons":false}}}},"resources":{"summary":"Resources block","description":"Creates a downloadable resources list.","value":{"type":"resources","variant":"list","content":{"title":"Additional Resources","items":[{"id":"res-1","title":"JavaScript MDN Documentation","description":"Comprehensive JavaScript reference","type":"link","url":"https://developer.mozilla.org/en-US/docs/Web/JavaScript"},{"id":"res-2","title":"Course Cheat Sheet","description":"PDF summary of all concepts covered","type":"file","fileUrl":"https://example.com/files/js-cheatsheet.pdf","fileName":"javascript-cheatsheet.pdf"}]}}},"flow":{"summary":"Flow block (step-by-step)","description":"Creates a guided step-by-step experience with images.","value":{"type":"flow","variant":"default","content":{"intro":{"content":"<p>Let's walk through creating your first JavaScript variable.</p>","startButtonText":"Start Tutorial"},"steps":[{"title":"Step 1: Open your editor","content":"<p>Open your code editor (VS Code, Sublime, etc.) and create a new file called <code>script.js</code>.</p>","media":{"url":"https://example.com/images/step1-editor.png","type":"image","position":"center"}},{"title":"Step 2: Declare a variable","content":"<p>Type <code>const greeting = 'Hello, World!';</code> in your file.</p>","media":{"url":"https://example.com/images/step2-variable.png","type":"image","position":"center"}},{"title":"Step 3: Log the value","content":"<p>Add <code>console.log(greeting);</code> on the next line to output the value.</p>"}],"outro":{"content":"<p>Congratulations! You've created your first JavaScript variable.</p>","completionMessage":"Tutorial completed!"},"settings":{"showProgress":true,"allowSkip":false}}}},"timeline":{"summary":"Timeline block","description":"Creates an interactive timeline with dated events and expandable rich details.","value":{"type":"timeline","variant":"default","content":{"events":[{"id":"event-1","date":"1995","name":"JavaScript is created","description":"Brendan Eich creates the first version of JavaScript.","icon":"light-bulb","image":{"src":"https://example.com/images/javascript-1995.png","alt":"Early web browser interface","caption":"JavaScript began as a browser scripting language.","position":"center"},"content":"<p>JavaScript was created to make web pages dynamic and interactive inside the browser.</p>"},{"id":"event-2","date":"2009","name":"Node.js expands JavaScript","description":"JavaScript starts running outside the browser.","icon":"server","image":null,"content":"<p>Node.js made JavaScript useful for server-side applications, build tools, and automation.</p>"}],"settings":{"layout":"vertical","displayMode":"expandable","completionMode":"tried","showConnectors":true,"connectorColor":"auto"}}}},"categorization":{"summary":"Categorization assessment","description":"Creates a drag-and-drop sorting exercise.","value":{"type":"categorization","variant":"checklist","content":{"instructions":"<p>Sort these items into the correct JavaScript data type category.</p>","categories":[{"id":"cat-1","title":"Primitive Types","color":"#4CAF50"},{"id":"cat-2","title":"Reference Types","color":"#2196F3"}],"items":[{"id":"item-1","content":"<p><code>\"hello\"</code></p>","correctCategory":"cat-1"},{"id":"item-2","content":"<p><code>42</code></p>","correctCategory":"cat-1"},{"id":"item-3","content":"<p><code>true</code></p>","correctCategory":"cat-1"},{"id":"item-4","content":"<p><code>{ name: 'John' }</code></p>","correctCategory":"cat-2"},{"id":"item-5","content":"<p><code>[1, 2, 3]</code></p>","correctCategory":"cat-2"}],"settings":{"shuffleItems":true,"showFeedback":true},"grading":{"enabled":true,"points":20,"partialCredit":true}}}},"sorting":{"summary":"Sorting assessment","description":"Creates an ordering exercise with drag-and-drop and accessible position inputs.","value":{"type":"sorting","variant":"default","content":{"title":"Order the JavaScript workflow","instructions":"Put the steps in the correct order.","items":[{"id":"item-1","type":"text","textContent":"<p>Create the file</p>"},{"id":"item-2","type":"text","textContent":"<p>Write the code</p>"},{"id":"item-3","type":"text","textContent":"<p>Run the script</p>"}],"correctOrder":["item-1","item-2","item-3"],"settings":{"shuffleItems":true,"showPositionInputs":true,"showMoveButtons":true,"direction":"vertical"},"grading":{"partialCredit":true,"weight":1}}}},"openResponse":{"summary":"Open response assessment","description":"Creates a free-text response question.","value":{"type":"open_response","variant":"default","content":{"question":"<p>Explain in your own words what a JavaScript function is and why functions are useful.</p>","placeholder":"Type your answer here...","minLength":50,"maxLength":500,"rubric":"<p>A good answer should mention: reusable code, parameters, return values, and code organization.</p>"}}},"reactions":{"summary":"Reactions block","description":"Captures a single learner reaction, with optional follow-up comment for outdated content or questions.","value":{"type":"reactions","variant":"default","content":{"settings":{"completionMode":"viewed","enablementCondition":"previous_block"}}}},"embed":{"summary":"Embed block","description":"Embeds external content via iframe.","value":{"type":"embed","variant":"iframe","content":{"url":"https://codepen.io/embed/preview/abcdef","title":"Interactive Code Example","height":400}}},"separator":{"summary":"Separator block","description":"Creates a visual divider between content sections.","value":{"type":"separator","variant":"line","content":{"style":"line","spacing":"medium"}}}}}}},"responses":{"201":{"description":"Block created and added to slide.","content":{"application/json":{"example":{"success":true,"data":{"id":"blk_d4e5f6a7-b8c9-0123-def1-234567890123","type":"text","variant":"heading","content":{"heading":"Welcome to JavaScript","paragraph_1":"<p>JavaScript is a versatile programming language.</p>"},"created_at":"2024-01-15T10:30:00.000Z","updated_at":"2024-01-15T10:30:00.000Z"}}}}},"400":{"description":"Invalid block content for the specified type.","content":{"application/json":{"example":{"error":"Invalid content for block type 'flashcards'","code":"INVALID_BLOCK_CONTENT","details":{"field":"content.cards","reason":"Cards array is required"}}}}}}}},"/courses/{courseId}/slides/{slideId}/blocks/{blockId}":{"get":{"summary":"Retrieve a block","description":"Retrieves details of a specific block.","operationId":"getBlock","tags":["Blocks"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"slideId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012"},{"name":"blockId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"blk_d4e5f6a7-b8c9-0123-def1-234567890123"}],"responses":{"200":{"description":"Block details"},"404":{"description":"Block not found"}}},"put":{"summary":"Update a block","description":"Updates an existing block's content and/or variant in place, preserving its ID and comments. A variant-only update preserves all stored content. Supported variants are listed by /blocks/defaults.","operationId":"updateBlock","tags":["Blocks"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"slideId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012"},{"name":"blockId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"blk_d4e5f6a7-b8c9-0123-def1-234567890123"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlockUpdate"},"example":{"content":{"heading":"Updated Heading","paragraph_1":"<p>Updated paragraph content.</p>"}}}}},"responses":{"200":{"description":"Block updated"},"400":{"description":"Invalid body or unsupported variant (INVALID_BLOCK_VARIANT)."}}},"delete":{"summary":"Remove a block","description":"Removes a block from the slide.","operationId":"deleteBlock","tags":["Blocks"],"parameters":[{"name":"courseId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"slideId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"sld_c3d4e5f6-a7b8-9012-cdef-123456789012"},{"name":"blockId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"example":"blk_d4e5f6a7-b8c9-0123-def1-234567890123"}],"responses":{"200":{"description":"Block removed from slide"}}}},"/blocks/defaults":{"get":{"summary":"Get block defaults","description":"Retrieves default content templates for all block types.\n\nUse this endpoint to discover available block types and their content structures. Returns real examples you can copy and modify when creating blocks.","operationId":"getBlockDefaults","tags":["Block Templates"],"parameters":[{"name":"type","in":"query","schema":{"type":"string"},"description":"Filter by block type (e.g., 'text', 'flashcards').","example":"text"},{"name":"variant","in":"query","schema":{"type":"string"},"description":"Get a specific variant. Requires 'type' parameter.","example":"heading"}],"responses":{"200":{"description":"Block defaults retrieved.","content":{"application/json":{"examples":{"allDefaults":{"summary":"All block types","description":"Returns all available block types and their variants.","value":{"success":true,"availableTypes":["slide_intro","separator","text","image","audio","video","embed","pdf","callout","list","table","accordion","tabs","flashcards","timeline","flow","interactive_image","web_simulation","resources","assessment","fill_in_blank","matching","click_on_image","success_meter","categorization","sorting","open_response","navigation_button","reactions","time_requirements"],"data":{"text":{"defaultVariant":"heading","createPayload":{"type":"text","variant":"heading","content":{"heading":"Your heading","paragraph_1":"<p>Content here</p>"}},"variants":{"heading":{"variant":"heading","name":"Heading","content":{"heading":"Your heading","paragraph_1":"<p>Content here</p>"},"createPayload":{"type":"text","variant":"heading","content":{"heading":"Your heading","paragraph_1":"<p>Content here</p>"}}},"paragraph":{"variant":"paragraph","name":"Paragraph","content":{"heading":"","paragraph_1":"<p>Your text here</p>"},"createPayload":{"type":"text","variant":"paragraph","content":{"heading":"","paragraph_1":"<p>Your text here</p>"}}}}}}}},"singleType":{"summary":"Single type (?type=flashcards)","value":{"success":true,"data":{"type":"flashcards","defaultVariant":"stack","createPayload":{"type":"flashcards","variant":"stack","content":{"cards":[{"id":"card-1","front":{"content":"<p>Question</p>"},"back":{"content":"<p>Answer</p>"}}]}},"variants":{"stack":{"variant":"stack","name":"Stack","content":{"cards":[{"id":"card-1","front":{"content":"<p>Question</p>"},"back":{"content":"<p>Answer</p>"}}]},"createPayload":{"type":"flashcards","variant":"stack","content":{"cards":[{"id":"card-1","front":{"content":"<p>Question</p>"},"back":{"content":"<p>Answer</p>"}}]}}}}}}}}}}},"404":{"description":"Block type or variant not found"}}}},"/assets":{"get":{"summary":"List assets","description":"Retrieves a paginated list of assets (images, videos, audio, PDFs) owned by the authenticated user.","operationId":"listAssets","tags":["Assets"],"parameters":[{"name":"page","in":"query","description":"Page number for pagination (1-indexed).","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","description":"Number of items per page (max 100).","schema":{"type":"integer","default":20,"minimum":1,"maximum":100}},{"name":"type","in":"query","description":"Filter by asset type.","schema":{"type":"string","enum":["image","video","audio","pdf"]}},{"name":"course_id","in":"query","description":"Filter assets by course ID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Assets retrieved successfully.","content":{"application/json":{"example":{"success":true,"data":[{"id":"ast_a1b2c3d4-e5f6-7890-abcd-ef1234567890","file_name":"course-banner_1704067200.jpg","file_type":"image/jpeg","file_size":245760,"url":"https://cdn.scormstack.com/medias/courses/123/course-banner_1704067200.jpg","width":1920,"height":1080,"created_at":"2024-01-01T10:00:00.000Z"},{"id":"ast_b2c3d4e5-f6a7-8901-bcde-f12345678901","file_name":"intro-video_1704067300.mp4","file_type":"video/mp4","file_size":52428800,"url":"https://cdn.scormstack.com/medias/courses/123/intro-video_1704067300.mp4","width":1280,"height":720,"metadata":{"duration":120},"created_at":"2024-01-01T10:05:00.000Z"}],"pagination":{"page":1,"limit":20,"total":2,"totalPages":1}}}}},"401":{"description":"Unauthorized"}}},"post":{"summary":"Upload a small asset (legacy)","description":"Upload a small asset file through the API function.\n\nThis legacy multipart endpoint is suitable only when the complete request is below the hosting platform's 4.5MB payload limit. For videos and other large files, use the three-step direct upload flow:\n\n1. `POST /assets/uploads` to obtain a pre-signed URL\n2. `PUT` the file directly to that URL\n3. `POST /assets/uploads/complete` to register the asset\n\n**Supported file types:**\n- **Images:** JPEG, PNG, GIF, WebP, SVG (max 10MB)\n- **Videos:** MP4, WebM, MOV, AVI (max 100MB; 250MB with Pro/Enterprise)\n- **Audio:** MP3, WAV, OGG, FLAC, M4A (max 100MB)\n- **PDF:** PDF documents (max 50MB)\n\n**Usage:** Send a multipart/form-data request with:\n- `file` (required): The file to upload\n- `course_id` (required): The course to associate the asset with","operationId":"uploadAsset","tags":["Assets"],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"The file to upload."},"course_id":{"type":"string","format":"uuid","description":"The course ID to associate the asset with."}},"required":["file","course_id"]}}}},"responses":{"201":{"description":"Asset uploaded successfully.","content":{"application/json":{"example":{"success":true,"data":{"id":"ast_a1b2c3d4-e5f6-7890-abcd-ef1234567890","file_name":"lesson-image_1704067200.jpg","file_type":"image/jpeg","file_size":245760,"category":"image","url":"https://cdn.scormstack.com/medias/courses/123/lesson-image_1704067200.jpg","created_at":"2024-01-01T10:00:00.000Z"}}}}},"400":{"description":"Invalid file or validation error.","content":{"application/json":{"examples":{"missingFile":{"summary":"No file provided","value":{"error":"No file provided. Send a file in the 'file' field.","code":"MISSING_FILE"}},"missingCourseId":{"summary":"No course_id provided","value":{"error":"course_id is required.","code":"MISSING_COURSE_ID"}},"invalidType":{"summary":"Unsupported file type","value":{"error":"Unsupported file type: text/plain. Allowed types: images, videos, audio, pdf.","code":"INVALID_FILE_TYPE"}},"tooLarge":{"summary":"File too large","value":{"error":"File too large. Maximum size for image: 10MB. Your file: 15MB.","code":"FILE_TOO_LARGE"}}}}}},"401":{"description":"Unauthorized"}}}},"/assets/uploads":{"post":{"summary":"Create a direct asset upload","description":"Create a short-lived pre-signed URL for uploading an asset directly to storage without sending the file through the ScormStack API function.\n\nAfter this request succeeds, send the exact file bytes to `data.upload_url` with an HTTP `PUT`. Include every header returned in `data.headers`. Then call `POST /assets/uploads/complete` with the returned `key` and the same `course_id`.\n\nThe pre-signed URL expires after five minutes.","operationId":"createAssetUpload","tags":["Assets"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file_name":{"type":"string","description":"Original file name, including its extension.","example":"introduction.mp4"},"file_type":{"type":"string","description":"MIME type sent with the direct upload.","example":"video/mp4"},"file_size":{"type":"integer","minimum":1,"description":"File size in bytes.","example":51380224},"course_id":{"type":"string","format":"uuid","description":"Course to associate the asset with."}},"required":["file_name","file_type","file_size","course_id"]}}}},"responses":{"201":{"description":"Direct upload created successfully.","content":{"application/json":{"example":{"success":true,"data":{"upload_url":"https://storage.example.com/bucket/medias/courses/course-id/introduction_123.mp4?X-Amz-Signature=...","method":"PUT","headers":{"Content-Type":"video/mp4","Content-Length":"51380224","Cache-Control":"max-age=31536000"},"key":"medias/courses/course-id/introduction_123.mp4","expires_at":"2026-08-25T10:05:00.000Z","complete_url":"/api/v1/assets/uploads/complete"}}}}},"400":{"description":"Invalid file metadata or file too large."},"401":{"description":"Unauthorized"},"404":{"description":"Course not found or access denied."}}}},"/assets/uploads/complete":{"post":{"summary":"Complete a direct asset upload","description":"Verify an object uploaded with `POST /assets/uploads`, create or update its asset record, and associate it with the course.\n\nScormStack reads the object's actual MIME type and size from storage before accepting it. This request is safe to retry with the same `key`.","operationId":"completeAssetUpload","tags":["Assets"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string","description":"Storage key returned by POST /assets/uploads.","example":"medias/courses/course-id/introduction_123.mp4"},"course_id":{"type":"string","format":"uuid","description":"The same course ID used to create the upload."}},"required":["key","course_id"]}}}},"responses":{"201":{"description":"Asset registered successfully.","content":{"application/json":{"example":{"success":true,"data":{"id":"ast_a1b2c3d4-e5f6-7890-abcd-ef1234567890","file_name":"introduction_123.mp4","file_type":"video/mp4","file_size":51380224,"category":"video","url":"https://cdn.scormstack.com/medias/courses/course-id/introduction_123.mp4","created_at":"2026-08-25T10:01:00.000Z"}}}}},"400":{"description":"Invalid upload key or uploaded object metadata."},"401":{"description":"Unauthorized"},"404":{"description":"Course or uploaded object not found."}}}},"/assets/{assetId}":{"get":{"summary":"Get an asset","description":"Retrieves details of a specific asset by ID.","operationId":"getAsset","tags":["Assets"],"parameters":[{"name":"assetId","in":"path","required":true,"description":"Unique identifier of the asset.","schema":{"type":"string","format":"uuid"},"example":"ast_a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"responses":{"200":{"description":"Asset retrieved successfully.","content":{"application/json":{"example":{"success":true,"data":{"id":"ast_a1b2c3d4-e5f6-7890-abcd-ef1234567890","file_name":"course-banner_1704067200.jpg","file_type":"image/jpeg","file_size":245760,"url":"https://cdn.scormstack.com/medias/courses/123/course-banner_1704067200.jpg","width":1920,"height":1080,"created_at":"2024-01-01T10:00:00.000Z"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Asset not found.","content":{"application/json":{"example":{"error":"Asset not found","code":"NOT_FOUND"}}}}}},"delete":{"summary":"Delete an asset","description":"Permanently deletes an asset from storage and database.","operationId":"deleteAsset","tags":["Assets"],"parameters":[{"name":"assetId","in":"path","required":true,"description":"Unique identifier of the asset to delete.","schema":{"type":"string","format":"uuid"},"example":"ast_a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"responses":{"200":{"description":"Asset deleted successfully.","content":{"application/json":{"example":{"success":true,"message":"Asset deleted successfully"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Asset not found.","content":{"application/json":{"example":{"error":"Asset not found","code":"NOT_FOUND"}}}}}}},"/locales/courses/{courseId}":{"get":{"summary":"List course locales","description":"Retrieves all locales (languages) configured for a course, including translation progress.","operationId":"listCourseLocales","tags":["Locales"],"parameters":[{"name":"courseId","in":"path","required":true,"description":"Unique identifier of the course.","schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"}],"responses":{"200":{"description":"Locales retrieved successfully.","content":{"application/json":{"example":{"success":true,"data":[{"id":"loc_a1b2c3d4-e5f6-7890-abcd-ef1234567890","course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","language_code":"en","language_name":"English","native_name":"English","is_default":true,"text_direction":"ltr","created_at":"2024-01-15T10:30:00.000Z"},{"id":"loc_b2c3d4e5-f6a7-8901-bcde-f12345678901","course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","language_code":"fr","language_name":"French","native_name":"Français","is_default":false,"text_direction":"ltr","created_at":"2024-01-16T09:00:00.000Z"},{"id":"loc_c3d4e5f6-a7b8-9012-cdef-234567890123","course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","language_code":"ar","language_name":"Arabic","native_name":"العربية","is_default":false,"text_direction":"rtl","created_at":"2024-01-17T11:00:00.000Z"}]}}}},"401":{"description":"Unauthorized"},"404":{"description":"Course not found.","content":{"application/json":{"example":{"error":"Course not found or access denied","code":"NOT_FOUND"}}}}}}},"/locales/courses/{courseId}/export":{"get":{"summary":"Export translations (XLIFF)","description":"Exports course translations in XLIFF format for use with external translation tools (Lokalise, Phrase, Crowdin, memoQ, etc.).\n\n**Query Parameters:**\n- `locale` (required): The target language code (e.g., 'fr', 'de', 'es')\n- `type`: Type of content to export - 'all' (default), 'system_labels', 'content', or 'general'\n- `version`: XLIFF version - '1.2', '2.0' (default), or '2.1'\n- `format`: Response format - 'xml' (default) or 'json'\n\n**Response:** With `format=xml`, returns the XLIFF file directly with Content-Type: application/xliff+xml. With `format=json`, returns `{ success, data: { xliff, filename, metadata } }`. The XLIFF version is selected independently with `version` (for example, `format=json&version=2.1`).","operationId":"exportTranslations","tags":["Locales"],"parameters":[{"name":"courseId","in":"path","required":true,"description":"Unique identifier of the course.","schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"locale","in":"query","required":true,"description":"Target language code to export translations for.","schema":{"type":"string"},"example":"fr"},{"name":"type","in":"query","description":"Type of content to export.","schema":{"type":"string","enum":["all","system_labels","content","general"],"default":"all"}},{"name":"version","in":"query","description":"XLIFF document version, independent of the response format.","schema":{"type":"string","enum":["1.2","2.0","2.1"],"default":"2.0"}},{"name":"format","in":"query","description":"Return raw XML or a JSON object containing the XLIFF and export metadata.","schema":{"type":"string","enum":["xml","json"],"default":"xml"}}],"responses":{"200":{"description":"XLIFF file exported successfully.","content":{"application/xliff+xml":{"schema":{"type":"string"},"example":"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\">\n  <file original=\"course_general\" source-language=\"en\" target-language=\"fr\" datatype=\"plaintext\">\n    <body>\n      <trans-unit id=\"course.title\">\n        <source>Introduction to JavaScript</source>\n        <target>Introduction à JavaScript</target>\n      </trans-unit>\n    </body>\n  </file>\n</xliff>"},"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"xliff":{"type":"string","description":"XLIFF document in the requested version."},"filename":{"type":"string"},"metadata":{"type":"object","properties":{"courseId":{"type":"string","format":"uuid"},"locale":{"type":"string"},"type":{"type":"string"},"xliffVersion":{"type":"string","enum":["1.2","2.0","2.1"]},"exportedAt":{"type":"string","format":"date-time"}}}}}}}}}},"400":{"description":"Missing locale or invalid type, version, or format parameter.","content":{"application/json":{"example":{"error":"locale query parameter is required","code":"MISSING_LOCALE"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Course or locale not found"}}}},"/locales/courses/{courseId}/import":{"post":{"summary":"Import translations (XLIFF)","description":"Imports translations from an XLIFF file. Supports files from external translation tools like Lokalise, Phrase, Crowdin, memoQ, etc.\n\n**Request Options:**\n- **Option A:** Send raw XML body with `Content-Type: application/xliff+xml`\n- **Option B:** Send multipart form with a 'file' field containing the XLIFF file\n\n**MCP:** Call `importTranslations` with the XLIFF XML string in `body`. The connector sends it as raw XML with the correct content type; do not JSON-encode the string yourself.\n\nKeep the file and unit identifiers from the export. Imports update locale targets, and omitted content and general fields keep their existing values. Invalid XML or files with no non-empty targets return an error.\n\nFor linked library blocks, imports save overrides in this course's locale. They never modify the shared library translation. Course overrides take priority field by field, with library translations as fallback, in the localization panel, XLIFF exports and course exports.\n\n**Import counts:** Each non-empty recognized unit is counted only in its own group (`systemLabels`, `content`, or `general`). `added` means no previous target existed; `modified` means an existing target changed; `unchanged` means it stayed the same. For system labels, existing targets include built-in translations shown by export, with saved overrides taking priority. Section titles are counted individually. `content.skipped` reports units referencing blocks not found in this course; they are not counted as added or modified.\n\n**Query Parameters:**\n- `locale` (required): Target language code (e.g., 'fr', 'de', 'es')\n\nIf the locale doesn't exist, it will be created automatically.","operationId":"importTranslations","tags":["Locales"],"parameters":[{"name":"courseId","in":"path","required":true,"description":"Unique identifier of the course.","schema":{"type":"string","format":"uuid"},"example":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890"},{"name":"locale","in":"query","required":true,"description":"Target language code to import translations for.","schema":{"type":"string"},"example":"fr"}],"requestBody":{"required":true,"content":{"application/xliff+xml":{"schema":{"type":"string"},"example":"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\">\n  <file original=\"course_general\" source-language=\"en\" target-language=\"fr\" datatype=\"plaintext\">\n    <body>\n      <trans-unit id=\"course.title\">\n        <source>Introduction to JavaScript</source>\n        <target>Introduction à JavaScript</target>\n      </trans-unit>\n    </body>\n  </file>\n</xliff>"},"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"The XLIFF file to import."}},"required":["file"]}}}},"responses":{"200":{"description":"Translations imported successfully.","content":{"application/json":{"example":{"success":true,"data":{"imported":{"systemLabels":{"added":5,"modified":2,"unchanged":10},"content":{"added":12,"modified":3,"unchanged":45,"skipped":0},"general":{"added":2,"modified":1,"unchanged":5}},"detectedVersion":"1.2","locale":"fr","localeId":"loc_b2c3d4e5-f6a7-8901-bcde-f12345678901","importedAt":"2024-01-20T14:30:00.000Z"}}}}},"400":{"description":"Invalid request.","content":{"application/json":{"examples":{"missingLocale":{"summary":"Missing locale parameter","value":{"error":"locale query parameter is required","code":"MISSING_LOCALE"}},"missingFile":{"summary":"Missing XLIFF content","value":{"error":"XLIFF content is required","code":"MISSING_XLIFF"}},"invalidXliff":{"summary":"Invalid XLIFF format","value":{"error":"Invalid XLIFF: Missing xliff root element","code":"INVALID_XLIFF"}},"noTranslations":{"summary":"No translated targets","value":{"error":"No non-empty translations found in the XLIFF targets","code":"NO_TRANSLATIONS"}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Course not found"}}}},"/webhooks/course_published":{"post":{"x-mcp-expose":false,"summary":"Course published webhook","description":"Outbound webhook delivered when a SCORM, xAPI, or HTML package export has completed.\n\nThis is **not** an API endpoint you call. Configure the destination in **Settings → Workspace → Webhooks** and ScormStack will send events to your server.","operationId":"webhookCoursePublished","tags":["Webhooks"],"parameters":[{"name":"Scormstack-Signature","in":"header","required":true,"description":"HMAC signature of the payload. Format: `t=timestamp,v1=signature` where signature = HMAC_SHA256(secret, `${t}.${rawBody}`)","schema":{"type":"string"},"example":"t=1705327800,v1=0f1d2c3b4a5e6f7890..."},{"name":"Scormstack-Event","in":"header","required":true,"description":"Webhook event type.","schema":{"type":"string"},"example":"course_published"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"},"example":{"id":"evt_1a2b3c4d5e6f7g8h9i0j","object":"event","type":"course_published","created":1705327800,"livemode":false,"data":{"object":{"course_id":"crs_a1b2c3d4-e5f6-7890-abcd-ef1234567890","title":"Introduction to JavaScript","lms_course_id":"LMS-COURSE-1024","download_url":"https://exports.scormstack.com/exports/req_123/course_scorm2004_with_assets.zip?X-Amz-Signature=...","expiration_date":"2024-01-22T14:45:00.000Z","export_type":"scorm","request_id":"req_1234567890abcdef"}}}}}},"responses":{"200":{"description":"Your endpoint should return a 2xx response to acknowledge receipt."}}}}},"tags":[{"name":"Courses","description":"Manage learning courses.\n\nCourses are the top-level container for all learning content. Each course can contain multiple sections and slides."},{"name":"Sections","description":"Organize course content into sections.\n\nSections are optional organizational units that group related slides together. They appear in the course navigation sidebar."},{"name":"Slides","description":"Manage content pages within courses.\n\nSlides are the main content containers. Each slide contains one or more blocks that make up the actual learning content."},{"name":"Blocks","description":"Create and manage content blocks.\n\nBlocks are the building blocks of slides. Each block has a `type` that determines its content structure:\n\n**Content Blocks:**\n- `text` - Rich text with headings and paragraphs\n- `image` - Images with captions\n- `video` - YouTube, Vimeo, or uploaded videos\n- `audio` - Audio with visualizations\n\n**Interactive Blocks:**\n- `flashcards` - Flip card decks\n- `accordion` / `tabs` - Collapsible or tabbed content\n- `flow` - Step-by-step guided experiences\n- `timeline` - Chronological events with expandable details\n\n**Assessment Blocks:**\n- `fill_in_blank` - Fill-in-the-blank questions\n- `matching` - Drag-and-drop matching\n- `categorization` - Sort items into categories\n- `sorting` - Sort items into a sequence\n- `success_meter` - Scenario-based assessments\n- `click_on_image` - Click correct areas on images\n- `open_response` - Free-text responses\n- `reactions` - Single-choice learner reactions with optional feedback comment\n\nSee the **Block Templates** endpoint for real examples of each block type."},{"name":"Block Templates","description":"Get default content templates for block types.\n\nUse these endpoints to discover available block types and get example content structures you can copy and modify."},{"name":"Assets","description":"Upload and manage media assets.\n\nAssets are files (images, videos, audio, PDFs) that can be used in course content blocks.\n\n**Supported file types:**\n- **Images:** JPEG, PNG, GIF, WebP, SVG (max 10MB)\n- **Videos:** MP4, WebM, MOV, AVI (max 100MB; 250MB with Pro/Enterprise)\n- **Audio:** MP3, WAV, OGG, FLAC, M4A (max 100MB)\n- **PDF:** PDF documents (max 50MB)\n\nFor files larger than 4MB, use the direct upload flow: create an upload with `POST /assets/uploads`, send the file to the returned storage URL, then register it with `POST /assets/uploads/complete`. The legacy `POST /assets` multipart endpoint remains available for small files."},{"name":"Locales","description":"Manage course translations and localization.\n\nExport and import course translations using XLIFF format, compatible with professional translation tools like Lokalise, Phrase, Crowdin, and memoQ.\n\n**Workflow:**\n0. Set the source/default language during course creation with `default_locale` (for example `\"fr\"`)\n1. List available locales with `GET /locales/courses/{courseId}`\n2. Export translations with `GET /locales/courses/{courseId}/export?locale=fr`\n3. Translate using your preferred translation tool or service\n4. Import completed translations with `POST /locales/courses/{courseId}/import?locale=fr`\n\n**Supported XLIFF versions:** 1.2 and 2.0\n\n**Translation types:**\n- **System Labels:** UI strings like buttons, navigation, etc.\n- **Content:** Block content (headings, paragraphs, quiz questions, etc.)\n- **General:** Course title, description, section names, slide titles"},{"name":"Publishing","description":"Publish courses as SCORM, xAPI, HTML packages, or hosted public links."},{"name":"Analytics","description":"Read, export, and delete course learner analytics collected by ScormStack progress tracking."},{"name":"Webhooks","description":"Receive outbound events from ScormStack.\n\nConfigure webhook destinations in **Settings → Workspace → Webhooks**. Events are signed using HMAC-SHA256 in the `Scormstack-Signature` header."}]}