{"openapi":"3.1.0","info":{"title":"Utterance Engine API","description":"HTTP server for serving the active scheduled audio challenge","version":"0.1.0"},"paths":{"/":{"get":{"summary":"Root","description":"Root endpoint with basic info","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health Check","description":"Health check endpoint","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/debug/network":{"get":{"summary":"Debug Network","description":"Debug endpoint to check Bittensor network connection","operationId":"debug_network_debug_network_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth":{"post":{"summary":"Authenticate","description":"Authenticate a Bittensor validator.\n\nProcess:\n1. Generate a challenge message with current timestamp\n2. Validator signs the message with their hotkey\n3. Server verifies signature and validator permit\n4. Returns JWT token for API access\n\nReturns JWT token valid for 24 hours.","operationId":"authenticate_auth_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChallengeResponse"}}}}}}},"/auth/verify":{"post":{"summary":"Verify Authentication","description":"Verify validator authentication and return JWT token.\n\n- **hotkey**: Bittensor validator hotkey (SS58 address)\n- **signature**: Hex-encoded signature of the challenge message\n- **timestamp**: Timestamp from the challenge\n- **message**: The challenge message that was signed\n\nReturns JWT access token for API usage.","operationId":"verify_authentication_auth_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/challenge":{"get":{"summary":"Get Active Challenge View","description":"Return the source-side view of the currently active challenge.","operationId":"get_active_challenge_view_challenge_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/transcription":{"get":{"summary":"Get Active Challenge Transcription View","description":"Return the transcription-facing view of the currently active challenge.","operationId":"get_active_challenge_transcription_view_transcription_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/source-audio/start":{"post":{"summary":"Start Source Audio Session","description":"Start a source-audio session for the active scheduled challenge.","operationId":"start_source_audio_session_source_audio_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/source-audio/next":{"post":{"summary":"Next Source Audio Utterance","description":"Advance an active source-audio session and return the next utterance.","operationId":"next_source_audio_utterance_source_audio_next_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NextRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/target-audio/start":{"post":{"summary":"Start Target Audio Session","description":"Start a target-audio session for the active scheduled challenge.","operationId":"start_target_audio_session_target_audio_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/target-audio/next":{"post":{"summary":"Next Target Audio Utterance","description":"Advance an active target-audio session and return the next utterance.","operationId":"next_target_audio_utterance_target_audio_next_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NextRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/challenge/{challenge_uid}/n_utterances":{"get":{"summary":"Get Challenge Utterance Count","description":"Return the number of utterances in the active scheduled challenge.","operationId":"get_challenge_utterance_count_challenge__challenge_uid__n_utterances_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"challenge_uid","in":"path","required":true,"schema":{"type":"string","title":"Challenge Uid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/solo/start":{"get":{"summary":"Start Solo Session","description":"Start a new session with a unique solo audio challenge.\n\nEach session gets a unique challenge metadata/audio pair from the solo S3 prefixes.\nThe challenge is reserved for this session and archived when the session ends.\n\nReturns the first audio utterance and session information.","operationId":"start_solo_session_solo_start_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/solo/next":{"post":{"summary":"Next Solo Audio Utterance","description":"Get the next audio utterance in the solo challenge session.\n\n- **session_id**: Session ID returned from /solo/start\n- **prediction**: Optional prediction (currently ignored but accepted for API compatibility)\n\nReturns the next audio utterance and updated session information.","operationId":"next_solo_audio_utterance_solo_next_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NextRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/solo/session/{session_id}":{"delete":{"summary":"Delete Solo Session","description":"Manually delete a solo challenge session and archive the challenge file.\n\nNote: Sessions are automatically cleaned up when they complete (done=True).\nThis endpoint is for manual cleanup of abandoned or interrupted sessions.\n\nThis endpoint:\n1. Removes the session from memory\n2. Deletes the local challenge file\n3. Archives the challenge file by mirroring its S3 key under archive/","operationId":"delete_solo_session_solo_session__session_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/solo/sessions":{"get":{"summary":"List Solo Sessions","description":"List all active solo challenge sessions","operationId":"list_solo_sessions_solo_sessions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}}},"components":{"schemas":{"AuthRequest":{"properties":{"hotkey":{"type":"string","title":"Hotkey","description":"Bittensor hotkey (SS58 address)"},"signature":{"type":"string","title":"Signature","description":"Signature of the challenge message"},"timestamp":{"type":"integer","title":"Timestamp","description":"Unix timestamp"},"message":{"type":"string","title":"Message","description":"Challenge message that was signed"}},"type":"object","required":["hotkey","signature","timestamp","message"],"title":"AuthRequest"},"AuthResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"},"expires_in":{"type":"integer","title":"Expires In"},"validator_uid":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Validator Uid"}},"type":"object","required":["access_token","expires_in"],"title":"AuthResponse"},"ChallengeResponse":{"properties":{"message":{"type":"string","title":"Message"},"challenge":{"type":"string","title":"Challenge"},"timestamp":{"type":"integer","title":"Timestamp"},"instructions":{"type":"string","title":"Instructions"}},"type":"object","required":["message","challenge","timestamp","instructions"],"title":"ChallengeResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"NextRequest":{"properties":{"session_id":{"type":"string","title":"Session Id"},"prediction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prediction"}},"type":"object","required":["session_id"],"title":"NextRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}