Mandarin learners do not mispronounce "words" — they mispronounce a tone, an initial or a final. A phoneme-level English-style scorer hides that: it tells you the syllable shì scored 62 and leaves your app to guess why. TonePerfect splits every syllable into its three parts and reports each one separately, so your feedback can say "you said a 2nd tone; this is a 4th" or "you said s; this needs the retroflex sh".
Tone sandhi is understood
When a 3rd tone precedes another 3rd tone, native speakers say the first as a 2nd tone (nǐ hǎo → ní hǎo). TonePerfect expects that change, so a learner who applies sandhi correctly is not told they used the wrong tone. Read the detail in How to handle tone sandhi in pronunciation scoring.
Decisions per component
With task=connected_speech, each initial, final and tone carries a decision: review when the evidence for an error is strong, uncertain when it is not, and no_correction otherwise. Display grades and decisions are separate on purpose: a score can be modest while the decision is "leave it" — for instance a slightly off-centre vowel that no teacher would stop the class for.
Learner errors this pack is built to show
- Dental for retroflex — s where sh was expected, z for zh, c for ch — reported as an initial with expected vs heard values.
- Aspiration contrasts — b / p, d / t, g / k — the most common substitution for speakers of languages without the contrast.
- The -n / -ng ending pair (in / ing, an / ang).
- Tone shape errors: a 4th tone that rises, a 3rd tone with no dip, a 2nd tone that stays flat — each named as expected tone vs heard tone.
What it does not do
The Mandarin pack scores scripted practice only — you supply the characters. It reports pronunciation, initial, final and tone dimensions; fluency and rhythm are not scored for Mandarin today. Known weak spots we are working on: the neutral tone is not reliably distinguished from a 1st tone, the ü / i contrast is the least sensitive final, and a retroflex produced where a dental was expected (sh for s) is caught far less often than the reverse. The pack is labelled experimental in /v1/capabilities, which means we are still growing the native and learner calibration data behind it; the response's model_version tells you exactly which model scored a request.
Example request
Reference text: 你好世界. Send the recording, the text and the locale; nothing else is required.
curl https://api.toneperfect.app/v1/assess \
-H "Authorization: Bearer $TONEPERFECT_API_KEY" \
-H "Idempotency-Key: lesson-42-attempt-1" \
-F "audio=@take.wav" \
-F "text=你好世界" \
-F "language=zh-CN" \
-F "task=connected_speech"What comes back
The same structure as every other language: sentence-level scores, a words[] array with timestamps and, under each word, phones[] with expected and heard values. Abbreviated to the one flagged word:
{
"language": "zh",
"locale": "zh-CN",
"task": "connected_speech",
"status": "completed",
"assessable": true,
"model_version": "mandarin-human-v2-…",
"scores": {
"overall": 86,
"pronunciation": 90,
"initial": 91,
"final": 89,
"tone": 80
},
"words": [
{
"word": "世",
"pinyin": "shi4",
"score": 68,
"start_ms": 1020,
"end_ms": 1400,
"phones": [
{
"dimension": "initial",
"expected": "sh",
"heard": "s",
"score": 78,
"decision": "uncertain"
},
{
"dimension": "final",
"expected": "i",
"heard": "i",
"score": 83,
"decision": "no_correction"
},
{
"dimension": "tone",
"expected": 4,
"heard": 2,
"score": 62,
"decision": "review"
}
]
}
],
"billing": {
"credits": 1,
"balance_credits": 2499
}
}Reference text goes in as text: Chinese characters (simplified or traditional) or numbered pinyin such as ni3 hao3. Send characters for connected speech so the correction policy can apply. See the response reference for every field.