openapi: 3.0.3 info: title: AI Voice Synthesis API description: | Standardized TTS API for AI assistants (Coze, Dify, GPTs, custom Agents). Supports sync/async modes, natural language instructions, smart voice recommendation. version: 1.0.0 contact: name: AI Voice Team email: api@your-domain.com servers: - url: https://api.your-domain.com description: Production - url: https://api-staging.your-domain.com description: Staging tags: - name: voices description: Voice management - name: tts description: Speech synthesis - name: tasks description: Async tasks paths: /v1/tts/voices: get: tags: [voices] summary: List available voices security: - bearerAuth: [] responses: '200': description: Success content: application/json: schema: $ref: '#/components/schemas/VoiceListResponse' /v1/tts/detect: post: tags: [tts] summary: Smart detect (recommend voice + emotion) description: AI assistants should call this before synthesize security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DetectRequest' responses: '200': description: Success content: application/json: schema: $ref: '#/components/schemas/DetectResponse' /v1/tts/synthesize: post: tags: [tts] summary: Sync synthesis (short text, less than 500 chars) security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SynthesizeRequest' responses: '200': description: Success content: application/json: schema: $ref: '#/components/schemas/SynthesizeResponse' /v1/tts/async-synthesize: post: tags: [tts, tasks] summary: Async synthesis (long text) security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AsyncSynthesizeRequest' responses: '202': description: Task accepted content: application/json: schema: $ref: '#/components/schemas/AsyncSynthesizeResponse' /v1/tts/tasks/{task_id}: get: tags: [tasks] summary: Query task status security: - bearerAuth: [] parameters: - name: task_id in: path required: true schema: type: string responses: '200': description: Success content: application/json: schema: $ref: '#/components/schemas/TaskResponse' /v1/tts/instruct: post: tags: [tts] summary: Natural language instruction synthesis description: | AI assistant describes requirements in natural language (e.g. "Use magnetic male voice, sad tone"), backend parses params and generates audio. security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/InstructRequest' responses: '200': description: Success content: application/json: schema: $ref: '#/components/schemas/InstructResponse' components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT schemas: Voice: type: object properties: id: { type: string, example: male-qn-jingying } name: { type: string, example: Magnetic Male Voice } gender: { type: string, enum: [male, female, neutral] } age: { type: string, enum: [child, young, middle, old] } style: type: array items: { type: string } language: { type: string, example: zh-CN } preview_url: { type: string, format: uri } description: { type: string } VoiceListResponse: type: object properties: code: { type: integer, example: 0 } message: { type: string } data: type: object properties: voices: type: array items: { $ref: '#/components/schemas/Voice' } DetectRequest: type: object required: [text] properties: text: type: string minLength: 10 maxLength: 5000 DetectResponse: type: object properties: code: { type: integer } data: type: object properties: voice_id: { type: string } voice_name: { type: string } emotion: type: string enum: [neutral, happy, sad, angry, fearful, surprised, disgusted] emotion_label: { type: string } scene: { type: string } role: { type: string } instruct_text: { type: string } SynthesizeRequest: type: object required: [text] properties: text: { type: string, minLength: 10, maxLength: 500 } voice_id: { type: string } emotion: { type: string, enum: [neutral, happy, sad, angry, fearful, surprised, disgusted] } speed: { type: number, minimum: 0.5, maximum: 2.0, default: 1.0 } pitch: { type: integer, minimum: -12, maximum: 12, default: 0 } volume: { type: integer, minimum: 0, maximum: 100, default: 50 } format: { type: string, enum: [mp3, wav, pcm], default: mp3 } sample_rate: { type: integer, enum: [16000, 24000, 48000], default: 24000 } SynthesizeResponse: type: object properties: code: { type: integer } data: type: object properties: audio_url: { type: string, format: uri } duration: { type: number } characters: { type: integer } cached: { type: boolean } request_id: { type: string } AsyncSynthesizeRequest: allOf: - $ref: '#/components/schemas/SynthesizeRequest' - type: object properties: text: type: string minLength: 10 maxLength: 100000 instruction: { type: string } callback_url: { type: string, format: uri } metadata: type: object additionalProperties: true AsyncSynthesizeResponse: type: object properties: code: { type: integer } data: type: object properties: task_id: { type: string } estimated_duration: { type: integer } status_url: { type: string } created_at: { type: string, format: date-time } TaskResponse: type: object properties: code: { type: integer } data: type: object properties: task_id: { type: string } status: type: string enum: [pending, processing, completed, failed] progress: { type: integer, minimum: 0, maximum: 100 } audio_url: { type: string, format: uri } duration: { type: number } characters: { type: integer } error: { type: string } completed_at: { type: string, format: date-time } metadata: type: object additionalProperties: true InstructRequest: type: object required: [text, instruction] properties: text: { type: string, minLength: 10, maxLength: 5000 } instruction: type: string example: Use magnetic male voice, sad tone, last sentence slow InstructResponse: type: object properties: code: { type: integer } data: type: object properties: parsed_params: type: object properties: voice_id: { type: string } emotion: { type: string } speed: { type: number } pitch: { type: integer } audio_url: { type: string, format: uri } duration: { type: number }