WordloopWordloop
WorkDeliveredLive CaptureTechnical DesignContractsML

ML NDJSON Stream API

HTTP streaming API and NDJSON events for the ML service.

ML HTTP Streaming API

The ML service exposes a bidirectional HTTP streaming endpoint. Core opens the connection on StartRecordingCommand and holds it open for the duration of the session.

POST /streaming/sessions

Creates a streaming session. The HTTP response body remains open.

AuthserviceAuth (Core → ML, mTLS service token)
Request Content-Typeapplication/json
Body{ meeting_id, transcription_id, audio_config }
Response201 Created — initial JSON { session_id } header line, then Content-Type: application/x-ndjson streaming body
Errors409 a session for this meeting_id already exists; 503 AssemblyAI unavailable

POST /streaming/sessions/{session_id}/audio

Delivers a binary audio chunk to the active session.

AuthserviceAuth
Request Content-Typeapplication/octet-stream
BodyRaw binary audio chunk
Response204 No Content
Errors404 session not found; 410 session has been terminated

DELETE /streaming/sessions/{session_id}

Terminates the session cleanly. ML drains the AssemblyAI buffer and closes the streaming response.

AuthserviceAuth
Response204 No Content
Errors404 session not found

Streaming Response Envelope

ML writes NDJSON events to the open response stream. Each newline-terminated line is one event.

{ "type": "transcript_segment", "data": { "segment_id": "<uuid>", "speaker_label": "Speaker A", "text": "Hello world", "start_ms": 1200, "end_ms": 2400, "confidence": 0.96, "is_final": true } }
{ "type": "feature_vector",     "data": { "segment_id": "<uuid>", "vector": [0.12, -0.34, 0.77] } }
{ "type": "speaker_match",      "data": { "segment_id": "<uuid>", "person_id": "<uuid>", "score": 0.91 } }
{ "type": "talking_point",      "data": { "id": "<uuid>", "content": "Discussed Q3 roadmap", "is_final": false, "segments": ["<uuid>"] } }
{ "type": "task",               "data": { "id": "<uuid>", "content": "Follow up with design team", "source": "system" } }

Core routes each event type to the appropriate handler:

Event typeCore action
transcript_segmentBroadcast TranscriptSegmentEvent on WS → async DB insert
feature_vectorAsync DB update on segment (no WS broadcast)
speaker_matchAsync DB update → broadcast EntityChanged { entity: transcript_segment }
talking_pointBroadcast TalkingPointEvent on WS → async DB upsert
taskBroadcast TaskEvent on WS → async DB insert

On this page