Xiangyinge Logo

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