POST /api/chat/send is the only streaming endpoint. It accepts one student message and responds
with text/event-stream. OpenAPI cannot describe the event framing, so this page is the contract.
Request
Send
message, image, or both. A request with an empty message and no image returns 400
with {"error":"empty message"}. The 400 arrives before the stream, as normal JSON.
Response events
The response status is200 and the content type is text/event-stream. Each event has a name
and a JSON data payload.
ChatChunkEvent
One text delta. Repeats many times.
ChatDoneEvent
Terminal. Holds the complete answer text and the reactions.
ChatErrorEvent
Terminal. The turn failed.
done or error. A model failure is an error
event, not an HTTP status. The HTTP status stays 200 in both cases.
Rules for the client
- Append each
chunkpayload to the text on screen. - On
done, replace the text on screen with thetextfield. This corrects any lost delta. - On
done, show the emoji inreactions. The array is usually empty. Lala reacts rarely. - On
error, show a retry control. Do not show the partial text as a finished answer. - If the socket closes with no terminal event, treat the turn as failed.
The server persists the student message before the model runs. It persists the answer after the
model runs. A turn that fails mid-stream can leave the student message in the history with no
answer. Call
GET /api/chat/history to resynchronize after an error.