Skip to content

POST /exercises/evaluate

Evaluates a user’s answer to an exercise. Returns score 0-10, result and feedback.

Body Fields

FieldTypeRequiredDescription
exerciseIdstringYesExercise identifier (max 128 chars)
areastringYeslistening, reading, writing, vocabulary, grammar
typestringYesSee types table
answerstringYesUser’s answer (max 2000 chars)
correctAnswerstring or string[]ConditionalRequired for multiple_choice and fill_blank. Optional for open_answer.
contentobjectConditionalRequired for drag_and_drop, match, word_search, crossword. Returns 400 if missing.
difficultynumberNoDifficulty level 1-5

Supported Types

typeStrategyScore
multiple_choiceCase-insensitive + trim0 or 10
fill_blankCase-insensitive + trim, multiple alternatives0 or 10
completeSame as fill_blank — user writes the word0 or 10
open_answerLevenshtein >= 0.8 or minimum length0-10
drag_and_dropCorrect items / total0-10
matchCorrect pairs / total0-10
word_searchFound words / total0-10
crosswordCorrect answers / total, case-insensitive0-10

Response Structure

{
"correct": true,
"score": 10,
"feedback": "Correct!",
"metadata": {
"area": "vocabulary",
"type": "multiple_choice"
}
}

Examples by Type

multiple_choice

{
"exerciseId": "ex_001",
"area": "vocabulary",
"type": "multiple_choice",
"answer": "B",
"correctAnswer": "b"
}

“B” and “b” are equivalent (case-insensitive).

fill_blank - multiple alternatives

{
"exerciseId": "ex_002",
"area": "grammar",
"type": "fill_blank",
"answer": "goes",
"correctAnswer": ["went", "go", "goes"]
}

complete

Identical to fill_blank. Use when the exercise asks the user to write a word in a blank space within a text.

{
"exerciseId": "ex_002b",
"area": "vocabulary",
"type": "complete",
"answer": "She",
"correctAnswer": "She"
}

Accepts correctAnswer as string or array of alternatives.

open_answer

{
"exerciseId": "ex_003",
"area": "writing",
"type": "open_answer",
"answer": "The cat is sleeping on the couch",
"correctAnswer": "The cat sleeps on the sofa"
}

Feedback by score: "Good answer!" (>= 0.8), "Your answer is partially correct." (0.5-0.8), "Incorrect. Review the topic and try again." (< 0.5).

drag_and_drop

answer = JSON.stringify({ item_id: zone_id })

{
"exerciseId": "ex_004",
"area": "vocabulary",
"type": "drag_and_drop",
"answer": "{\"1\":\"fruit\",\"2\":\"vegetable\"}",
"content": {
"items": [
{ "id": "1", "text": "Apple", "correctZoneId": "fruit" },
{ "id": "2", "text": "Carrot", "correctZoneId": "vegetable" }
],
"zones": [
{ "id": "fruit", "label": "Fruits" },
{ "id": "vegetable", "label": "Vegetables" }
]
}
}

match

answer = JSON.stringify({ left: right })

{
"exerciseId": "ex_005",
"area": "vocabulary",
"type": "match",
"answer": "{\"Dog\":\"A loyal pet\",\"Cat\":\"A small animal\"}",
"content": {
"pairs": [
{ "left": "Dog", "right": "A loyal pet" },
{ "left": "Cat", "right": "A small animal" }
]
}
}

answer = JSON.stringify({ found: string[] })

{
"exerciseId": "ex_006",
"area": "vocabulary",
"type": "word_search",
"answer": "{\"found\":[\"CAT\",\"DOG\"]}",
"content": {
"words": ["CAT", "DOG", "BIRD"]
}
}

content.words accepts string[] or { word, clue }[].

crossword

answer = JSON.stringify({ "clue_number": "answer" }) - keys are 1-based clue numbers.

{
"exerciseId": "ex_007",
"area": "vocabulary",
"type": "crossword",
"answer": "{\"1\":\"cat\",\"2\":\"dog\",\"3\":\"act\"}",
"content": {
"words": [
{ "answer": "CAT", "clue": { "type": "TEXT", "value": "A small animal" } },
{ "answer": "DOG", "clue": { "type": "TEXT", "value": "A loyal pet" } },
{ "answer": "ACT", "clue": { "type": "TEXT", "value": "To do something" } }
]
}
}

Comparison is case-insensitive: “cat” === “CAT”.