Sending pinyin
Put the reading in the pinyin field: numbered tones, one syllable per space, for example ni3 hao3. Use v (or ü) for ü, as in lv4, and 5 or 0 for the neutral tone. Up to 100 syllables. Tone marks (nǐ) are not accepted in pinyin.
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 "pinyin=ni3 hao3" \
-F "language=zh-CN" \
-F "task=isolated_word"You can also send characters and pinyin together, with exactly one syllable per character, to fix the reading of a character with several pronunciations (还 hai2 or huan2). If the counts differ, the request is rejected with invalid_assessment and nothing is charged.
A real response
The same 你好 clip sent as pinyin=ni3 hao3 with no characters. Each words[] entry is one syllable, named by its pinyin:
{
"id": "req_example",
"language": "zh",
"locale": "zh-CN",
"model_version": "mandarin-hubert-baseline-85741cdf3967",
"task": "isolated_word",
"status": "completed",
"assessable": true,
"reason": null,
"scores": {
"overall": 99.6,
"pronunciation": 97.8,
"initial": 98.2,
"final": 97.3,
"tone": 98,
"fluency": null,
"rhythm": null,
"integrity": null
},
"words": [
{
"word": "ni3",
"pinyin": "ni3",
"score": 99.3,
"start_ms": 0,
"end_ms": 155,
"phones": [
{
"dimension": "initial",
"expected": "n",
"heard": "n",
"score": 96.6,
"decision": "no_correction",
"flagged": false
},
{
"dimension": "final",
"expected": "i",
"heard": "i",
"score": 96.1,
"decision": "no_correction",
"flagged": false
},
{
"dimension": "tone",
"expected": 3,
"heard": 2,
"score": 99.7,
"decision": "no_correction",
"flagged": false
}
]
},
{
"word": "hao3",
"pinyin": "hao3",
"score": 99.5,
"start_ms": 155,
"end_ms": 424,
"phones": [
{
"dimension": "initial",
"expected": "h",
"heard": "h",
"score": 99.8,
"decision": "no_correction",
"flagged": false
},
{
"dimension": "final",
"expected": "ao",
"heard": "ao",
"score": 98.5,
"decision": "no_correction",
"flagged": false
},
{
"dimension": "tone",
"expected": 3,
"heard": 3,
"score": 96.3,
"decision": "no_correction",
"flagged": false
}
]
}
],
"heard": {
"syllables": [
{
"initial": "n",
"final": "i",
"tone": 2
},
{
"initial": "h",
"final": "ao",
"tone": 3
}
]
},
"duration_seconds": 0.54,
"billing": {
"credits": 1,
"balance_credits": 2499
}
}Note the model_version: pinyin-only requests are scored by the baseline Mandarin model, without the human-judgment layer that characters enable. Grades and expected-vs-heard values are the same kind; for sentence practice with component correction decisions, send the characters too, with task=connected_speech.
What comes back per syllable
| Field | Per syllable, for the initial, the final and the tone |
|---|---|
expected | What the reference requires: an initial such as sh, a final such as ang, or a tone number 1–5 (5 = neutral). |
heard | The engine’s estimate of what was said, in the same units. |
score | 0–100 display grade against native-speaker references. |
decision | review, uncertain or no_correction: whether your app should correct this component. |
agrees_with_prompt, confidence, alternatives | In syllables[].components: whether heard equals expected, a confidence label, and the ranked candidates with probabilities. |
start_ms, end_ms | The syllable’s position in the recording, for replaying exactly that slice. |
Initials and finals use pinyin spelling (zh, ü, iang), tones are numbers, and heard.syllables[] lists what the engine estimates was said for every syllable, so you can render the learner’s own pinyin next to the target.
Common input errors
- Tone marks or missing tone numbers in
pinyin(nǐ,ni): writeni3. - Pinyin in
text: thetextfield is for characters in Mandarin; usepinyinfor pinyin. - Digits or Latin words in Chinese text: write numbers in Chinese or send the full reading as pinyin.
Known weak spots of the current Mandarin model: the neutral tone is not reliably told apart from a 1st tone, ü / i is the least sensitive final, and a retroflex said where a dental was expected (sh for s) is caught far less often than the reverse. The pack is labelled experimental in /v1/capabilities, and every response names the model_version that scored it. More on the Mandarin pack page and the methodology.