API reference

What the ArticScore API returns

ArticScore takes a recording plus the word a child was asked to say, and returns one row per sound: a score from 0 to 100, the phoneme in ARPAbet and IPA, the millisecond span it occupied, the engine's best candidate for what was produced instead, a clinical error type, and a confidence tier. This page documents every field.

The request

One endpoint, one multipart POST. You do not send phonemes — the API derives the expected phoneme sequence from the target text and aligns it against the audio itself.

Request
POST /articscore/v1/score
Authorization: Bearer <your key>
Content-Type: multipart/form-data

audio    = <file>        # the recording
text     = "rabbit"      # the word or phrase the child was asked to say
dialect  = "en-us"       # optional; en-us is the evaluated default

The response

A child saying “rabbit” as “wabbit”. The second phoneme is truncated for length; a real response contains a row for every sound in the word.

Response
{
  "engine": "articscore",
  "model": "ft-epoch3",
  "text": "rabbit",
  "overall_score": 61.4,
  "words": [
    {
      "word": "rabbit",
      "score": 61.4,
      "phonemes": [
        {
          "phone": "R",
          "phone_ipa": "ɹ",
          "score": 41.2,
          "sound_most_like": "W",
          "sound_most_like_ipa": "w",
          "extent": [120, 260],
          "flagged": true,
          "error_type": "substitution",
          "tier": "flag"
        },
        {
          "phone": "AE",
          "phone_ipa": "æ",
          "score": 88.1,
          "sound_most_like": null,
          "sound_most_like_ipa": null,
          "extent": [260, 390],
          "flagged": false,
          "error_type": null,
          "tier": "clean"
        }
      ]
    }
  ],
  "timing": { "inference_s": 1.12, "total_s": 1.31 }
}

Top-level fields

FieldTypeMeaning
enginestringAlways "articscore".
modelstringThe checkpoint that produced this score. Pin it in your logs — scores are not comparable across checkpoints.
textstringThe target text you sent back, after normalisation.
overall_scorenumber 0–100Utterance-level score. Useful for a headline; not what to build therapy logic on.
words[]arrayOne entry per word in the target text.
timingobjectServer-side processing durations in seconds. Not audio timing — that lives in extent.

Phoneme fields

This is the part of the response that distinguishes a scoring API from an explanation API. The three fields to pay attention to are sound_most_like, error_type, and tier.

FieldTypeMeaning
phonestringThe expected phoneme in ARPAbet, e.g. "R", "AE", "TH".
phone_ipastringThe same phoneme in IPA, e.g. "ɹ", "æ", "θ".
scorenumber 0–100How well this phoneme was produced. Calibrated against human ratings; saturates near the top, so ranking beats thresholding.
sound_most_likestring | nullThe engine's best candidate for what was actually produced, in ARPAbet. Populated whenever the phone is flagged.
sound_most_like_ipastring | nullThe same candidate in IPA.
extent[number, number]Start and end of this phoneme in the audio, in milliseconds. Use it to highlight or replay the fragment.
flaggedbooleanWhether this phone crossed the flag threshold. A convenience over score; the threshold is documented and stable.
error_typestring | nullOne of substitution, omission, distortion, unclear. Null when the phone is not flagged.
tierstringflag, review, or clean. The confidence tier — see below. This is the field to branch product behaviour on.

The three confidence tiers

Rather than making every integrator pick their own score threshold and get it slightly wrong, the API collapses its signals into three tiers that map onto the three decisions a product actually makes.

TierMeaningWhat to do with it
flagThe engine's lowest-scoring tier — its strongest signal that something went wrong, which on our evaluation set still meant most flags were false positives.The top of a clinician's worklist. Surface it to a child as practice feedback only where being wrong is low-cost, and expect roughly two in three flags to be false positives at this tier.
reviewUncertain. The engine saw something but is not confident.Send to a clinician's queue. Do not show a child a correction based on this alone.
cleanNothing detected.Treat as 'no signal', not as 'verified correct'. See the warning below.

Error types

The error_type field uses the vocabulary a clinical note is written in, because that is what makes the output useful to a therapist rather than only to a scoring loop.

ValueMeaningHow reliably we detect it
substitutionA different phoneme was produced in place of the target.Detectable, but the weakest category — see the benchmark.
omissionThe target phoneme was not produced at all.The best-handled category. A deleted sound leaves an unambiguous gap.
distortionThe target was attempted but produced incorrectly, without becoming another phoneme.Largely undetectable. Structural limitation — see below.
unclearSomething is wrong but the engine cannot characterise it.Route to a human.

Building on the output

Three patterns cover most of what teams actually do with this response.

Immediate practice feedback

Branch on tier === "flag" and use sound_most_liketo phrase the feedback concretely — “the R in rabbit came out as a W” instead of “try again”. Use extent to replay just that fragment. Keep review silent in a child-facing loop: at these precision levels an uncertain flag shown to a child is usually wrong, and being told you are wrong when you were right is the fastest way to lose a young user.

A clinician worklist

Rank recordings by score rather than thresholding them. In our clinical evaluation, reviewing only the worst-ranked productions recovered a disproportionate share of the clinician's error list — far more than reviewing the same number at random would have. That is, in our view, the highest-value thing you can build on this API today.

A rendering of all three

The ArticScore overview shows this exact response rendered three ways — a child-facing game screen, a practice summary, and a clinician's review row — so you can see which fields carry which part of each experience.

Progress tracking over time

Aggregate per-phoneme scores by sound and by word position across sessions. Because the API scores every phone in context, you can show that a child's initial /s/ improved while their /s/ in clusters did not — which is the shape of information an IEP goal is written in. Log the model field alongside the scores so a checkpoint change does not appear in your charts as clinical progress.

API reference questions

What does the ArticScore API return?
A per-phoneme breakdown of the recording. For every sound in the target word you get a score from 0 to 100, the phoneme in both ARPAbet and IPA, the millisecond span it occupied in the audio, whether it was flagged, the engine's best candidate for what was produced instead, an error type, and a confidence tier of flag, review, or clean.
What audio format does ArticScore accept?
Standard uncompressed WAV at 16 kHz mono is the format the engine is evaluated on and the one that will behave most predictably. Common compressed formats are accepted and resampled. Recording quality matters more than format: a close, quiet microphone materially reduces false flags, and background noise is the largest controllable source of scoring error in real deployments.
Do I need to send phonemes, or just the word?
Just the word or phrase. The API converts it to the expected phoneme sequence using its pronunciation dictionary and performs forced alignment internally. You never handle phonemes on the way in — only on the way out.
What does the 'tier' field mean and why not just use the score?
The tier collapses the score plus the engine's secondary signals into the three decisions a product actually has to make: show it to the child, send it to a human, or do nothing. Branching on tier rather than on a raw score threshold means your product behaviour does not silently change if the score calibration is updated in a later model version.
Does a 'clean' tier mean the sound was definitely correct?
No, and this is the most important thing to get right when building on the API. Clean means the engine detected nothing, not that nothing was there. In our evaluation on recordings of children with speech sound disorders, the clean bucket still contained real errors a clinician caught. Never present clean as verified or cleared.
Is the score comparable between model versions?
No. Scores are calibrated per checkpoint, and swapping engines or versions without recalibrating would silently move every child's pass rate. The response includes a model field for exactly this reason: log it, and treat a change in that field as a reason to re-check your thresholds.

Get the current specification

ArticScore is in limited early access, rolled out case by case. Tell us your use case and expected volume and we will come back to you.

Request access