Guides
Gradebook Sync
Push exam results into your gradebook the moment they are graded.
Flow#
- Register a webhook endpoint subscribed to
exam.graded(and optionallyexam.submittedfor "turned in" states). - On
exam.graded, fetch the submission for the authoritative numbers. - Write the score to the gradebook item mapped to
exam_id.
Handler sketch#
app.post('/hooks/grout', express.raw({ type: 'application/json' }), async (req, res) => {
if (!verifyGrout(req.body.toString(), req.get('X-Grout-Signature'), SECRET)) return res.status(400).end();
const evt = JSON.parse(req.body);
res.status(202).end(); // ack first
if (await seen(evt.id)) return; // dedupe on event id
if (evt.type !== 'exam.graded') return;
const { data } = await grout(`/submissions/${evt.data.submission_id}`);
const item = await gradeItemFor(evt.data.exam_id);
if (evt.data.resubmission_required) await markNeedsRevision(item, data.student_id, data.feedback);
else await postGrade(item, data.student_id, data.score, data.max_score, data.feedback);
});Mapping exams to items#
Create the gradebook item when you see exam.published (title, max_score, due_date), store exam_id → item_id, and assign the exam to the section's group. That keeps authoring in Grout and reporting in the LMS.
Backfill#
Missed events? Pull them:
curl "$API/events?type=exam.graded&since=2026-09-01T00:00:00Z" -H "Authorization: Bearer $KEY"
curl "$API/submissions?exam_id=ex_…&status=graded" -H "Authorization: Bearer $KEY"Or export a whole exam with GET /exams/{id}/export.csv.