Skip to main content

Mark a practice session as completed and return the score

POST 

/sessions/:session_id/complete

Sets the session's completed_at = now() and returns the finalized session payload with a server-computed score_percentage. Can be called even when not all questions were answered (the user quit early) -- total_questions stays at the snapshot value, correct_answers reflects only the answers actually submitted.

Score: round((correct_answers / total_questions) * 100), rounded to the nearest integer. When total_questions is 0 (theoretically unreachable -- create-quiz requires >=1 -- but the read-side defensively handles it), the score is 0 rather than a division-by-zero panic.

Authorization: the session must belong to the authenticated user (403 otherwise). Once completed, a second call returns 409 -- this endpoint is NOT idempotent. Callers that want to fetch a completed session's state should use GET /api/sessions/{id} (ASK-152, future).

Race protection: SELECT FOR UPDATE on the session row serializes against any concurrent SubmitAnswer (ASK-137). If an answer commits first, it's counted in the final score; if complete commits first, the answer call returns 409.

Response shape: similar to PracticeSessionResponse but without the answers array (callers can fetch them via GET /api/sessions/{id}) and with the new score_percentage field. completed_at is non-nullable on this endpoint -- a successful response always carries the freshly-set timestamp.

Request

Responses

Session completed; returns the final state with score.