{"openapi":"3.1.0","info":{"title":"MCU Speech-to-Text API","version":"1.0.0","description":"Real-time transcription for an MCU/conferencing server. Stream PCM16 over WebSocket (/ws/stt) or WebRTC (/api/webrtc); receive live transcripts, an embeddable caption page, and an automatic summary. WebSocket/SSE message protocols are documented at /docs."},"servers":[{"url":"https://mcustt.manager.click"}],"components":{"securitySchemes":{"tenantKey":{"type":"apiKey","in":"header","name":"x-tenant-key"},"adminBearer":{"type":"http","scheme":"bearer"},"sessionToken":{"type":"apiKey","in":"query","name":"t","description":"Embed/subscribe JWT (also accepted as Authorization: Bearer)."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"CreateSession":{"type":"object","properties":{"title":{"type":"string"},"sourceLang":{"type":"string","example":"en-US"},"autoDetect":{"type":"boolean","default":true}}},"CreatedSession":{"type":"object","properties":{"sessionId":{"type":"string"},"ownerSecret":{"type":"string"},"ingestToken":{"type":"string"},"ingestUrl":{"type":"string"},"embedToken":{"type":"string"},"embedUrl":{"type":"string"},"subscribeToken":{"type":"string"},"subscribeUrl":{"type":"string"},"sseUrl":{"type":"string"}}},"Summary":{"type":"object","properties":{"status":{"type":"string","enum":["ready","pending","failed","none"]},"model":{"type":"string"},"lang":{"type":"string"},"content":{"type":"object","properties":{"tldr":{"type":"string"},"decisions":{"type":"array","items":{"type":"string"}},"actionItems":{"type":"array","items":{"type":"object","properties":{"owner":{"type":"string"},"task":{"type":"string"}}}},"qa":{"type":"array","items":{"type":"string"}}}}}}}},"paths":{"/api/sessions":{"post":{"summary":"Create a session","security":[{"tenantKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSession"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedSession"}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/sessions/{id}":{"get":{"summary":"Session state","security":[{"tenantKey":[]},{"sessionToken":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"End a session","security":[{"tenantKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"ownerSecret":{"type":"string"}}}}}},"responses":{"200":{"description":"Ended"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/sessions/{id}/ingest-token":{"post":{"summary":"Rotate the single-use ingest token","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"ownerSecret":{"type":"string"}},"required":["ownerSecret"]}}}},"responses":{"200":{"description":"OK"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/sessions/{id}/embed-token":{"post":{"summary":"Mint read-only embed + subscribe tokens","security":[{"tenantKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/sessions/{id}/transcript":{"get":{"summary":"Full transcript / subtitles","security":[{"tenantKey":[]},{"sessionToken":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","schema":{"type":"string","enum":["json","srt","vtt","txt"]}}],"responses":{"200":{"description":"OK"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/sessions/{id}/summary":{"get":{"summary":"Fetch the meeting summary","security":[{"tenantKey":[]},{"sessionToken":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Summary"}}}},"202":{"description":"Pending"}}}},"/api/sessions/{id}/summarize":{"post":{"summary":"Force (re)generate the summary","security":[{"tenantKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"ownerSecret":{"type":"string"},"fromSeq":{"type":"integer"},"toSeq":{"type":"integer"}}}}}},"responses":{"200":{"description":"OK"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/transcribe-summary":{"post":{"summary":"Batch: subtitles → transcript + summary","security":[{"tenantKey":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"subtitles":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string"},"ts":{"type":"integer"},"speaker":{"type":"string"}}}},"text":{"type":"string"},"sourceLang":{"type":"string"},"want":{"type":"array","items":{"type":"string","enum":["summary","transcript"]}}}}}}},"responses":{"200":{"description":"Result (small inputs)"},"202":{"description":"Queued (large inputs) — poll /api/jobs/{id}"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/jobs/{id}":{"get":{"summary":"Poll an async batch job","security":[{"tenantKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/webrtc":{"post":{"summary":"WebRTC ingest (WHIP): POST SDP offer → SDP answer","description":"Auth: ingest token (?token=) or x-tenant-key. Body is the SDP offer (application/sdp). The answer SDP is returned; the session id + a subscribe token come back in X-Session-Id / X-Subscribe-Token headers.","security":[{"tenantKey":[]}],"requestBody":{"required":true,"content":{"application/sdp":{"schema":{"type":"string"}}}},"responses":{"201":{"description":"SDP answer","content":{"application/sdp":{"schema":{"type":"string"}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/webrtc/{id}":{"delete":{"summary":"Hang up a WebRTC ingest","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Closed"},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/admin/tenants":{"post":{"summary":"Provision a tenant + API key (admin)","security":[{"adminBearer":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"maxSessions":{"type":"integer"},"dailyMinutesCap":{"type":"integer"},"brand":{"type":"object","properties":{"brandName":{"type":"string"},"logoUrl":{"type":"string"},"accentColor":{"type":"string"}}}}}}}},"responses":{"201":{"description":"Created (apiKey shown once)"},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/healthz":{"get":{"summary":"Liveness","responses":{"200":{"description":"OK"}}}},"/readyz":{"get":{"summary":"Readiness","responses":{"200":{"description":"Ready"},"503":{"description":"Not ready"}}}},"/metrics":{"get":{"summary":"Prometheus metrics","security":[{"adminBearer":[]}],"responses":{"200":{"description":"OK"}}}}}}