Ella Backend: API & Database System Inventory
This document provides a technical specification and catalog of the database schema, active API endpoints, and real-world testing examples for the Ella voice-first English tutor backend.Base URL Prefix
All API endpoints are deployed behind the production gateway at:https://ella.navgurukul.org/api
For local testing, swap the prefix with: http://localhost:8000/api
Interactive API Documentation
You can access the auto-generated Swagger and ReDoc pages to test endpoints and inspect response schemas directly:- Swagger UI (Production): https://ella.navgurukul.org/api/docs (Local:
http://localhost:8000/docs) - ReDoc (Production): https://ella.navgurukul.org/api/redoc (Local:
http://localhost:8000/redoc)
Placement & Onboarding Flow API Sequence
When a student launches the app and goes through placement, the following APIs are triggered in sequence:-
App Launch & Welcome Screen:
POST /auth/anonymous: Automatically invoked in the background to exchange the device’s generated UUID for a secure JWT access token, registering the account if it’s the first run.
-
Placement Screen (Voice screening chat):
POST /llm/placement-turn: Called on every message turn (speech or text) containing the conversation history. Zoe replies with the next prompt until sufficient turn evidence is gathered, at which point the API responds withis_complete: trueand the evaluated CEFR level results.
-
Transitioning to Result Screen:
PUT /users/me: Updates student’s extracted name, age, and location.POST /placements: Persists the final CEFR level assessment, description highlight, hobbies, and conversation transcript.
Client App API Integration Summary
This table summarizes which backend APIs are actively integrated and called by the student-facing Flutter client app versus those that are unused, administrative, or diagnostic.| API Group / Endpoint | HTTP Method | Frontend Service Method | Status in Client App |
|---|---|---|---|
| Authentication | |||
/auth/anonymous | POST | ensureAuthenticated() / _anonymousAuth() | Active (Called on launch) |
| User Profiles | |||
/users/me | GET | getMyProfile() | Unused (No client-side consumption yet) |
/users/me | PUT | updateProfile() | Active (Updates profile details after placement) |
/users/me/memory | GET | — | Unused (Only used in loop simulator) |
/users/me/memory | PUT | — | Unused |
| Placement Loop | |||
/placements | POST | savePlacement() | Active (Saves test result on completion) |
/placements/latest | GET | getLatestPlacement() | Unused (No client-side consumption yet) |
/placements | GET | — | Unused |
/llm/placement-turn | POST | sendPlacementTurn() | Active (Drives placement chat) |
| Active Practice Chat | |||
/session | POST | createConversation() | Active (Starts new learning session) |
/session | GET | listConversations() | Unused (History screen not implemented) |
/session/{session_id}/messages | POST | storeMessage() | Active (Saves message bubbles) |
/session/{session_id}/messages | GET | getMessages() | Unused |
/session/{session_id}/turn | POST | conversationTurn() | Active (Submit user response and get Zoe’s response) |
/session/{session_id}/analysis | GET | getConversationAnalysis() | Active (Retrieve qualitative/quantitative conversation analysis) |
/session/{session_id}/session-log | GET | getSessionLog() | Active (Retrieve compiled session log) |
/llm/conversation-starter | POST | getConversationStarter() | Active (Generates Zoe’s opening question) |
/llm/conversation-turn | POST | sendConversationTurn() | Active (Zoe’s chat responses + corrections) |
/llm/session-analysis | POST | getSessionAnalysis() | Active (Generates end-of-session summary card) |
| Progress & Admin | |||
/progress/summary | GET | getProgressSummary() | Unused (Dashboard not yet built) |
/admin/* | GET | — | Unused (Supervisor portal only) |
1. Database Schema & Models
The backend utilizes PostgreSQL 16 (mapped in Docker via SQLAlchemy models underbackend/app/models/). There are 5 primary tables in the database:
A. Users Table (user.py)
Stores registered students, their CEFR levels, interest tags, and learning settings.| Column | SQLAlchemy Type | Constraints | Description |
|---|---|---|---|
id | String(36) | Primary Key (UUID v4) | Unique user identifier. |
device_id | String(64) | Unique, Indexed | Hardware UUID sent by mobile client on first launch. |
name | String(100) | Nullable | Student’s name (extracted during placement). |
age | String(10) | Nullable | Student’s age bracket (extracted during placement). |
location | String(100) | Nullable | Student’s location (extracted during placement). |
level | String(5) | Nullable | Assigned CEFR level (e.g., A1, A2, B1). |
level_label | String(50) | Nullable | User-facing label (e.g., Beginner, Intermediate). |
interests | String(200) | Nullable | Comma-separated interest tags (e.g., cricket,music). |
first_session_done | Boolean | Default: False | Tracks if onboarding is complete. |
created_at | DateTime(timezone=True) | Default: UTC Now | Account creation timestamp. |
updated_at | DateTime(timezone=True) | Default/Update: UTC Now | Account last update timestamp. |
B. Placements Table (placement.py)
Logs the results of the 3-turn voice screening test taken by the user.| Column | SQLAlchemy Type | Constraints | Description |
|---|---|---|---|
id | String(36) | Primary Key (UUID) | Unique placement record identifier. |
user_id | String(36) | ForeignKey(users.id), Index | Owner of the placement test. |
level | String(5) | Required | Assessed CEFR level code. |
level_label | String(50) | Nullable | Level display label. |
confidence | String(20) | Nullable | LLM confidence rating on grading accuracy. |
highlight | Text | Nullable | Highlight sentence displayed to the student. |
transcript_json | Text | Nullable | Full serialized transcript of the 3 placement turns. |
created_at | DateTime(timezone=True) | Default: UTC Now | Test completion timestamp. |
C. Conversations Table (conversation.py)
Tracks each session container/call completed by the user.| Column | SQLAlchemy Type | Constraints | Description |
|---|---|---|---|
id | String(36) | Primary Key (UUID) | Unique call session identifier. |
user_id | String(36) | ForeignKey(users.id), Index | The student who conducted this session. |
topic | String(100) | Nullable | Selected conversation topic. |
header_title | String(100) | Nullable | User-facing display title for the call. |
duration_seconds | Integer | Nullable | Estimated length of the call in seconds. Scaled automatically on the backend from the number of learner turns (turns * 30). |
session_type | String(20) | Nullable | Type of session (e.g. topic, free_flow). |
quality | String(20) | Nullable | Overall session performance quality. |
completed | Boolean | Default: False | Status flag. |
created_at | DateTime(timezone=True) | Default: UTC Now | Start time. |
completed_at | DateTime(timezone=True) | Nullable | End time. |
D. Messages Table (message.py)
Logs every spoken turn inside active conversation sessions.| Column | SQLAlchemy Type | Constraints | Description |
|---|---|---|---|
id | String(36) | Primary Key (UUID) | Unique message identifier. |
conversation_id | String(36) | ForeignKey(conversations.id), Index | Session container this message belongs to. |
role | String(20) | Required | "user" or "assistant". |
content | Text | Required | Transcribed voice text of the message. |
correction | Text | Nullable | Grammar suggestions/corrections for the user. |
stt_duration_ms | Integer | Nullable | Speech-to-Text conversion time telemetry. |
llm_duration_ms | Integer | Nullable | LLM response generation time telemetry. |
tts_duration_ms | Integer | Nullable | Text-to-Speech audio conversion time telemetry. |
turn_number | Integer | Default: 0 | Sequence index of the turn inside the conversation. |
created_at | DateTime(timezone=True) | Default: UTC Now | Message send timestamp. |
E. Session Analyses Table (session_analysis.py)
Stores post-session LLM analysis cards generated at the end of each conversation.| Column | SQLAlchemy Type | Constraints | Description |
|---|---|---|---|
id | String(36) | Primary Key (UUID) | Unique analysis card identifier. |
conversation_id | String(36) | ForeignKey(conversations.id), Unique, Index | One-to-one link to conversation container. |
overall | String(20) | Required | Overall grade/evaluation score (e.g. great, okay). |
best_moment_quote | Text | Nullable | Quote highlighting student’s best speech moment. |
best_moment_note | Text | Nullable | Explanation note why it was the best moment. |
courage_type | String(30) | Nullable | Type of courage shown (e.g. speaking_clearly). |
courage_content | Text | Nullable | Explanation note regarding shown courage. |
try_next_skill | Text | Nullable | Suggested grammar/vocab skill to practice next. |
try_next_example | Text | Nullable | Usage example of the recommended next skill. |
transcript_notes_json | Text | Nullable | Serialized list of turn-by-turn notes for progress analysis. |
created_at | DateTime(timezone=True) | Default: UTC Now | Evaluation generation timestamp. |
2. API Endpoints Catalog & Purpose Specs
FastAPI routes are organized underbackend/app/routers/.
Group 1: Onboarding & Authentication
POST https://ella.navgurukul.org/api/auth/anonymous- Payload:
AnonymousAuthRequest(device_idstring) - Purpose & Reason: Establishes a zero-friction user account on first app install. We want to avoid requiring emails or passwords for young students. If the
device_idis new, it silently provisions a new SQL record inusersand issues a JSON Web Token (JWT). If the device is returning, it issues a fresh token to authenticate subsequent calls.
- Payload:
Group 2: User Profiles & Learning Settings
GET https://ella.navgurukul.org/api/users/me- Headers:
Authorization: Bearer <token> - Purpose & Reason: Fetches the student’s active status (level, tags, and settings). This is called when the app starts to check if the student has completed their first voice placement screening.
- Headers:
PUT https://ella.navgurukul.org/api/users/me- Payload:
UpdateProfileRequest(name,age,location) - Purpose & Reason: Captures details parsed from LLM placement transcripts. It updates demographic details on the student’s profile for localized progress grouping.
- Payload:
Group 3: Voice Placement Screening Loop
POST https://ella.navgurukul.org/api/llm/placement-turn- Payload:
PlacementTurnRequest(messages,name,age) - Purpose & Reason: Runs the 3-turn voice screening test. Zoe greets the student and conducts a conversational prompt flow. The API acts as the state machine; once 3 turns are completed, it evaluates CEFR proficiency and sets
is_complete=True.
- Payload:
POST https://ella.navgurukul.org/api/placements- Payload:
CreatePlacementRequest(level,level_label,confidence,highlight,transcript_json,interests) - Purpose & Reason: Finalizes the placement test. Saves the final CEFR grading, logs confidence scoring, extracts interest tags, and stores the chat transcript JSON. It updates the student’s profile settings to lock in their learning level.
- Payload:
GET https://ella.navgurukul.org/api/placements/latest- Purpose & Reason: Fetches the student’s active placement parameters to adjust vocabulary and theme choices.
GET https://ella.navgurukul.org/api/placements- Purpose & Reason: Lists historical placement tests completed, allowing progress comparisons over time.
Group 4: Call Sessions & Active Voice Chat
POST https://ella.navgurukul.org/api/session- Payload:
CreateConversationRequest(topic) - Purpose & Reason: Creates a new session container. Binds the selected learning theme (e.g. “My Family”) to a unique session ID, allowing us to group subsequent message turns under one session.
- Payload:
POST https://ella.navgurukul.org/api/session/{session_id}/turn- Payload:
ConversationTurnRequest(content) - Purpose & Reason: The core turn-by-turn conversational logic. For every sentence the student speaks, this endpoint processes the message, runs context analysis, and returns Zoe’s response.
- Payload:
POST https://ella.navgurukul.org/api/session/{session_id}/messages- Payload:
StoreMessageRequest(role,content,correction,stt_duration_ms,llm_duration_ms,tts_duration_ms,turn_number) - Purpose & Reason: Persists individual message bubbles, corrections, and latency metrics to database history.
- Payload:
GET https://ella.navgurukul.org/api/session/{session_id}/messages- Purpose & Reason: Returns the transcript history of a call to display the chat list UI.
GET https://ella.navgurukul.org/api/session/{session_id}/analysis- Purpose & Reason: Returns qualitative and quantitative evaluation of the session once completed.
GET https://ella.navgurukul.org/api/session/{session_id}/session-log- Purpose & Reason: Returns the compiled structured log for learning analytics.
Group 5: Post-Session Evaluation & Progress
POST https://ella.navgurukul.org/api/llm/session-analysis- Payload:
SessionAnalysisRequest - Purpose & Reason: Runs immediately after session completion. Zoe analyzes the full transcript, extracting a “Best Moment” and “Courage” moments to build encouragement cards. The endpoint automatically computes practice duration dynamically as
learner_turns * 30seconds and saves it to the database, completing the conversation.
- Payload:
GET https://ella.navgurukul.org/api/progress/summary- Purpose & Reason: Computes aggregate statistics (total calls, completed sessions, speaking time, and placement history) to display on the student’s profile dashboard.
Group 6: Classroom Admin Dashboards (Key Protected)
GET https://ella.navgurukul.org/api/admin/stats- Purpose & Reason: Provides classroom stats (user levels, total minutes spoken) for supervisor auditing (requires query string key).
GET https://ella.navgurukul.org/api/admin/conversations/{conversation_id}/transcript- Purpose & Reason: Allows supervisors to fetch full transcripts with detailed latency profiles to review student progress (requires admin key).
GET https://ella.navgurukul.org/api/admin/placements/{user_id}/transcript- Purpose & Reason: Allows supervisors to review the transcript of a student’s placement test to audit grading accuracy (requires admin key).
Group 7: Accent Evaluation (POC — Disabled)
POST https://ella.navgurukul.org/api/accent/predict- Payload:
UploadFile(Multipart WAV Audio) - Purpose & Reason: Implements an accent prediction POC. Takes WAV audio files, extracts MFCC features using
librosa, and uses a trained Keras CNN model (accent_model.h5) to classify the accent as Indian or American. (Currently commented out in main app due to heavy machine learning dependencies).
- Payload:
Group 8: System Diagnostics
GET https://ella.navgurukul.org/api/- Purpose & Reason: Verifies the API server is reachable and redirects to OpenAPI specs.
GET https://ella.navgurukul.org/api/health- Purpose & Reason: Basic health check endpoint for DevOps monitoring.
3. Practical API Curl Examples
Below are standardcurl calls demonstrating how to query the primary backend endpoints.