Skip to main content

Generate Narrative

Convert simulation results into a human-readable narrative explaining the outcome, probability, and key insights.
POST /api/ai/generate-narrative

Request Body

simulationResults
object
required
Simulation results object containing success probability, percentiles, and statistics
financialProfile
object
required
Current financial situation
goal
object
required
Financial goal details

Response

narrative
string
Human-readable narrative explaining the simulation results, success probability, and actionable insights

Example

const response = await fetch('http://localhost:3001/api/ai/generate-narrative', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    simulationResults: {
      successProbability: 0.78,
      medianOutcome: 52000,
      percentiles: { p10: 35000, p25: 45000, p50: 52000, p75: 60000, p90: 68000 }
    },
    financialProfile: {
      monthlyIncome: 6000,
      monthlySpending: 4200,
      liquidAssets: 15000
    },
    goal: {
      targetAmount: 50000,
      timelineMonths: 36,
      goalType: 'house'
    }
  })
})

const { narrative } = await response.json()
console.log(narrative)
// "Based on 100,000 simulations, you have a 78% chance of reaching your $50,000 house down payment goal in 3 years..."

Generate Audio Briefing

Generate both narrative text and audio in a single request.
POST /api/ai/generate-briefing

Request Body

Same as /generate-narrative with an optional voice parameter:
voice
string
default:"josh"
Voice to use for audio generation. Options: rachel, adam, josh, bella, antoni, domi

Response

narrative
string
Human-readable narrative text
audioAvailable
boolean
Whether audio was generated (false if ElevenLabs not configured)
audio
string
Base64-encoded MP3 audio (only present if audioAvailable is true)
contentType
string
Always “audio/mpeg”
voice
string
Voice used for generation

Example

const response = await fetch('http://localhost:3001/api/ai/generate-briefing', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    simulationResults: { /* ... */ },
    financialProfile: { /* ... */ },
    goal: { /* ... */ },
    voice: 'josh'  // Optional: friendly, conversational voice
  })
})

const { narrative, audioAvailable, audio } = await response.json()

if (audioAvailable) {
  // Play audio in browser
  const audioBlob = new Blob(
    [Uint8Array.from(atob(audio), c => c.charCodeAt(0))],
    { type: 'audio/mpeg' }
  )
  const audioUrl = URL.createObjectURL(audioBlob)
  const audioElement = new Audio(audioUrl)
  audioElement.play()
}
If ELEVENLABS_API_KEY is not configured, the endpoint returns the narrative text but audioAvailable will be false.

Error Responses

error
string
Error message
message
string
Detailed error description

Common Errors

  • 400 Bad Request - Missing required fields
  • 500 Internal Server Error - Gemini API error or text generation failure
  • 503 Service Unavailable - ElevenLabs not configured (audio endpoints only)

Build docs developers (and LLMs) love