Skip to main content

Developer API

The SATE Developer API lets you build on the same speech pipeline that powers SATE: send audio, get back a transcript and a speech report.

Public APIAPI-key authasync jobstranscript + report
Start here

Portal — request access, create keys, view usage: https://developers-sate.long-cao.dev Full API reference (endpoints, examples, a complete client): https://developers-sate.long-cao.dev/docs API base URL: https://api-sate.long-cao.dev

How it relates to the rest of SATE

This is not the Device API. They are separate services with separate audiences, and it is worth being precise about which one you want:

Device APIDeveloper API
Who calls itSATE recorders, the SATE apps, fleet operatorsAny third-party application
AuthDevice key or a signed-in SATE userAn API key you create in the portal
Concerned withDevices, patients, clinical sessions, firmwareAudio in, transcript and report out
AccessInternal to the SATE productOpen to approved developers

The Developer API shares no data with the clinical app — by design, not by omission. There is no patient, no clinician, no device, and no SATE account anywhere in it. The only thing the two have in common is the AI transcription service underneath, and even that is reached through a priority gate, so a developer's batch can never make a clinician's recording wait.

Getting access

  1. Register in the portal. New accounts land as pending until an administrator approves them.
  2. Create an API key. The key is shown once, at creation — only a hash is stored, so a lost key must be revoked and replaced, never recovered.
  3. Send every request with it:
Authorization: Bearer sate_live_…

Submitting audio

Jobs are asynchronous: you submit audio, get a job id back immediately, and collect the result when it settles. Transcription takes far longer than any sensible HTTP request, so the API never makes you hold a connection open waiting for it.

curl -X POST https://api-sate.long-cao.dev/v1/jobs \
-H "Authorization: Bearer sate_live_…" \
-F audio=@sample.wav \
-F view=full

Then either poll GET /v1/jobs/{id}, or pass a webhook_url and be told when it settles. The webhook payload deliberately carries no result — you fetch that over the authenticated API — so a leaked or guessed webhook URL reveals nothing.

Scopes and views

A key carries scopes; a view is the shape of the result you ask for. The AI runs once regardless of which view you request, so widening a key's scopes later retroactively unlocks richer views of jobs that were already processed.

ViewScope requiredWhat you get
transcripttranscript:readSpeaker-attributed segments, per-word timings, plain text
reportreport:readCounts and metrics only — no words at all
fullanyEverything your scopes allow; anything withheld is named in omitted
Asking for more than you hold is not an error

A report-only key requesting view=full gets its report plus "omitted": ["transcript","annotations"] — so you always learn what was withheld and why, instead of a bare 403. Use the section endpoints (/v1/jobs/{id}/transcript) when you want a hard failure on a missing scope.

What the report contains

The report is computed by the same code as the first-party clinical product, so your numbers match SATE's: annotation counts (pause, filler, repetition, mispronunciation, morpheme, morpheme-omission, revision, utterance-error), plus NTW, NDW, MLUw, MLUm, speaking rate, and annotation rate.

Endpoints at a glance

EndpointPurpose
POST /v1/jobsSubmit audio (multipart, or raw bytes)
GET /v1/jobs/{id}Read a result in the requested view
GET /v1/jobs/{id}/transcript · /annotations · /reportOne section, hard 403 without the scope
GET /v1/jobsYour recent jobs
DELETE /v1/jobs/{id}Delete a job and its result now
GET /v1/usageYour consumption
GET /v1/meWhat this key can do

Full request and response shapes, the report field reference, and a complete working client are in the API reference.

Limits and retention

LimitBehaviour
RatePer key, per minute. Over it: 429 with retry_after_seconds
Audio quotaMonthly or lifetime, depending on your account. Over it: 402
Upload size50 MB per file (~26 min of 16 kHz mono WAV). Over it: 413
RetentionResults deleted after 30 days. Uploaded audio is deleted the moment the job finishes

Errors

Every failure carries a stable machine-readable code. Build retry logic on the code, not the message — messages are written for humans and may change.

{ "error": { "code": "quota_exceeded", "message": "Monthly quota of 120 audio minutes reached." } }
CodeStatusMeaning
unauthorized401Missing or invalid key
key_revoked401The key was revoked in the portal
account_inactive403The developer account is not active
api_locked403An administrator locked API access; the message says why
insufficient_scope403The key lacks the scope for that section
quota_exceeded402Audio quota reached
rate_limited429Too many requests this minute
audio_too_large413File over the size limit