Camlin Speech API
Speech-to-Text
Recognize Australian English WAV recordings, apply tenant lexicons, and receive JSON transcripts with confidence and word timing.
Endpoints
POST/api/v1/asr/recognize
GET/api/v1/asr/healthz
GET/api/v1/asr/lexicon
GET/api/v1/asr/lexicon/{tenant}
PUT/api/v1/asr/lexicon/{tenant}
DELETE/api/v1/asr/lexicon/{tenant}
Recognize Audio
Send RIFF/WAV bytes in the request body. Mono 16 kHz PCM is preferred; other WAV sample rates are accepted when the service can decode them.
| Header | Required | Description |
|---|---|---|
Content-Type: audio/wav | Recommended | Identifies the body as WAV audio. |
x-camlin-asr-language | No | Language hint. Use en-AU unless directed otherwise. |
x-camlin-asr-model | No | Recognition profile. camlin-au is the production default. |
x-camlin-tenant-id | No | Applies a tenant lexicon for names, agencies, places, and domain vocabulary. |
x-camlin-asr-backend | No | Operational override. Omit for normal production traffic. |
bash
curl -X POST "$CAMLIN_SPEECH_URL/api/v1/asr/recognize" -H "Content-Type: audio/wav" -H "x-camlin-asr-language: en-AU" -H "x-camlin-tenant-id: acme-au" --data-binary @sample.wavResponse Schema
json
{
"text": "good morning, thanks for calling Camlin",
"confidence": 0.93,
"duration_s": 2.18,
"backend": "gpu",
"model": "camlin-au",
"asr_model": "camlin-au",
"words": [
{ "word": "good", "start": 0.12, "end": 0.38, "confidence": 0.96 }
]
}| Field | Type | Description |
|---|---|---|
text | string | Full transcript. Empty when no speech was recognized. |
confidence | number | Overall confidence in the range 0..1 when available. |
duration_s | number | Audio duration in seconds. |
backend | string | Operational route used by the service. Do not branch user logic on it. |
model | string | Runtime diagnostic identifier. |
asr_model | string | Recognition profile requested or selected by default. |
words | array | Optional word-level timing and confidence entries. |
Errors
| Status | Meaning | Typical Fix |
|---|---|---|
400 | Empty body, invalid WAV, unknown profile, or invalid override. | Re-encode to WAV and use a supported profile. |
413 | Request too large. | Split long recordings before submitting. |
503 | Requested route unavailable. | Retry with default routing or fall back to queued processing. |
500 | Recognition failed unexpectedly. | Retry once, then capture request context for support. |
Tenant Lexicons
Lexicons improve recognition of names and vocabulary without changing client code. Create one once, then include x-camlin-tenant-id on recognition calls.
json
{
"tenant_id": "acme-au",
"names": ["Sione Tuilagi", "Aanya Reddy", "Hayden Vu"],
"context_words": ["Centrelink", "NDIS", "BPAY"],
"pronunciations": { "Tuilagi": "too-ee-LAH-ngee" },
"boost": 5.0
}bash
curl -X PUT "$CAMLIN_SPEECH_URL/api/v1/asr/lexicon/acme-au" -H "Content-Type: application/json" -d '{"names":["Sione Tuilagi","Aanya Reddy"],"context_words":["NDIS"]}'Implementation Recipe
javascript
export async function recognizeWav(wavBuffer, { tenantId } = {}) {
const headers = {
"content-type": "audio/wav",
"x-camlin-asr-language": "en-AU",
};
if (tenantId) headers["x-camlin-tenant-id"] = tenantId;
const res = await fetch(`${process.env.CAMLIN_SPEECH_URL}/api/v1/asr/recognize`, {
method: "POST",
headers,
body: wavBuffer,
});
if (!res.ok) throw new Error(`recognize failed: HTTP ${res.status}`);
return res.json();
}Operational Notes
- Production callers should omit backend overrides and let the service route to the fastest healthy path with CPU fallback.
camlin-auis the customer-facing default recognition profile.- Lexicon data can contain customer information; keep exports out of source control and support tickets unless approved.