Prep Eval API

Every speech- and language-scoring engine behind one host and one credential: https://eval.flowb.ai. Each engine is a lane with its own path prefix and its own native request format — the gateway adds shared authentication and, for the team-hosted graders, holds their upstream credentials so you never handle them.

LaneEngineWhat it scores
/pronviin-processVietnamese pronunciation: segmental CTC-GOP + speaker-relative F0 tone, per syllable
/shadowscorein-processHow closely a take MATCHES a model recording: intonation, rhythm, per-word forced-alignment GOP (en)
/englishproxy → Prep VR MarkingIELTS speaking & writing band grading (async: enqueue, then poll)
/chineseproxy → CPAChinese scripted-speech analysis: per-character tone + segmental pronunciation

Authentication

Send your eval key on every request:

X-API-Key: <your-eval-key>

Authorization: Bearer <key> is accepted in place of X-API-Key. Failure is 401 {"detail":"missing or invalid credentials"}. Only /health, the lane healths and this page are open.

Optionally send X-Sender-Id: <your-product-id> on the /english lane — it is forwarded upstream as your identity with the marking team. Without it the gateway's default identity is used.

Health

GET /health
→ {"ok": true, "version": "1.0.0", "lanes": ["pronvi","shadowscore","english","chinese"]}

Lane healths: GET /pronvi/health, GET /shadowscore/health (both open, no key).

/pronvi — Vietnamese pronunciation

Segmental correctness (wav2vec2 CTC-GOP) + tone correctness (speaker-relative F0 against per-dialect calibrated profiles), combined into a 0–9 band. Audio is WAV (any sample rate; resampled to 16 kHz mono).

POST /pronvi/score — one syllable

Multipart form:

FieldTypeMeaning
audiofile (WAV)the learner's take
targettextthe target syllable, e.g.
speaker_mediannumber, optionalthe learner's running median F0 (Hz); omit → within-syllable tone only
dialecttext, default northnorth or south (south merges hỏi≡ngã)
→ {"target":"má","target_tone":"sac","dialect":"north","band":8.5,"verdict":"pass","percent":94,
   "segmental":{"ok":true,"gop":…,"ratio":…,"transcript":"ma","base_match":true},
   "tone":{"target":"sac","pred":"sac","conf":0.91,"ok":true},
   "speaker_median":112.4, "tone_flags":["má"]?}

Verdicts: pass / almost / retry. tone_flags appears only when the tone missed.

POST /pronvi/score_utterance — a whole turn

Same form fields as /score with target = the full text. Returns utterance-level segmental plus per-syllable tone rows (syllables) and tone_flags.

POST /pronvi/baseline — native-tongue F0 gauge

multipart: audio=<wav>
→ {"median":110.2,"floor":86.1,"ceiling":141.0}   (422 if no voiced pitch)

POST /pronvi/detect — dialect detection

Form fields audio, target, optional speaker_median. Ranks calibrated dialects by how well the take's tone fits; accumulate across several productions before trusting it.

/shadowscore — shadowing match

Scores how closely a learner's take matches a fixed model recording (scripted repeat): utterance intonation + rhythm always (Praat F0, language-agnostic), plus per-word pronunciation / rhythm / intonation via CTC forced alignment (English). Audio is passed as fetchable public URLs.

POST /shadowscore/shadowing/{lang}

{
  "model_url":   "https://…/model.wav",    // "" → GOP-only mode (drill pronunciation read)
  "learner_url": "https://…/take.wav",
  "script":      "the text that was read",  // enables per-word scoring (en)
  "linking":     [{…}],                     // authored linking spots — scored pass, never penalised
  "rate":        1.0,                       // tier playback rate while recording (bleed cancellation)
  "ref_clips":   [{"url":"…","start_ms":0}] // clips that PLAYED during the take (bleed cancellation)
}
→ {
  "intonation": 82, "rhythm": 76,           // 0–100, vs the model
  "pronunciation": 71,                      // omitted when the aligner can't run
  "words": [{"word":"loaf","pron":68,"rhythm":80,"intonation":77,
             "linked":false,"start":0.42,"end":0.71}, …],
  "bleed_db": 9.6,                          // present when bleed cancellation ran
  "cleaned_b64": "<16-bit WAV>"             // the voice-only take — store it over the raw take
}

Audio URLs must be publicly fetchable https — the gateway refuses private/internal destinations.

/english — IELTS speaking & writing grading

A transparent proxy to the Prep VR Marking service: same paths, same JSON, under the /english prefix. Grading is asynchronous — enqueue a session, then poll its result. Speaking answers are fetchable WAV URLs; writing answers are text.

EndpointPurpose
POST /english/api/v1/ielts/speaking/grade-testenqueue a speaking grading session
GET /english/api/v1/ielts/speaking/result/{session_id}poll a speaking result
POST /english/api/v1/ielts/speaking/grade-questiongrade a single speaking answer
POST /english/api/v1/ielts/writing/grade-testenqueue a writing grading session
GET /english/api/v1/ielts/writing/result/{session_id}poll a writing result
POST /english/api/v1/ielts/writing/grade-questiongrade a single writing answer
POST /english/api/v1/ielts/speaking/grade-test
{"meta":{"submission_skill_id":"…"},
 "responses":[{"question":{"id":1,"title":"…","part":1},"answer":"https://…/answer.wav"}]}
→ {"data":{"session_id":"…"}}

GET /english/api/v1/ielts/speaking/result/{session_id}
→ {"session_id":"…","status":3,"score":6.5,
   "result":{"score":6.5,"pronunciation":{"score":6.0},"fluency_and_coherence":{"score":7.0},
             "lexical_resource":{"score":6.5},"grammatical_range_and_accuracy":{"score":6.0}}}

Status: 1 pending · 2 in progress · 3 completed · 4 failed. Poll every ~2 s until terminal.

/chinese — Chinese pronunciation (CPA)

A transparent proxy to the team's Chinese Pronunciation Assessment. The upstream credential is injected by the gateway — send only your eval key. Synchronous multipart; audio is a fetchable URL.

POST /chinese/api/v1/scripted_speech_analysis

Form fieldMeaning
audio_urlfetchable URL of the learner's clip
scriptthe reference script the clip should match
sender_idyour product identity (e.g. tp-virtual-room)
user_idyour learner id, for the team's tracking
accent_codeoptional, e.g. zh-vi
verify_script"true"
language"chinese"
request_high_resource"false"
→ {"has_speech":true,
   "scores":{"pronunciation":87.2,"tone":78.5,"overall":83.9},
   "utterances":[{"words":[{"text":"你","pinyin":"nǐ","syllables":[…]}]}]}

Errors

StatusMeaning
401missing or invalid eval key
422malformed request (missing field, unusable audio)
4xx/5xx on /english, /chinesethe upstream grader's own status, passed through verbatim
503gateway key unconfigured (deploy-time misconfiguration)