Course Evaluations and Quizzes in Your LMS
This guide shows how a learning management system or course platform gives every instructor a survey workspace for their own course, shows the end-of-course evaluation or a knowledge check to learners on the course page, and hears back from ResponseDock when a learner has answered. It uses the same signed embed tokens as Embedding a survey builder for your customers, with the course as the subject.
Embedded workspaces, respondent embeds, the browser SDK and webhooks need a workspace secret key, which is part of the Pro plan and above. Never send the secret key to the browser.
How It Works
- When an instructor opens a course's surveys tab, your backend requests an admin embed with the course as the
subject. - The instructor creates the evaluation or a knowledge check, from a template or from scratch, and publishes it. Your page stores the survey ID against the course.
- At the end of the course, your backend requests a respondent embed signed with the learner's ID, and the learner answers on your course page.
- A signed
survey.response.completedwebhook tells your backend that the learner has answered.
1. A Workspace for Each Course
POST https://api.responsedock.com/api/v1/auth/embed-token
Authorization: Bearer sk_live_your_secret_key
Content-Type: application/json
{
"workspaceId": "ws_xxxx",
"role": "admin",
"mode": "workspace",
"allowedOrigin": "https://lms.yourplatform.com",
"tenant": { "id": "school_42", "name": "Northfield College" },
"user": { "id": "instructor_7", "name": "Dana Whitfield" },
"capabilities": ["questionnaire:create", "questionnaire:edit", "questionnaire:publish", "results:view"],
"subject": { "type": "course", "id": "course_101", "label": "Intro to Data Analysis" }
}The response contains token, expiresIn (300 seconds) and embedUrl. Load the URL in an iframe. Questionnaires created in this session are filed under the course, and list, results and export requests for other courses are refused by the API, whatever the browser sends. Leave out questionnaire:create and questionnaire:edit for teaching assistants who should only read results.
2. Keep the Course's Survey IDs
The iframe posts responsedock.survey.created for every new survey, whether the instructor starts from a blank questionnaire or from a template. The message also carries the signed subject.
window.addEventListener('message', (event) => {
if (event.origin !== 'https://app.responsedock.com') return;
if (event.data?.type === 'responsedock.survey.created') {
saveCourseSurvey(event.data.subject?.id, event.data.survey.id);
}
});3. Show the Evaluation to Learners
Request a respondent embed for the learner who reached the end of the course:
POST https://api.responsedock.com/api/v1/auth/embed-token
Authorization: Bearer sk_live_your_secret_key
Content-Type: application/json
{
"workspaceId": "ws_xxxx",
"role": "respondent",
"surveyId": "survey_end_of_course",
"allowedSurveyIds": ["survey_end_of_course"],
"externalUserId": "learner_123",
"allowedOrigin": "https://lms.yourplatform.com"
}Set the survey's duplicate rule to One per external user ID (ONE_PER_EXTERNAL_USER), so each learner can complete it once. The learner's identity comes from the signed token, not from the browser. Respondent screens are translated into 18 languages, including right-to-left Arabic and Hebrew; see Localization for translating the questions.
Two other ways to reach learners:
- Browser SDK. Identify the learner and send
ResponseDock.track('course_completed', { courseId }). A trigger rule with theONCE_PER_CONTEXTfrequency andcontextKey: "courseId"opens the survey in a modal once per learner per course. - Email invitations. From your ResponseDock dashboard, send personal survey links to a list of addresses, with one reminder for people who have not answered.
4. Knowledge Checks (Quiz Mode)
Turn on Quiz mode in the builder to give questions an answer key, points and an explanation, and to set a passing score. Choice, yes/no and number answers are scored automatically. Open-text answers with a reference answer are graded by an AI model, and only when the server has one configured (OPENAI_API_KEY). The Module Knowledge Check template uses choice questions only, so it is scored without AI.
What learners see when they submit follows the quiz settings. With Show score at the end, the thank-you screen shows their points, the percentage and, when you set a passing score, whether they passed. With Show correct answers and explanations, it adds a review of every scored question: their answer, the correct answer and your explanation. The score is calculated on the server when the response is completed, and the answer key never reaches the browser before the learner submits. With both settings off, learners see only the thank-you screen.
An open-text answer that could not be graded (no AI model configured, or grading failed or timed out) is shown as waiting for review, and while it could still change the outcome, the result says pass or fail is decided after review. Retake quiz starts a new attempt when the quiz allows retakes and the survey's duplicate rule allows more than one response; with One per external user ID each learner has one attempt. Response notification emails include the score and whether the learner passed.
When the score is shown, the survey frame's responsedock.lifecycle.completed message carries it too, without answers or the answer key:
window.addEventListener('message', (event) => {
if (event.origin !== 'https://survey.responsedock.com') return;
if (event.data?.type === 'responsedock.lifecycle.completed' && event.data.payload.quiz) {
// { score: 7, maxScore: 8, scorePercent: 88, passed: true, pendingReview: false }
showProgressBadge(event.data.payload.quiz);
}
});Use the message for the page you show. Record grades from the signed webhook below, not from the browser.
5. Hear Back When a Learner Answers
Create a webhook endpoint subscribed to survey.response.completed (see Webhooks). Each delivery is signed:
{
"event": "survey.response.completed",
"data": {
"workspaceId": "ws_xxxx",
"surveyId": "survey_end_of_course",
"surveySlug": "end-of-course-evaluation",
"responseId": "resp_aaaa",
"completedAt": "2026-10-18T09:30:00.000Z",
"isAnonymous": false,
"answers": { "count": 6 },
"externalUserId": "learner_123"
}
}import { createHmac, timingSafeEqual } from 'node:crypto';
const ts = Number(req.headers['x-responsedock-timestamp']);
const expected = 'sha256=' + createHmac('sha256', process.env.RESPONSEDOCK_WEBHOOK_SECRET)
.update(`${ts}.${rawBody}`).digest('hex');
const received = String(req.headers['x-responsedock-signature-v2'] ?? '');
if (Math.abs(Date.now() - ts) > 5 * 60_000 || received.length !== expected.length
|| !timingSafeEqual(Buffer.from(received), Buffer.from(expected))) {
return res.status(401).end();
}
const { event, data } = JSON.parse(rawBody);
if (event === 'survey.response.completed' && data.externalUserId) {
await markCourseTaskDone(data.externalUserId, data.surveyId, data.completedAt);
if (data.quiz) await recordGrade(data.externalUserId, data.surveyId, data.quiz);
}The payload carries the answer count, never the answers themselves. For a quiz it also carries a score summary, whatever the learner is shown:
"quiz": { "score": 7, "maxScore": 8, "scorePercent": 88, "passed": true, "pendingReview": false }passed is null when the quiz has no passing score, or when an open-text answer waiting for review could still change the outcome (pendingReview is then true). The summary never includes answers or the answer key. Instructors read and export answers in the course workspace. For an anonymous survey the payload has no externalUserId and no quiz score, so your LMS can count completions without knowing who said what.
Templates
- Course Evaluation: quality, learning objectives, the instructor and what to change.
- Module Knowledge Check: a scored quiz with explanations and a passing score.
- Training Evaluation: reaction, learning and application at work.
What It Does Not Do
- There is no LTI or SCORM package. The integration runs from your backend with the embed token, the SDK and webhooks.
- No completion certificates or badges. Issue them from your LMS when the webhook arrives.
- Answers waiting for review are not graded later in ResponseDock, and the webhook is not sent again. Grade those answers in your LMS if you need a final mark.
- The webhook carries the score, not the per-question results or the answers.