API Reference

Everything a React Native developer needs to build a native ReadIn client.

Download OpenAPI Spec →
https://readin-jdbx.polsia.app/api/v1

Voices

GET /api/v1/voices List available TTS voices

Returns all available voices with descriptions. Use these voice IDs when generating audio.

Response

{
  "success": true,
  "voices": [
    { "id": "alloy", "name": "Alloy", "description": "Neutral, balanced" },
    { "id": "echo", "name": "Echo", "description": "Warm, resonant" },
    { "id": "fable", "name": "Fable", "description": "Expressive, British" },
    { "id": "onyx", "name": "Onyx", "description": "Deep, authoritative" },
    { "id": "nova", "name": "Nova", "description": "Energetic, bright" },
    { "id": "shimmer", "name": "Shimmer", "description": "Soft, clear" }
  ],
  "count": 6
}

Scripts

POST /api/v1/scripts/parse Parse script into structured dialogue

Parses raw script text into structured dialogue. Auto-detects characters (UPPERCASE names followed by colon), assigns voices, and counts lines per character.

Request Body

FieldTypeDescription
text requiredstringRaw script text. Format: CHARACTER: dialogue
// Request
{
  "text": "MARCUS: You said you'd be there.\nELENA: Things changed.\nSARAH: I tried to warn you."
}

Response

{
  "success": true,
  "lines": [
    { "character": "MARCUS", "dialogue": "You said you'd be there." },
    { "character": "ELENA", "dialogue": "Things changed." },
    { "character": "SARAH", "dialogue": "I tried to warn you." }
  ],
  "characters": ["MARCUS", "ELENA", "SARAH"],
  "voiceAssignments": { "MARCUS": "alloy", "ELENA": "echo", "SARAH": "fable" },
  "lineCounts": { "MARCUS": 1, "ELENA": 1, "SARAH": 1 }
}

Text-to-Speech

POST /api/v1/tts/generate Generate speech audio from text

Generates MP3 audio from text using AI voices. Returns binary audio data. Cached for 1 hour. Text truncated to 4096 characters.

Request Body

FieldTypeDescription
text requiredstringText to speak (max 4096 chars)
voicestringVoice ID from /api/v1/voices. Default: alloy
speednumberSpeed multiplier 0.25–4.0. Default: 1.0
// Request
{
  "text": "You said you'd be there. You promised me.",
  "voice": "echo",
  "speed": 1.0
}

// Response: audio/mpeg binary (MP3)
// Headers: X-Voice: echo, X-Text-Length: 42

Usage in React Native

// Fetch audio blob and play it
const res = await fetch('https://readin-jdbx.polsia.app/api/v1/tts/generate', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ text: 'Hello world', voice: 'nova' })
});
const blob = await res.blob();
// Use expo-av or react-native-sound to play the blob

Rehearsal

POST /api/v1/rehearsal/plan Create playback plan for rehearsal

Generates a complete playback sequence with timing, gaps, and TTS payloads. Native clients use this to orchestrate rehearsal without reimplementing the sequencing logic. Each item tells you exactly what to do: play audio (AI line) or wait (user line).

Request Body

FieldTypeDescription
lines requiredarrayLines from /api/v1/scripts/parse
selectedCharacter requiredstringCharacter the user is playing
voiceAssignmentsobjectVoice mapping from parse response
// Response (truncated)
{
  "success": true,
  "selectedCharacter": "ELENA",
  "summary": {
    "totalLines": 13,
    "userLines": 4,
    "aiLines": 9,
    "estimatedDurationSec": 120,
    "estimatedDurationMin": 2.0
  },
  "sequence": [
    {
      "index": 0,
      "character": "MARCUS",
      "dialogue": "You said you'd be there.",
      "isUser": false,
      "voice": "alloy",
      "estimatedDurationSec": 3,
      "gapDurationSec": 0,
      "ttsEndpoint": "/api/v1/tts/generate",
      "ttsPayload": { "text": "You said...", "voice": "alloy" },
      "delayAfterMs": 400
    },
    {
      "index": 1,
      "character": "ELENA",
      "isUser": true,
      "voice": null,
      "gapDurationSec": 4,
      "ttsEndpoint": null,
      "ttsPayload": null
    }
  ]
}

Integration Pattern

// 1. Parse script
const parsed = await parseScript(scriptText);

// 2. Get rehearsal plan
const plan = await createPlan(parsed.lines, 'ELENA', parsed.voiceAssignments);

// 3. Pre-load all AI audio
for (const item of plan.sequence.filter(s => !s.isUser)) {
  const audio = await fetch(item.ttsEndpoint, {
    method: 'POST',
    body: JSON.stringify(item.ttsPayload)
  });
  cache[item.index] = await audio.blob();
}

// 4. Play sequence
for (const item of plan.sequence) {
  if (item.isUser) {
    // Show "Your turn" UI, wait gapDurationSec
    await waitForUser(item.gapDurationSec);
  } else {
    // Play cached audio
    await playAudio(cache[item.index]);
  }
  await delay(item.delayAfterMs);
}

System

GET /api/v1/health Health check
{
  "status": "healthy",
  "version": "2.0.0",
  "services": { "tts": true, "database": true }
}

Error Handling

All errors follow a consistent format with machine-readable error codes:

{
  "success": false,
  "error": "MISSING_TEXT",      // Machine-readable code
  "message": "Text is required"  // Human-readable message
}

Error Codes

CodeHTTPMeaning
MISSING_TEXT400Required text field is empty
NO_DIALOGUE400Script contains no parseable dialogue
MISSING_LINES400Rehearsal plan needs parsed lines
MISSING_CHARACTER400No character selected for rehearsal
PARSE_FAILED500Internal parsing error
TTS_FAILED500OpenAI TTS generation failed
PLAN_FAILED500Rehearsal plan creation failed
OFFLINE-PWA offline (service worker response)

CORS

All /api/* endpoints include permissive CORS headers for cross-origin access from native apps and other domains.