Skip to Content
📧 Join the Teacharium waitlist to get access. 
Developer DocumentationAPIExport Lesson

Export Lesson

Export a published lesson version as a self-contained ZIP file containing all lesson content, media assets, and widget bundles.

EdTech Plan Required

Lesson export is available on EdTech plans only. Organizations on a Solo plan will receive a 403 Forbidden response with the code FEATURE_NOT_AVAILABLE. Contact your organization admin to upgrade if you need export access.

Endpoint

GET /api/lessons/{lessonId}/versions/{versionId}/export-zip

Authentication

This endpoint requires authentication using a Bearer token. See Authentication for complete details on API token format, usage, and error handling.

Path Parameters

ParameterTypeRequiredDescription
lessonIdstring (UUID)YesThe unique identifier of the lesson
versionIdstring (UUID)YesThe unique identifier of the published version

Response

Success Response (200 OK)

Returns a ZIP file as a binary download.

Response Headers:

HeaderValue
Content-Typeapplication/zip
Content-Dispositionattachment; filename="lesson-slug-v1.zip"
Content-LengthSize of the ZIP file in bytes

ZIP File Structure

The exported ZIP contains the following structure:

lesson-slug-v1/ ├── lesson.json # Lesson content with localized media references ├── manifest.json # Export metadata and file inventory ├── styles/ │ └── custom.css # Lesson custom CSS (if the lesson has any) ├── media/ │ ├── {uuid}.jpg # Media files (images, audio) │ ├── {uuid}.png │ └── ... ├── videos/ │ └── {uuid}/ │ ├── video.mp4 # Library videos (Video Player components) │ └── thumbnail.jpg └── widgets/ ├── {widget-id}.js # Widget JavaScript bundles ├── {widget-id}.css # Widget CSS files (if available) └── ...

lesson.json

Contains the full lesson content structure. All media references are rewritten from media:{uuid} format to local paths (./media/{uuid}.{ext}).

manifest.json

Contains export metadata and file inventory:

{ "lessonId": "550e8400-e29b-41d4-a716-446655440000", "title": "Introduction to Biology", "versionNumber": 1, "versionId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "publishedAt": "2025-01-15T10:30:00Z", "exportedAt": "2025-01-20T14:45:00Z", "formatVersion": "1.0.0", "files": { "lesson": "./lesson.json", "media": [ { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "localPath": "./media/a1b2c3d4-e5f6-7890-abcd-ef1234567890.jpg", "mimeType": "image/jpeg" } ], "widgets": [ { "widgetType": "multiple-choice", "localPath": "./widgets/widget-123.js", "cssLocalPath": "./widgets/widget-123.css" } ] }, "fonts": { "display": { "family": "Lobster", "category": "display", "variants": ["400"], "fontFamily": "\"Lobster\", system-ui, sans-serif" }, "body": null, "googleFontsUrl": "https://fonts.googleapis.com/css2?family=Lobster&display=swap" }, "failedMedia": [], "failedWidgets": [], "attributions": [ { "mediaId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "text": "Photo by John Doe", "url": "https://unsplash.com/photos/abc123", "portfolioUrl": "https://unsplash.com/@johndoe" } ] }

Error Responses

400 Bad Request

The path parameters are invalid.

{ "error": "Bad Request", "message": "Invalid lesson ID", "code": "BAD_REQUEST", "timestamp": "2025-01-20T14:45:00.000Z" }

401 Unauthorized

Authentication failed. See Authentication Errors for detailed information.

{ "error": "Authentication Error", "message": "User authentication is required", "code": "UNAUTHORIZED", "timestamp": "2025-01-20T14:45:00.000Z" }

403 Forbidden

The organization’s plan does not include lesson export. This applies to Solo plan organizations.

{ "error": "Forbidden", "message": "Lesson export is not available on your current plan. Upgrade to an EdTech plan to export lessons.", "code": "FEATURE_NOT_AVAILABLE", "timestamp": "2025-01-20T14:45:00.000Z" }

404 Not Found

The specified lesson or version does not exist, or is not accessible by the authenticated user.

{ "error": "Not Found", "message": "Published version not found", "code": "NOT_FOUND", "timestamp": "2025-01-20T14:45:00.000Z" }

422 Unprocessable Entity

The published version content is invalid or empty.

{ "error": "Invalid Content", "message": "Published version content is invalid or empty", "code": "INVALID_CONTENT", "timestamp": "2025-01-20T14:45:00.000Z" }

500 Internal Server Error

An unexpected error occurred during export.

{ "error": "Internal Server Error", "message": "An unexpected error occurred while generating export ZIP", "code": "INTERNAL_ERROR", "timestamp": "2025-01-20T14:45:00.000Z" }

Example Requests

Download Lesson Export

curl -X GET 'https://app.teacharium.io/api/lessons/550e8400-e29b-41d4-a716-446655440000/versions/6ba7b810-9dad-11d1-80b4-00c04fd430c8/export-zip' \ -H 'Authorization: Bearer tapub_xxxxx.tasec_xxxxx' \ -o lesson-export.zip

Using wget

wget --header='Authorization: Bearer tapub_xxxxx.tasec_xxxxx' \ 'https://app.teacharium.io/api/lessons/550e8400-e29b-41d4-a716-446655440000/versions/6ba7b810-9dad-11d1-80b4-00c04fd430c8/export-zip' \ -O lesson-export.zip

Export Manifest

If you need to download assets individually or implement custom export logic, you can use the manifest endpoint:

GET /api/lessons/{lessonId}/versions/{versionId}/export-manifest

This returns a JSON manifest with signed URLs for all assets (valid for 4 hours), allowing you to download files individually.

Export SCORM Package

To deliver a lesson through an LMS (Moodle, Canvas, Cornerstone, SCORM Cloud and others), export it as a SCORM package instead:

GET /api/lessons/{lessonId}/versions/{versionId}/export-scorm?version=1.2
Query ParameterValuesDefaultDescription
version1.2 or 20041.2SCORM version of the package. SCORM 2004 packages use the 4th Edition manifest schema.

The response is a ZIP to upload to your LMS as-is. It contains everything in the lesson export above, at the root of the ZIP, plus:

FilePurpose
imsmanifest.xmlSCORM manifest with a single SCO that launches index.html
index.html, runtime/A self-contained lesson player
react-shim.js, react-dom-shim.jsLet the widget bundles share the player’s React
scorm.jsonThe SCORM version the package was exported for

The player reports to the LMS:

  • Status: incomplete when the learner starts, then completed at the end. If the lesson is scored and the LMS sets a passing score (cmi.student_data.mastery_score in SCORM 1.2, cmi.scaled_passing_score in SCORM 2004), the result is passed or failed instead.
  • Score: SCORM 1.2 gets a percentage (0–100). SCORM 2004 gets the raw score, its maximum and the scaled score (0–1).
  • Resume: the learner’s progress is saved in cmi.suspend_data at every step, so they continue where they left off. SCORM 1.2 allows only 4,096 characters, so long lessons are compressed and, if still too long, only the current step and variables are kept.
  • Review: relaunching a finished attempt opens it in review mode when the LMS keeps its data.
  • Session time and exit when the learner leaves.

Fonts are loaded from Google Fonts, as in the lesson export, so learners need internet access for custom lesson fonts.

Notes

  • Only published lesson versions can be exported
  • The ZIP file includes all media assets and widget bundles required to play the lesson offline
  • Media references in lesson.json are automatically rewritten to use local paths
  • External media (e.g., from Unsplash) is downloaded and included in the ZIP
  • Attribution information for external media is preserved in manifest.json
  • Font files are not included. If the lesson uses custom fonts, manifest.json has a fonts entry (omitted otherwise) with the font families and a ready-made Google Fonts URL; your page must load them. See Lesson Fonts
  • Large exports may take several seconds to generate on the server
  • The failedMedia and failedWidgets arrays in the manifest indicate any assets that could not be downloaded
  • This endpoint is only available to organizations on an EdTech plan. Solo plan organizations should use hosted embedding or LTI integration instead