Files
noteflow/noteflow-api-spec.json
Travis Vasceannie 3ea953c677 Add API specification and remove deprecated client files
- Introduced a new API specification file `noteflow-api-spec.json` detailing the real-time audio-to-text functionality.
- Removed obsolete client configuration files, including `.prettierrc.json`, `biome.json`, `index.html`, and various TypeScript configuration files.
- Deleted unused components and tests from the client directory to streamline the project structure.
2025-12-23 10:20:45 +00:00

538 lines
26 KiB
JSON

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "NoteFlow API",
"version": "1.0.0",
"description": "Intelligent meeting notetaker API - real-time audio transcription, meeting management, and AI-powered summarization",
"protocol": "gRPC",
"package": "noteflow"
},
"service": {
"name": "NoteFlowService",
"description": "Main service providing real-time ASR streaming and meeting management"
},
"endpoints": {
"StreamTranscription": {
"type": "bidirectional_streaming",
"description": "Bidirectional streaming: client sends audio chunks, server returns transcripts in real-time",
"request": {
"type": "stream",
"message": "AudioChunk"
},
"response": {
"type": "stream",
"message": "TranscriptUpdate"
}
},
"CreateMeeting": {
"type": "unary",
"description": "Create a new meeting session",
"request": "CreateMeetingRequest",
"response": "Meeting"
},
"StopMeeting": {
"type": "unary",
"description": "Stop an active meeting recording",
"request": "StopMeetingRequest",
"response": "Meeting"
},
"ListMeetings": {
"type": "unary",
"description": "List meetings with optional filtering and pagination",
"request": "ListMeetingsRequest",
"response": "ListMeetingsResponse"
},
"GetMeeting": {
"type": "unary",
"description": "Get a specific meeting by ID with optional transcript and summary",
"request": "GetMeetingRequest",
"response": "Meeting"
},
"DeleteMeeting": {
"type": "unary",
"description": "Delete a meeting and all associated data",
"request": "DeleteMeetingRequest",
"response": "DeleteMeetingResponse"
},
"GenerateSummary": {
"type": "unary",
"description": "Generate an AI-powered summary for a meeting",
"request": "GenerateSummaryRequest",
"response": "Summary"
},
"AddAnnotation": {
"type": "unary",
"description": "Add a user annotation to a meeting (action item, decision, note, or risk)",
"request": "AddAnnotationRequest",
"response": "Annotation"
},
"GetAnnotation": {
"type": "unary",
"description": "Get a specific annotation by ID",
"request": "GetAnnotationRequest",
"response": "Annotation"
},
"ListAnnotations": {
"type": "unary",
"description": "List all annotations for a meeting with optional time range filter",
"request": "ListAnnotationsRequest",
"response": "ListAnnotationsResponse"
},
"UpdateAnnotation": {
"type": "unary",
"description": "Update an existing annotation",
"request": "UpdateAnnotationRequest",
"response": "Annotation"
},
"DeleteAnnotation": {
"type": "unary",
"description": "Delete an annotation",
"request": "DeleteAnnotationRequest",
"response": "DeleteAnnotationResponse"
},
"ExportTranscript": {
"type": "unary",
"description": "Export meeting transcript to Markdown or HTML format",
"request": "ExportTranscriptRequest",
"response": "ExportTranscriptResponse"
},
"RefineSpeakerDiarization": {
"type": "unary",
"description": "Run offline speaker diarization to improve speaker labels (background job)",
"request": "RefineSpeakerDiarizationRequest",
"response": "RefineSpeakerDiarizationResponse"
},
"RenameSpeaker": {
"type": "unary",
"description": "Rename a speaker ID to a human-readable name",
"request": "RenameSpeakerRequest",
"response": "RenameSpeakerResponse"
},
"GetDiarizationJobStatus": {
"type": "unary",
"description": "Check status of a background diarization job",
"request": "GetDiarizationJobStatusRequest",
"response": "DiarizationJobStatus"
},
"GetServerInfo": {
"type": "unary",
"description": "Get server health and capabilities information",
"request": "ServerInfoRequest",
"response": "ServerInfo"
}
},
"enums": {
"UpdateType": {
"description": "Type of transcript update",
"values": {
"UPDATE_TYPE_UNSPECIFIED": { "value": 0, "description": "Default/unspecified" },
"UPDATE_TYPE_PARTIAL": { "value": 1, "description": "Tentative transcript, may change" },
"UPDATE_TYPE_FINAL": { "value": 2, "description": "Confirmed segment" },
"UPDATE_TYPE_VAD_START": { "value": 3, "description": "Voice activity started" },
"UPDATE_TYPE_VAD_END": { "value": 4, "description": "Voice activity ended" }
}
},
"MeetingState": {
"description": "Current state of a meeting",
"values": {
"MEETING_STATE_UNSPECIFIED": { "value": 0, "description": "Default/unspecified" },
"MEETING_STATE_CREATED": { "value": 1, "description": "Created but not started" },
"MEETING_STATE_RECORDING": { "value": 2, "description": "Actively recording audio" },
"MEETING_STATE_STOPPED": { "value": 3, "description": "Recording stopped, processing may continue" },
"MEETING_STATE_COMPLETED": { "value": 4, "description": "All processing complete" },
"MEETING_STATE_ERROR": { "value": 5, "description": "Error occurred" }
}
},
"SortOrder": {
"description": "Sort order for listing meetings",
"values": {
"SORT_ORDER_UNSPECIFIED": { "value": 0, "description": "Default (newest first)" },
"SORT_ORDER_CREATED_DESC": { "value": 1, "description": "Newest first" },
"SORT_ORDER_CREATED_ASC": { "value": 2, "description": "Oldest first" }
}
},
"Priority": {
"description": "Priority level for action items",
"values": {
"PRIORITY_UNSPECIFIED": { "value": 0, "description": "Default/unspecified" },
"PRIORITY_LOW": { "value": 1, "description": "Low priority" },
"PRIORITY_MEDIUM": { "value": 2, "description": "Medium priority" },
"PRIORITY_HIGH": { "value": 3, "description": "High priority" }
}
},
"AnnotationType": {
"description": "Type of user annotation",
"values": {
"ANNOTATION_TYPE_UNSPECIFIED": { "value": 0, "description": "Default/unspecified" },
"ANNOTATION_TYPE_ACTION_ITEM": { "value": 1, "description": "Action item to be done" },
"ANNOTATION_TYPE_DECISION": { "value": 2, "description": "Decision made" },
"ANNOTATION_TYPE_NOTE": { "value": 3, "description": "General note" },
"ANNOTATION_TYPE_RISK": { "value": 4, "description": "Risk or concern" }
}
},
"ExportFormat": {
"description": "Transcript export format",
"values": {
"EXPORT_FORMAT_UNSPECIFIED": { "value": 0, "description": "Default/unspecified" },
"EXPORT_FORMAT_MARKDOWN": { "value": 1, "description": "Markdown format" },
"EXPORT_FORMAT_HTML": { "value": 2, "description": "HTML format" }
}
},
"JobStatus": {
"description": "Background job status",
"values": {
"JOB_STATUS_UNSPECIFIED": { "value": 0, "description": "Default/unspecified" },
"JOB_STATUS_QUEUED": { "value": 1, "description": "Job is queued" },
"JOB_STATUS_RUNNING": { "value": 2, "description": "Job is running" },
"JOB_STATUS_COMPLETED": { "value": 3, "description": "Job completed successfully" },
"JOB_STATUS_FAILED": { "value": 4, "description": "Job failed" }
}
}
},
"messages": {
"AudioChunk": {
"description": "Audio data chunk for streaming transcription",
"fields": {
"meeting_id": { "type": "string", "required": true, "description": "Meeting ID this audio belongs to" },
"audio_data": { "type": "bytes", "required": true, "description": "Raw audio data (float32, mono, 16kHz expected)" },
"timestamp": { "type": "double", "required": false, "description": "Timestamp when audio was captured (monotonic, seconds)" },
"sample_rate": { "type": "int32", "required": false, "default": 16000, "description": "Sample rate in Hz" },
"channels": { "type": "int32", "required": false, "default": 1, "description": "Number of channels (1 for mono)" }
}
},
"TranscriptUpdate": {
"description": "Real-time transcript update from server",
"fields": {
"meeting_id": { "type": "string", "description": "Meeting ID this transcript belongs to" },
"update_type": { "type": "UpdateType", "description": "Type of update (partial, final, VAD events)" },
"partial_text": { "type": "string", "description": "For partial updates - tentative transcript text" },
"segment": { "type": "FinalSegment", "description": "For final updates - confirmed transcript segment" },
"server_timestamp": { "type": "double", "description": "Server-side processing timestamp" }
}
},
"FinalSegment": {
"description": "Confirmed transcript segment with word-level timing",
"fields": {
"segment_id": { "type": "int32", "description": "Segment ID (sequential within meeting)" },
"text": { "type": "string", "description": "Transcript text" },
"start_time": { "type": "double", "description": "Start time relative to meeting start (seconds)" },
"end_time": { "type": "double", "description": "End time relative to meeting start (seconds)" },
"words": { "type": "array", "items": "WordTiming", "description": "Word-level timestamps" },
"language": { "type": "string", "description": "Detected language code" },
"language_confidence": { "type": "float", "description": "Language detection confidence (0.0-1.0)" },
"avg_logprob": { "type": "float", "description": "Average log probability (quality indicator)" },
"no_speech_prob": { "type": "float", "description": "Probability that segment contains no speech" },
"speaker_id": { "type": "string", "description": "Speaker identification (from diarization)" },
"speaker_confidence": { "type": "float", "description": "Speaker assignment confidence (0.0-1.0)" }
}
},
"WordTiming": {
"description": "Word-level timing information",
"fields": {
"word": { "type": "string", "description": "The word text" },
"start_time": { "type": "double", "description": "Start time in seconds" },
"end_time": { "type": "double", "description": "End time in seconds" },
"probability": { "type": "float", "description": "Recognition confidence (0.0-1.0)" }
}
},
"Meeting": {
"description": "Complete meeting record with transcript and summary",
"fields": {
"id": { "type": "string", "description": "Unique meeting identifier (UUID)" },
"title": { "type": "string", "description": "User-provided or auto-generated title" },
"state": { "type": "MeetingState", "description": "Current meeting state" },
"created_at": { "type": "double", "description": "Creation timestamp (Unix epoch seconds)" },
"started_at": { "type": "double", "description": "Recording start timestamp" },
"ended_at": { "type": "double", "description": "Recording end timestamp" },
"duration_seconds": { "type": "double", "description": "Total duration in seconds" },
"segments": { "type": "array", "items": "FinalSegment", "description": "Full transcript segments" },
"summary": { "type": "Summary", "description": "Generated summary (if available)" },
"metadata": { "type": "map<string, string>", "description": "Custom metadata key-value pairs" }
}
},
"CreateMeetingRequest": {
"description": "Request to create a new meeting",
"fields": {
"title": { "type": "string", "required": false, "description": "Optional title (auto-generated if not provided)" },
"metadata": { "type": "map<string, string>", "required": false, "description": "Optional custom metadata" }
}
},
"StopMeetingRequest": {
"description": "Request to stop a meeting recording",
"fields": {
"meeting_id": { "type": "string", "required": true, "description": "Meeting ID to stop" }
}
},
"ListMeetingsRequest": {
"description": "Request to list meetings with filters",
"fields": {
"states": { "type": "array", "items": "MeetingState", "required": false, "description": "Filter by meeting states" },
"limit": { "type": "int32", "required": false, "default": 50, "description": "Max results to return" },
"offset": { "type": "int32", "required": false, "default": 0, "description": "Pagination offset" },
"sort_order": { "type": "SortOrder", "required": false, "default": "SORT_ORDER_CREATED_DESC", "description": "Sort order" }
}
},
"ListMeetingsResponse": {
"description": "Response containing list of meetings",
"fields": {
"meetings": { "type": "array", "items": "Meeting", "description": "List of meetings" },
"total_count": { "type": "int32", "description": "Total number of meetings matching filter" }
}
},
"GetMeetingRequest": {
"description": "Request to get a specific meeting",
"fields": {
"meeting_id": { "type": "string", "required": true, "description": "Meeting ID to retrieve" },
"include_segments": { "type": "bool", "required": false, "default": false, "description": "Include full transcript segments" },
"include_summary": { "type": "bool", "required": false, "default": false, "description": "Include summary if available" }
}
},
"DeleteMeetingRequest": {
"description": "Request to delete a meeting",
"fields": {
"meeting_id": { "type": "string", "required": true, "description": "Meeting ID to delete" }
}
},
"DeleteMeetingResponse": {
"description": "Response confirming meeting deletion",
"fields": {
"success": { "type": "bool", "description": "Whether deletion was successful" }
}
},
"Summary": {
"description": "AI-generated meeting summary with evidence linking",
"fields": {
"meeting_id": { "type": "string", "description": "Meeting this summary belongs to" },
"executive_summary": { "type": "string", "description": "Executive summary (2-3 sentences)" },
"key_points": { "type": "array", "items": "KeyPoint", "description": "Key points/highlights extracted" },
"action_items": { "type": "array", "items": "ActionItem", "description": "Action items extracted" },
"generated_at": { "type": "double", "description": "Generation timestamp (Unix epoch)" },
"model_version": { "type": "string", "description": "Model/version used for generation" }
}
},
"KeyPoint": {
"description": "Key point from meeting with evidence linking",
"fields": {
"text": { "type": "string", "description": "The key point text" },
"segment_ids": { "type": "array", "items": "int32", "description": "Segment IDs that support this point" },
"start_time": { "type": "double", "description": "Start of relevant time range" },
"end_time": { "type": "double", "description": "End of relevant time range" }
}
},
"ActionItem": {
"description": "Action item extracted from meeting",
"fields": {
"text": { "type": "string", "description": "Action item description" },
"assignee": { "type": "string", "description": "Person assigned (if mentioned)" },
"due_date": { "type": "double", "description": "Due date (Unix epoch, if mentioned)" },
"priority": { "type": "Priority", "description": "Priority level" },
"segment_ids": { "type": "array", "items": "int32", "description": "Segment IDs mentioning this action" }
}
},
"GenerateSummaryRequest": {
"description": "Request to generate meeting summary",
"fields": {
"meeting_id": { "type": "string", "required": true, "description": "Meeting ID to summarize" },
"force_regenerate": { "type": "bool", "required": false, "default": false, "description": "Force regeneration even if summary exists" }
}
},
"Annotation": {
"description": "User-created annotation on meeting timeline",
"fields": {
"id": { "type": "string", "description": "Unique annotation identifier (UUID)" },
"meeting_id": { "type": "string", "description": "Meeting this annotation belongs to" },
"annotation_type": { "type": "AnnotationType", "description": "Type of annotation" },
"text": { "type": "string", "description": "Annotation text content" },
"start_time": { "type": "double", "description": "Start time relative to meeting start (seconds)" },
"end_time": { "type": "double", "description": "End time relative to meeting start (seconds)" },
"segment_ids": { "type": "array", "items": "int32", "description": "Linked transcript segment IDs" },
"created_at": { "type": "double", "description": "Creation timestamp (Unix epoch)" }
}
},
"AddAnnotationRequest": {
"description": "Request to add an annotation",
"fields": {
"meeting_id": { "type": "string", "required": true, "description": "Meeting ID to annotate" },
"annotation_type": { "type": "AnnotationType", "required": true, "description": "Type of annotation" },
"text": { "type": "string", "required": true, "description": "Annotation text" },
"start_time": { "type": "double", "required": true, "description": "Start time in seconds" },
"end_time": { "type": "double", "required": true, "description": "End time in seconds" },
"segment_ids": { "type": "array", "items": "int32", "required": false, "description": "Optional linked segment IDs" }
}
},
"GetAnnotationRequest": {
"description": "Request to get an annotation",
"fields": {
"annotation_id": { "type": "string", "required": true, "description": "Annotation ID to retrieve" }
}
},
"ListAnnotationsRequest": {
"description": "Request to list annotations for a meeting",
"fields": {
"meeting_id": { "type": "string", "required": true, "description": "Meeting ID to list annotations for" },
"start_time": { "type": "double", "required": false, "description": "Filter: start of time range" },
"end_time": { "type": "double", "required": false, "description": "Filter: end of time range" }
}
},
"ListAnnotationsResponse": {
"description": "Response containing annotations",
"fields": {
"annotations": { "type": "array", "items": "Annotation", "description": "List of annotations" }
}
},
"UpdateAnnotationRequest": {
"description": "Request to update an annotation",
"fields": {
"annotation_id": { "type": "string", "required": true, "description": "Annotation ID to update" },
"annotation_type": { "type": "AnnotationType", "required": false, "description": "New type (keeps existing if not set)" },
"text": { "type": "string", "required": false, "description": "New text (keeps existing if empty)" },
"start_time": { "type": "double", "required": false, "description": "New start time (keeps existing if 0)" },
"end_time": { "type": "double", "required": false, "description": "New end time (keeps existing if 0)" },
"segment_ids": { "type": "array", "items": "int32", "required": false, "description": "New segment IDs (replaces existing)" }
}
},
"DeleteAnnotationRequest": {
"description": "Request to delete an annotation",
"fields": {
"annotation_id": { "type": "string", "required": true, "description": "Annotation ID to delete" }
}
},
"DeleteAnnotationResponse": {
"description": "Response confirming annotation deletion",
"fields": {
"success": { "type": "bool", "description": "Whether deletion was successful" }
}
},
"ExportTranscriptRequest": {
"description": "Request to export meeting transcript",
"fields": {
"meeting_id": { "type": "string", "required": true, "description": "Meeting ID to export" },
"format": { "type": "ExportFormat", "required": true, "description": "Export format (Markdown or HTML)" }
}
},
"ExportTranscriptResponse": {
"description": "Response containing exported transcript",
"fields": {
"content": { "type": "string", "description": "Exported content as string" },
"format_name": { "type": "string", "description": "Human-readable format name" },
"file_extension": { "type": "string", "description": "Suggested file extension (.md or .html)" }
}
},
"RefineSpeakerDiarizationRequest": {
"description": "Request to run offline speaker diarization",
"fields": {
"meeting_id": { "type": "string", "required": true, "description": "Meeting ID to process" },
"num_speakers": { "type": "int32", "required": false, "description": "Known number of speakers (auto-detect if 0)" }
}
},
"RefineSpeakerDiarizationResponse": {
"description": "Response from diarization job start",
"fields": {
"segments_updated": { "type": "int32", "description": "Number of segments updated (0 if job is async)" },
"speaker_ids": { "type": "array", "items": "string", "description": "Distinct speaker IDs found" },
"error_message": { "type": "string", "description": "Error message if failed" },
"job_id": { "type": "string", "description": "Background job ID for polling" },
"status": { "type": "JobStatus", "description": "Current job status" }
}
},
"RenameSpeakerRequest": {
"description": "Request to rename a speaker",
"fields": {
"meeting_id": { "type": "string", "required": true, "description": "Meeting ID" },
"old_speaker_id": { "type": "string", "required": true, "description": "Original speaker ID (e.g., 'SPEAKER_00')" },
"new_speaker_name": { "type": "string", "required": true, "description": "New human-readable name (e.g., 'Alice')" }
}
},
"RenameSpeakerResponse": {
"description": "Response from speaker rename",
"fields": {
"segments_updated": { "type": "int32", "description": "Number of segments updated" },
"success": { "type": "bool", "description": "Whether rename was successful" }
}
},
"GetDiarizationJobStatusRequest": {
"description": "Request to check diarization job status",
"fields": {
"job_id": { "type": "string", "required": true, "description": "Job ID from RefineSpeakerDiarization" }
}
},
"DiarizationJobStatus": {
"description": "Status of a diarization job",
"fields": {
"job_id": { "type": "string", "description": "Job ID" },
"status": { "type": "JobStatus", "description": "Current status" },
"segments_updated": { "type": "int32", "description": "Segments updated (when completed)" },
"speaker_ids": { "type": "array", "items": "string", "description": "Speaker IDs found (when completed)" },
"error_message": { "type": "string", "description": "Error message if failed" }
}
},
"ServerInfoRequest": {
"description": "Request for server info (empty message)",
"fields": {}
},
"ServerInfo": {
"description": "Server health and capabilities",
"fields": {
"version": { "type": "string", "description": "Server version string" },
"asr_model": { "type": "string", "description": "Loaded ASR model name" },
"asr_ready": { "type": "bool", "description": "Whether ASR is ready" },
"supported_sample_rates": { "type": "array", "items": "int32", "description": "Supported audio sample rates" },
"max_chunk_size": { "type": "int32", "description": "Maximum audio chunk size in bytes" },
"uptime_seconds": { "type": "double", "description": "Server uptime in seconds" },
"active_meetings": { "type": "int32", "description": "Number of active meetings" },
"diarization_enabled": { "type": "bool", "description": "Whether diarization is enabled" },
"diarization_ready": { "type": "bool", "description": "Whether diarization models are ready" }
}
}
},
"uiHints": {
"primaryEntities": ["Meeting", "Summary", "Annotation"],
"listViews": {
"meetings": {
"endpoint": "ListMeetings",
"displayFields": ["title", "state", "created_at", "duration_seconds"],
"actions": ["view", "delete", "export"]
},
"annotations": {
"endpoint": "ListAnnotations",
"displayFields": ["annotation_type", "text", "start_time"],
"actions": ["edit", "delete"]
}
},
"detailViews": {
"meeting": {
"endpoint": "GetMeeting",
"sections": [
{ "name": "Overview", "fields": ["title", "state", "created_at", "duration_seconds"] },
{ "name": "Transcript", "field": "segments", "type": "timeline" },
{ "name": "Summary", "field": "summary", "type": "expandable" }
]
}
},
"forms": {
"createMeeting": {
"endpoint": "CreateMeeting",
"fields": [
{ "name": "title", "label": "Meeting Title", "type": "text", "placeholder": "Optional - will be auto-generated" }
]
},
"addAnnotation": {
"endpoint": "AddAnnotation",
"fields": [
{ "name": "annotation_type", "label": "Type", "type": "select", "options": "AnnotationType" },
{ "name": "text", "label": "Note", "type": "textarea" },
{ "name": "start_time", "label": "Start Time", "type": "number" },
{ "name": "end_time", "label": "End Time", "type": "number" }
]
}
},
"realTimeFeatures": {
"transcription": {
"endpoint": "StreamTranscription",
"description": "Real-time audio-to-text with live updates",
"updateTypes": ["partial", "final", "vad_start", "vad_end"]
}
}
}
}