ipa.raymati.com

Quickstart

POST /v1/tutor with Content-Type: application/json. An IPA request does not need the recognizer. ipa wins if you also send audio.

Audio is JSON. audio_base64 is a WAV of at most 256 KiB decoded. A larger clip calls the MCP tool create_upload, PUTs the wav, and passes audio_url. Client setup is on Install.

The path is /v1. The success field api is tutor-v1. Package 0.2.0 names the build, not the score contract. New fields may appear without a new path. A break in the score contract would be /v2.

curl

curl -sS https://ipa.raymati.com/v1/tutor \
  -H 'content-type: application/json' \
  -d '{"target":"λόγος","ipa":"l o g o s","scheme":"koine-greek","different_word":false,"calibrate":true}'

Python

The standard library is enough.

import json
from urllib.request import Request, urlopen

body = json.loads(r"""{
  "target": "λόγος",
  "ipa": "l o g o s",
  "scheme": "koine-greek",
  "different_word": false,
  "calibrate": true
}""")
request = Request(
    "https://ipa.raymati.com/v1/tutor",
    data=json.dumps(body).encode(),
    headers={"content-type": "application/json"},
)
with urlopen(request) as response:
    score = json.load(response)
print(score["proximity"])

JavaScript

const body = {
  "target": "λόγος",
  "ipa": "l o g o s",
  "scheme": "koine-greek",
  "different_word": false,
  "calibrate": true
};
const response = await fetch("https://ipa.raymati.com/v1/tutor", {
  method: "POST",
  headers: {"content-type": "application/json"},
  body: JSON.stringify(body),
});
const score = await response.json();
console.log(score.proximity);

Rust

No extra crate. The snippet shells out to curl.

fn main() {
    let body = r#"{"target":"λόγος","ipa":"l o g o s","scheme":"koine-greek","different_word":false,"calibrate":true}"#;
    let output = std::process::Command::new("curl")
        .args([
            "-sS",
            "https://ipa.raymati.com/v1/tutor",
            "-H",
            "content-type: application/json",
            "-d",
            body,
        ])
        .output()
        .expect("curl");
    println!("{}", String::from_utf8(output.stdout).expect("utf-8"));
}

What you get back

λόγος / l o g o s (example exactLogos):

The full object is the exactLogos response example in openapi.json. Other public calls:

ExampleIPAproximityreal_editsfirst learner status
exactLogosl o g o s1.00exact
stressShiftl o g ˈo s0.90exact
thetaAsSs e o s0.751close
acceptableThetatʰ e o s0.9881870acceptable_variant
verseArchee n a r x i1.00exact

Local replacement for the host: http://127.0.0.1:43117. Set IPA_TUTOR_BIND to move it.

MCP

POST /mcp speaks Streamable HTTP as one JSON object, not an SSE stream.

curl -sS https://ipa.raymati.com/mcp \
  -H 'content-type: application/json' \
  -H 'MCP-Protocol-Version: 2025-03-26' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"score","arguments":{"target":"λόγος","ipa":"l o g o s","scheme":"koine-greek","different_word":false,"calibrate":true}}}'

A missing MCP-Protocol-Version header is treated as 2025-03-26. 2026-07-28 is also accepted. GET /mcp is 405.

HTML guides honor Accept: text/markdown (draft-consolidated-content-01). curl -H 'Accept: text/markdown' https://ipa.raymati.com/docs/quickstart returns this page. The .md URL does the same without negotiation.