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 · pinyin only
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:

JSON · 200 OK (real response, trimmed)
{
  "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

FieldPer syllable, for the initial, the final and the tone
expectedWhat the reference requires: an initial such as sh, a final such as ang, or a tone number 1–5 (5 = neutral).
heardThe engine’s estimate of what was said, in the same units.
score0–100 display grade against native-speaker references.
decisionreview, uncertain or no_correction: whether your app should correct this component.
agrees_with_prompt, confidence, alternativesIn syllables[].components: whether heard equals expected, a confidence label, and the ranked candidates with probabilities.
start_ms, end_msThe 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): write ni3.
  • Pinyin in text: the text field is for characters in Mandarin; use pinyin for 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.