Courses & quizzes
Courses & quizzes endpoints of the Zanfia Workspace API, with schemas and code samples.
Course content is addressed by the product id. Lesson and module statuses: draft, public, hidden, locked. Lesson content is Markdown and a PATCH replaces the whole body. Video lessons also carry chapters and key moments on their Bunny video (…/lessons/{lessonId}/video); the AI generate routes propose them from the transcript and you persist the picks with the same PUT. All routes require a Authorization: Bearer header — see Authentication.
Course structure
/products/{productId}/courseAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Response Body
application/json
application/json
curl -X GET "https://example.com/products/string/course"{ "courseId": "string", "modulesCount": 0, "modules": [ { "id": "string", "name": "string", "description": "string", "status": "draft", "lessonsCount": 0, "lessons": [ { "id": "string", "title": "string", "description": "string", "type": "video", "status": "draft", "videoStatus": "Pending", "length": 0, "thumbnail": "string" } ] } ]}{ "error": "string", "message": "string"}Course analytics
/products/{productId}/course/analyticsAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Query Parameters
Learner rows to return (default 50, max 200).
progress-desc (default), progress-asc (least progress first) or last-activity-desc.
Value in
- "progress-desc"
- "progress-asc"
- "last-activity-desc"
Response Body
application/json
application/json
curl -X GET "https://example.com/products/string/course/analytics"{ "summary": { "tracked": 0, "completedCourse": 0, "activeLast7Days": 0, "activeLast30Days": 0 }, "lessons": [ { "lessonId": "string", "title": "string", "module": "string", "status": "string", "started": 0, "completed": 0, "quizAttempts": 0, "quizPassed": 0 } ], "learners": { "total": 0, "returned": 0, "lessonsBasis": 0, "rows": [ { "email": "string", "name": "string", "progressPercent": 0, "completedLessons": 0, "startedLessons": 0, "completedCourse": true, "numberOfSessions": 0, "firstActivityAt": "string", "lastActivityAt": "string" } ] }}{ "error": "string", "message": "string"}Course transcripts map
/products/{productId}/course/transcriptsAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Response Body
application/json
application/json
curl -X GET "https://example.com/products/string/course/transcripts"{ "courseId": "string", "modules": [ { "id": "string", "name": "string", "lessons": [ { "lessonId": "string", "title": "string", "type": "video", "mediaId": "string", "hasTranscript": true, "transcriptionStatus": "string", "durationSeconds": 0 } ] } ], "totals": { "lessons": 0, "videoLessons": 0, "transcribed": 0 }}{ "error": "string", "message": "string"}Lesson detail
/products/{productId}/course/lessons/{lessonId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Response Body
application/json
application/json
curl -X GET "https://example.com/products/string/course/lessons/string"{ "courseId": "string", "lesson": { "id": "string", "moduleId": "string", "title": "string", "description": "string", "type": "video", "status": "draft", "content": "string", "attachments": [ { "uid": "string", "name": "string", "url": "string" } ], "thumbnail": "string", "video": { "type": "bunny", "status": "Pending", "url": "string", "length": 0 }, "audio": { "url": "string", "mimeType": "string", "length": 0, "size": 0 }, "createdAt": "string", "updatedAt": "string" }}{ "error": "string", "message": "string"}Update a lesson
/products/{productId}/course/lessons/{lessonId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X PATCH "https://example.com/products/string/course/lessons/string" \ -H "Content-Type: application/json" \ -d '{}'{ "lessonId": "string"}{ "error": "string", "message": "string"}Delete a lesson (permanent)
/products/{productId}/course/lessons/{lessonId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Response Body
application/json
application/json
curl -X DELETE "https://example.com/products/string/course/lessons/string"{ "deleted": true}{ "error": "string", "message": "string"}Add a module
/products/{productId}/course/modulesAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X POST "https://example.com/products/string/course/modules" \ -H "Content-Type: application/json" \ -d '{ "name": "string" }'{ "moduleId": "string", "name": "string"}{ "error": "string", "message": "string"}Update a module
/products/{productId}/course/modules/{moduleId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Module id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X PATCH "https://example.com/products/string/course/modules/string" \ -H "Content-Type: application/json" \ -d '{}'{ "moduleId": "string"}{ "error": "string", "message": "string"}Delete a module (permanent)
/products/{productId}/course/modules/{moduleId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Module id
Response Body
application/json
application/json
curl -X DELETE "https://example.com/products/string/course/modules/string"{ "deleted": true}{ "error": "string", "message": "string"}Add a lesson
/products/{productId}/course/modules/{moduleId}/lessonsAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Module id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X POST "https://example.com/products/string/course/modules/string/lessons" \ -H "Content-Type: application/json" \ -d '{ "title": "string", "type": "video" }'{ "lessonId": "string", "moduleId": "string", "title": "string"}{ "error": "string", "message": "string"}Bulk lesson status change
/products/{productId}/course/lessons/statusAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X POST "https://example.com/products/string/course/lessons/status" \ -H "Content-Type: application/json" \ -d '{ "lessonIds": [ "string" ], "status": "draft" }'{ "updated": 0}{ "error": "string", "message": "string"}Reorder modules
/products/{productId}/course/modules/orderAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X PUT "https://example.com/products/string/course/modules/order" \ -H "Content-Type: application/json" \ -d '{ "moduleIds": [ "string" ] }'{ "courseId": "string"}{ "error": "string", "message": "string"}Reorder a module's lessons
/products/{productId}/course/modules/{moduleId}/lessons/orderAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Module id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X PUT "https://example.com/products/string/course/modules/string/lessons/order" \ -H "Content-Type: application/json" \ -d '{ "lessonIds": [ "string" ] }'{ "moduleId": "string"}{ "error": "string", "message": "string"}Set a lesson thumbnail
/products/{productId}/course/lessons/{lessonId}/thumbnailAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X PUT "https://example.com/products/string/course/lessons/string/thumbnail" \ -H "Content-Type: application/json" \ -d '{}'{ "lessonId": "string", "thumbnailUrl": "string"}{ "error": "string", "message": "string"}Lesson video chapters & moments
/products/{productId}/course/lessons/{lessonId}/videoAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Response Body
application/json
application/json
curl -X GET "https://example.com/products/string/course/lessons/string/video"{ "lessonId": "string", "chapters": [ { "title": "string", "start": 0, "end": 0 } ], "moments": [ { "label": "string", "timestamp": 0 } ], "metaTags": [ { "property": "string", "value": "string" } ]}{ "error": "string", "message": "string"}Save lesson video chapters & moments
/products/{productId}/course/lessons/{lessonId}/videoAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Presence-based: a list that is sent REPLACES the stored list, an omitted list is kept as is (the server fills it from the current video). At least one list required. metaTags are merged over Bunny's existing tags.
Response Body
application/json
application/json
curl -X PUT "https://example.com/products/string/course/lessons/string/video" \ -H "Content-Type: application/json" \ -d '{}'{ "lessonId": "string", "updated": true}{ "error": "string", "message": "string"}Generate chapters (AI)
/products/{productId}/course/lessons/{lessonId}/chapters/generateAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
AI chapter proposal from the lesson's transcript — candidates only, nothing is persisted; save them with PUT …/lessons/{lessonId}/video.
Response Body
application/json
application/json
curl -X POST "https://example.com/products/string/course/lessons/string/chapters/generate" \ -H "Content-Type: application/json" \ -d '{}'{ "chapters": [ { "title": "string", "start": 0, "end": 0 } ]}{ "error": "string", "message": "string"}Generate key moments (AI)
/products/{productId}/course/lessons/{lessonId}/moments/generateAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X POST "https://example.com/products/string/course/lessons/string/moments/generate" \ -H "Content-Type: application/json" \ -d '{}'{ "moments": [ { "label": "string", "timestamp": 0 } ]}{ "error": "string", "message": "string"}Quiz questions & settings
/products/{productId}/course/lessons/{lessonId}/quizAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Response Body
application/json
application/json
curl -X GET "https://example.com/products/string/course/lessons/string/quiz"{ "questions": [ { "id": "string", "question": "string", "explanation": "string", "points": 0, "order": 0, "mediaUrl": "string", "source": { "snippet": "string", "startSeconds": 0 }, "type": "single_choice", "options": [ { "id": "string", "text": "string", "isCorrect": true, "mediaUrl": "string" } ] } ], "settings": { "passingScore": 0, "maxAttempts": 0, "timeLimitSeconds": 0, "shuffleQuestions": true, "shuffleOptions": true, "showCorrectAnswers": true, "requirePassToProgress": true, "questionCount": 0, "totalPoints": 0 }}{ "error": "string", "message": "string"}Add a quiz question
/products/{productId}/course/lessons/{lessonId}/quiz/questionsAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X POST "https://example.com/products/string/course/lessons/string/quiz/questions" \ -H "Content-Type: application/json" \ -d '{ "question": { "question": "string", "type": "single_choice", "options": [ { "text": "string", "isCorrect": true } ] } }'{ "questionId": "string"}{ "error": "string", "message": "string"}Reorder quiz questions
/products/{productId}/course/lessons/{lessonId}/quiz/questions/orderAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X PUT "https://example.com/products/string/course/lessons/string/quiz/questions/order" \ -H "Content-Type: application/json" \ -d '{ "orderedQuestionIds": [ "string" ] }'{ "reordered": true}{ "error": "string", "message": "string"}Replace a quiz question
/products/{productId}/course/lessons/{lessonId}/quiz/questions/{questionId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Quiz question id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X PATCH "https://example.com/products/string/course/lessons/string/quiz/questions/string" \ -H "Content-Type: application/json" \ -d '{ "question": { "question": "string", "type": "single_choice", "options": [ { "text": "string", "isCorrect": true } ] } }'{ "updated": true}{ "error": "string", "message": "string"}Delete a quiz question (permanent)
/products/{productId}/course/lessons/{lessonId}/quiz/questions/{questionId}Authorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Quiz question id
Response Body
application/json
application/json
curl -X DELETE "https://example.com/products/string/course/lessons/string/quiz/questions/string"{ "deleted": true}{ "error": "string", "message": "string"}Update quiz settings
/products/{productId}/course/lessons/{lessonId}/quiz/settingsAuthorization
bearerAuth API key from Dashboard → Integrations → API, MCP and CLI.
In: header
Path Parameters
Product id
Lesson id
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X PATCH "https://example.com/products/string/course/lessons/string/quiz/settings" \ -H "Content-Type: application/json" \ -d '{ "settings": {} }'{ "updated": true}{ "error": "string", "message": "string"}Was this article helpful?

