app/api/. The frontend calls model providers through these routes. The server injects keys, chooses the API URL, and adjusts request parameters.
These routes are internal to the app and are mainly used by the frontend. Their parameters may change between versions. If you call them from another program, treat the source code in the repository as the source of truth.
Shared conventions
Request headers
Shared parameters
All model-related routes accept these parameters:Access verification
WhenCODE is configured, every route except /api/auth and /api/umami/script requires a valid ja_session cookie. Otherwise it returns:
Error format
On error, routes return the appropriate HTTP status code and an error in a uniform format:messageis always the original Simplified Chinese text and does not depend onX-App-Locale. The frontend translates known errors into the interface language before showing them.- Raw error messages from the model provider are forwarded as-is, and the frontend doesn’t translate them.
- When the model provider takes longer than 60 seconds, non-streaming requests return
504with 「上游接口请求超时,请稍后重试。」
Streaming responses
When streaming output is on, routes forward the upstream OpenAI-compatible Server-Sent Events stream directly, with aContent-Type of text/event-stream. When it’s off, they return the upstream’s complete JSON response.
If streaming output produces no new data for 90 seconds, the server sends an error event in the stream and then closes the connection:
Routes
POST /api/analyze
The model returns structured JSON in the form
{"tokens": [{"word", "pos", "furigana"}]}.
POST /api/translate
X-App-Locale determines the translation language. The translation keeps the paragraph and line-break structure of the original.
POST /api/word-detail
Word details return the fields
chineseTranslation, dictionaryForm, explanation, conjugation, example, exampleTranslation, pos, and furigana. Phrase details also return category and breakdown.
POST /api/image-to-text
POST /api/chat
The server prepends a Japanese learning assistant system prompt to the message list.
POST /api/tts
On success, it returns Base64-encoded audio:
GET /api/daily-sentence
Returns today’s sentence of the day (Japan time), includingdate, text, tokens, and translation in four languages. The response’s Cache-Control expires at midnight Japan time. If the server has no usable key or generation fails, it returns 503, and the frontend falls back to a built-in backup sentence.
/api/auth
GET: Returns{ "requiresAuth": boolean, "authenticated": boolean }.POST: The request body is{ "password": "..." }. If the password is correct, it returns{ "success": true }and sets the session cookie. Otherwise it returns401.
