{
  "name": "app-tts",
  "title": "App API - Text-to-Speech Service",
  "description": "Text-to-speech service for deployed apps: ElevenLabs, OpenAI, and Gemini (30 voices, multi-speaker, 60+ languages)",
  "guid": "sk_plat_atts",
  "category": "App services",
  "requiredTools": [
    "project_settings"
  ],
  "content": "# App API - Text-to-Speech Service\n\n> This is the **app service** a deployed app calls over HTTPS. For the agent generating speech during a chat, see [tts](tts.md).\n\nTTS is available for every project with no setup needed (owner_pays billing by default).\n\nUse `project_settings` to customize (optional):\n- Switch billing mode (owner_pays ↔ user_pays)\n- Set default provider and voice\n\n## Providers\n- **elevenlabs**: ElevenLabs (many voices - use voice_set list to discover)\n- **openai**: OpenAI (alloy, ash, ballad, coral, echo, fable, nova, onyx, sage, shimmer, verse)\n- **gemini**: Gemini (30 voices: Kore, Puck, Zephyr, Charon, Fenrir, Leda, Orus, Aoede, and 22 more). Multi-speaker (up to 2) and 60+ languages\n\n## Endpoints\n- `GET /api/<PROJECT_GUID>/services/tts/voices` - list available voices\n- `POST /api/<PROJECT_GUID>/services/tts` - generate speech audio\n\n## Listing Voices\n```\nGET /api/<PROJECT_GUID>/services/tts/voices?provider=elevenlabs\n```\nReturns `{ data: { voices: [...], provider, available_providers } }`\n\n## Request Format (POST /tts)\n```json\n{\n  \"text\": \"Hello, welcome to our app!\",\n  \"voice_id\": \"JBFqnCBsd6RMkjVDRZzb\",\n  \"provider\": \"elevenlabs\",\n  \"model\": \"eleven_multilingual_v2\"\n}\n```\n\nFields:\n- `text` (required): Text to speak, max 5,000 chars\n- `voice_id`: Voice to use (default: JBFqnCBsd6RMkjVDRZzb / George)\n- `provider`: \"elevenlabs\", \"openai\", or \"gemini\" (default: elevenlabs)\n- `model`: Provider-specific model ID (optional)\n- `language`: BCP-47 language code (Gemini only, e.g. \"ja-JP\", \"es-ES\"). 60+ languages\n- `speakers`: Multi-speaker config (Gemini only, up to 2). Array of `{ name, voice }`. Text must use \"Name: dialogue\" format per line\n\n## Gemini TTS Details\n\n**30 voices**: Zephyr, Puck, Charon, Kore, Fenrir, Leda, Orus, Aoede, Callirrhoe, Autonoe, Enceladus, Iapetus, Umbriel, Algieba, Despina, Erinome, Algenib, Rasalgethi, Laomedeia, Achernar, Alnilam, Schedar, Gacrux, Pulcherrima, Achird, Zubenelgenubi, Vindemiatrix, Sadachbia, Sadaltager, Sulafat\n\n**Multi-speaker example** (up to 2 speakers):\n```json\n{\n  \"text\": \"Joe: Hey, how are you?\\nJane: Great, thanks!\",\n  \"provider\": \"gemini\",\n  \"speakers\": [\n    { \"name\": \"Joe\", \"voice\": \"Charon\" },\n    { \"name\": \"Jane\", \"voice\": \"Leda\" }\n  ]\n}\n```\n\n**Language example** (Japanese):\n```json\n{\n  \"text\": \"こんにちは世界\",\n  \"provider\": \"gemini\",\n  \"voice_id\": \"Kore\",\n  \"language\": \"ja-JP\"\n}\n```\n\nOutput format is raw PCM audio (audio/L16, 24kHz). The platform converts and serves as MP3.\n\n## Response Format\n```json\n{\n  \"url\": \"https://media.gipity.ai/med_abc12345.mp3\",\n  \"voice_id\": \"JBFqnCBsd6RMkjVDRZzb\",\n  \"provider\": \"elevenlabs\",\n  \"credits_used\": 5\n}\n```\n\nThe `url` is a permanent public CDN URL to an MP3 file.\n\n## Client Code Example\n```js\nconst tokenRes = await fetch('https://a.gipity.ai/api/token', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ app: '<PROJECT_GUID>' })\n});\nconst { data: { token } } = await tokenRes.json();\n\nconst res = await fetch('https://a.gipity.ai/api/<PROJECT_GUID>/services/tts', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json', 'X-App-Token': token },\n  body: JSON.stringify({ text: 'Welcome to the future of AI!' })\n});\nconst data = await res.json();\n\n// Play audio\nconst audio = new Audio(data.url);\naudio.play();\n```\n\n## Limits\n- **Rate limit**: 600 requests per 5-minute window (per IP)\n- **Max text length**: 5,000 chars\n- **Timeout**: 60s\n- Standard `RateLimit-*` headers included in responses"
}
