Skip to main content
POST
/
api
/
chat
/
stream
Chat Stream API
curl --request POST \
  --url https://api.example.com/api/chat/stream \
  --header 'Content-Type: application/json' \
  --data '
{
  "message": "<string>",
  "messages": [
    {}
  ],
  "images": [
    {}
  ],
  "monto": 123,
  "categoria": "<string>",
  "descripcion": "<string>",
  "metodo_pago": "<string>",
  "registrado_por": "<string>"
}
'
{
  "thinking": true,
  "chunk": "<string>",
  "done": true
}

Overview

The Chat Stream API provides a conversational AI interface powered by Google’s Gemini 2.5 Flash model. It supports natural language processing for registering expenses and income, with Server-Sent Events (SSE) streaming and automatic database integration via function calling.

Authentication

Requires Supabase authentication and a valid OpenRouter API key configured in environment variables.

Endpoint

POST /api/chat/stream

Request Body

message
string
required
The user’s message in natural language.Example: “Gasté 450 pesos en gasolina”
messages
array
default:"[]"
Conversation history (last 10 messages are used).Each message object contains:
  • role: "user" or "assistant"
  • content: Message text
images
array
default:"[]"
Array of image URLs from uploaded receipts/tickets.Used for OCR-enhanced transaction registration.

Streaming Response

The API returns Server-Sent Events (SSE) with Content-Type: text/event-stream. Each event is a JSON object:

Event Types

thinking
boolean
Indicates the AI is processing (thinking mode).
  • true: AI is analyzing the request
  • false: AI has started generating response
chunk
string
A piece of the streaming response text.Concatenate all chunks to build the complete message.
done
boolean
Indicates the stream has completed.Always sent as the final event.

AI Function Calling

The AI can automatically execute functions to register transactions:

Available Functions

registrar_gasto

Registers an expense transaction.
monto
number
required
Expense amount
categoria
string
required
Category: Alimentación, Transporte, Vivienda, Salud, Entretenimiento, Educación, Otros Gastos
descripcion
string
Optional description
metodo_pago
string
default:"Efectivo"
Payment method: Efectivo, Tarjeta, Transferencia
registrado_por
string
Name of person registering

registrar_ingreso

Registers an income transaction.
monto
number
required
Income amount
categoria
string
required
Category: Salario, Ventas, Servicios, Inversiones, Otros Ingresos
descripcion
string
Optional description
metodo_pago
string
default:"Efectivo"
Payment method: Efectivo, Tarjeta, Transferencia
registrado_por
string
Name of person registering

Examples

const response = await fetch('/api/chat/stream', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    message: 'Gasté 450 pesos en gasolina',
    messages: [],
    images: []
  })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  
  const chunk = decoder.decode(value);
  const lines = chunk.split('\n');
  
  for (const line of lines) {
    if (line.startsWith('data: ')) {
      const data = JSON.parse(line.slice(6));
      
      if (data.thinking) {
        console.log('AI is thinking...');
      } else if (data.chunk) {
        console.log('Response:', data.chunk);
      } else if (data.done) {
        console.log('Stream complete');
      }
    }
  }
}

Stream Event Examples

data: {"thinking": true}

Workflow

  1. Client sends message with natural language input
  2. AI processes using Gemini 2.5 Flash with thinking mode (500 tokens)
  3. Thinking indicator sent to client (thinking: true)
  4. AI analyzes and determines if function calling is needed
  5. Response streams with thinking: false transition
  6. Function execution (if applicable):
    • AI extracts transaction details
    • Inserts into Supabase transacciones table
    • Returns formatted confirmation
  7. Stream completes with done: true
The AI is trained to handle conversational inputs in Spanish and automatically categorize transactions according to the predefined category list.

Thinking Mode

Gemini 2.5 Flash’s thinking mode allocates up to 500 tokens for internal reasoning before generating the response. This improves:
  • Category selection accuracy
  • Amount extraction from natural language
  • Context understanding from conversation history

Error Handling

data: {"chunk": "❌ Error al procesar. Intenta de nuevo.", "done": true}

Integration with Image Upload

When images are provided:
{
  "message": "Aquí está el ticket",
  "messages": [...],
  "images": ["https://supabase.co/storage/v1/object/public/facturas/ticket_123.jpg"]
}
The AI receives context: "[El usuario subió 1 imagen(es) de tickets]\n\nAquí está el ticket" This allows the AI to reference OCR data from the /api/upload-image endpoint.

Build docs developers (and LLMs) love