Dialect TTS API Documentation
Base URL: https://api.xiangyinge.com/api/v1
Authentication & Encryption
All endpoints require an API Key in the request header, and both request body and response body are AES encrypted:
X-API-Key: your_api_key
Content-Type: application/json
Encryption Details
- Algorithm: AES-256-CBC
- Key derivation: SHA256 hash of API Key used as AES key
- Request validity: 5 minutes (based on timestamp validation)
Request Format
All POST request bodies must be encrypted before sending:
{
"encryptedData": "Base64 encoded encrypted data",
"iv": "Base64 encoded initialization vector",
"timestamp": 1704067200000
}
encryptedData decrypts to the actual request parameters JSON.
Response Format
All responses are in encrypted format:
{
"encryptedData": "Base64 encoded encrypted data",
"iv": "Base64 encoded initialization vector",
"timestamp": 1704067200000
}
Decrypt to get the actual response data.
Encryption Example (JavaScript)
const crypto = require('crypto');
function encrypt(data, apiKey) {
const key = crypto.createHash('sha256').update(apiKey).digest();
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update(JSON.stringify(data), 'utf8', 'base64');
encrypted += cipher.final('base64');
return {
encryptedData: encrypted,
iv: iv.toString('base64'),
timestamp: Date.now()
};
}
function decrypt(response, apiKey) {
const key = crypto.createHash('sha256').update(apiKey).digest();
const iv = Buffer.from(response.iv, 'base64');
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
let decrypted = decipher.update(response.encryptedData, 'base64', 'utf8');
decrypted += decipher.final('utf8');
return JSON.parse(decrypted);
}
Endpoints
POST /tts
Text-to-speech endpoint that converts text to dialect audio.
Request Parameters (before encryption)
| Parameter | Type | Required | Description |
|---|---|---|---|
| text | string | Yes | Text to synthesize, max 5000 characters |
| voice_id | string | Yes | Voice ID |
Request Example
const apiKey = 'your_api_key';
const payload = encrypt({ text: '你好', voice_id: 'dongbei_laotie' }, apiKey);
fetch('https://api.xiangyinge.com/api/v1/tts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey
},
body: JSON.stringify(payload)
})
.then(res => res.json())
.then(encrypted => {
const data = decrypt(encrypted, apiKey);
console.log(data);
});
Success Response (after decryption)
{
"success": true,
"data": {
"audio_url": "https://r2.xiangyinge.com/abc123.mp3",
"billing": {
"raw_chars": 2,
"billable_chars": 50,
"cost_yuan": 0.01,
"balance_after_yuan": 0.99
}
}
}
Error Response (after decryption)
{
"success": false,
"error_code": "INSUFFICIENT_BALANCE",
"message": "Insufficient balance, requires 0.01 yuan, current balance 0.00 yuan",
"details": {
"required_cents": 1,
"available_cents": 0
}
}
GET /voices
Get all available voices.
Request Example
fetch('https://api.xiangyinge.com/api/v1/voices', {
headers: { 'X-API-Key': 'your_api_key' }
})
.then(res => res.json())
.then(encrypted => {
const data = decrypt(encrypted, 'your_api_key');
console.log(data);
});
Success Response (after decryption)
{
"success": true,
"data": {
"voices": {
"东北话": [
{ "id": "dongbei_laotie", "name": "东北老铁" },
{ "id": "dongbei_yatou", "name": "东北丫头" }
],
"四川话": [
{ "id": "chongqing_xiaohuo", "name": "重庆小伙" },
{ "id": "sichuan_tianmeier", "name": "四川甜妹儿" }
]
}
}
}
GET /account
Query current account information.
Request Example
fetch('https://api.xiangyinge.com/api/v1/account', {
headers: { 'X-API-Key': 'your_api_key' }
})
.then(res => res.json())
.then(encrypted => {
const data = decrypt(encrypted, 'your_api_key');
console.log(data);
});
Success Response (after decryption)
{
"success": true,
"data": {
"name": "test@example.com",
"balance_yuan": 1.0,
"total_recharge_yuan": 1.0,
"total_consumed_yuan": 0.0,
"price_per_wan_yuan": 2.0
}
}
Billing Rules
- Standard price: ¥2 / 10,000 characters
- Billing increment: Rounded up to 50 characters (1-50 counts as 50, 51-100 counts as 100)
- Tiered pricing:
- Total recharge ≥¥500: ¥1.9 / 10,000 characters
- Total recharge ≥¥2000: ¥1.75 / 10,000 characters
Error Codes
| Error Code | HTTP Status | Description |
|---|---|---|
| AUTH_ERROR | 401 | X-API-Key not provided or decryption failed |
| MISSING_API_KEY | 401 | X-API-Key header not provided |
| INVALID_API_KEY | 401 | API Key is invalid or disabled |
| DECRYPTION_FAILED | 400 | Request decryption failed |
| MISSING_PARAMETER | 400 | Missing required parameter text or voice_id |
| TEXT_TOO_LONG | 400 | Text exceeds 5000 character limit |
| INSUFFICIENT_BALANCE | 402 | Insufficient account balance |
| RATE_LIMIT_EXCEEDED | 429 | Rate limit exceeded (default 60 requests/minute) |
| TTS_FAILED | 200 | Speech synthesis failed, see message field for details |
Limits
- Maximum text length per request: 5000 characters
- Default rate limit: 60 requests/minute
- Request timestamp validity: 5 minutes