Spaces:
Runtime error
FinSight Backend API Documentation
Generated: February 9, 2026
Version: 1.0
Framework: Django 6.0.2 with Django REST Framework
Table of Contents
- Overview
- API Routes & Endpoints
- Models
- Views & Endpoints Detail
- Serializers
- Utility Functions
- Configuration
- Authentication
Overview
FinSight is a Django-based REST API backend that provides user authentication, email verification via OTP, and JWT-based token management. The backend is organized into modular Django apps:
core: Main project configuration and routingaccounts: User authentication, registration, and OTP verificationapi: Placeholder app for future API endpoints
API Routes & Endpoints
Base URL Structure
All authentication routes are prefixed with /api/auth/
Complete Endpoint List
| HTTP Method | Endpoint Path | View Class | Authentication Required | Description |
|---|---|---|---|---|
| POST | /api/auth/register/ |
RegisterView |
No | Register a new user account |
| POST | /api/auth/login/ |
LoginView |
No | Login with username/email and password |
| GET | /api/auth/me/ |
MeView |
Yes (JWT) | Get current authenticated user profile |
| POST | /api/auth/send-otp/ |
SendOTPView |
No | Send OTP to user's email for verification |
| POST | /api/auth/verify-otp/ |
VerifyOTPView |
No | Verify OTP to activate email verification |
| POST | /api/auth/logout/ |
LogoutView |
Yes (JWT) | Logout and blacklist refresh token |
| POST | /api/auth/token/refresh/ |
TokenRefreshView |
No | Refresh JWT access token using refresh token |
| POST | /api/auth/google/ |
GoogleAuthView |
No | Authenticate with Google OAuth token |
Models
User Model
Location: backend/accounts/models.py
Custom user model extending Django's AbstractBaseUser and PermissionsMixin.
Fields
| Field Name | Type | Properties | Description |
|---|---|---|---|
name |
CharField | max_length=100 | User's full name |
username |
CharField | max_length=50, unique=True | Unique username for login |
email |
EmailField | - | User's email address |
is_email_verified |
BooleanField | default=False | Email verification status |
otp |
CharField | max_length=6, blank=True, null=True | Current OTP for verification |
otp_created_at |
DateTimeField | blank=True, null=True | Timestamp when OTP was generated |
is_active |
BooleanField | default=True | Account active status |
is_staff |
BooleanField | default=False | Staff/admin status |
created_at |
DateTimeField | auto_now_add=True | Account creation timestamp |
Configuration
- USERNAME_FIELD:
username - REQUIRED_FIELDS:
["email"] - Manager:
UserManager
Methods
__str__(self)→ Returns the username as string representation
UserManager Class
Location: backend/accounts/models.py
Custom manager for the User model.
Methods
create_user(username, email, password=None, **extra_fields)
Purpose: Creates and saves a regular user with hashed password
Parameters:
username(str, required): Unique usernameemail(str, required): User's email addresspassword(str, optional): Plain text password (will be hashed)**extra_fields: Additional user fields
Returns: User instance
Raises:
ValueError: If username or email is not provided
create_superuser(username, email, password=None, **extra_fields)
Purpose: Creates and saves a superuser with staff and superuser privileges
Parameters:
username(str, required): Unique usernameemail(str, required): User's email addresspassword(str, optional): Plain text password (will be hashed)**extra_fields: Additional user fields
Returns: User instance with is_staff=True and is_superuser=True
Views & Endpoints Detail
RegisterView
Location: backend/accounts/views.py
Base Class: APIView
Permission: AllowAny (public access)
POST /api/auth/register/
Purpose: Register a new user account
Request Body:
{
"name": "string (required)",
"username": "string (required, unique)",
"email": "string (required)",
"password": "string (required)"
}
Success Response (201 CREATED):
{
"success": true,
"message": "User registered successfully"
}
Error Response (400 BAD REQUEST):
{
"field_name": ["error message"]
}
Implementation Details:
- Uses
RegisterSerializerfor validation and user creation - Password is automatically hashed during creation
- Email verification is NOT required at registration
LoginView
Location: backend/accounts/views.py
Base Class: APIView
Permission: AllowAny (public access)
POST /api/auth/login/
Purpose: Authenticate user and return JWT tokens
Request Body:
{
"identifier": "string (username or email)",
"password": "string"
}
Success Response (200 OK):
{
"access": "eyJhbGc...",
"refresh": "eyJhbGc..."
}
Error Responses:
400 BAD REQUEST:
{
"error": "Identifier and password are required"
}
401 UNAUTHORIZED:
{
"error": "Invalid username/email or password"
}
403 FORBIDDEN:
{
"error": "Email not verified"
}
Implementation Details:
- Accepts either username or email as identifier
- Checks password using Django's
check_password()method - Validates email verification status before issuing tokens
- Returns both access and refresh JWT tokens
MeView
Location: backend/accounts/views.py
Base Class: APIView
Permission: IsAuthenticated (requires JWT token)
GET /api/auth/me/
Purpose: Retrieve current authenticated user's profile information
Request Headers:
Authorization: Bearer <access_token>
Success Response (200 OK):
{
"id": 1,
"name": "John Doe",
"username": "johndoe",
"email": "john@example.com"
}
Error Response (401 UNAUTHORIZED):
{
"detail": "Authentication credentials were not provided."
}
Implementation Details:
- Extracts user from
request.user(populated by JWT authentication) - Returns user ID, name, username, and email
- Does not expose sensitive fields like password or OTP
SendOTPView
Location: backend/accounts/views.py
Base Class: APIView
Permission: AllowAny (public access)
POST /api/auth/send-otp/
Purpose: Generate and send a 6-digit OTP to user's email for verification
Request Body:
{
"email": "string (required)"
}
Success Response (200 OK):
{
"success": true,
"message": "OTP sent successfully"
}
Error Responses:
400 BAD REQUEST:
{
"error": "Email is required"
}
404 NOT FOUND:
{
"error": "User not found"
}
Implementation Details:
- Generates a 6-digit random OTP using
generate_otp()utility - Stores OTP and creation timestamp in user record
- Sends email via Django's
send_mail()with:- Subject: "FinSight AI - Email Verification OTP"
- Message: "Your OTP is {otp}. It is valid for 5 minutes."
- From: "no-reply@finsight.ai"
- OTP is valid for 5 minutes
VerifyOTPView
Location: backend/accounts/views.py
Base Class: APIView
Permission: AllowAny (public access)
POST /api/auth/verify-otp/
Purpose: Verify user's email using the OTP sent via email
Request Body:
{
"email": "string (required)",
"otp": "string (required, 6 digits)"
}
Success Response (200 OK):
{
"success": true,
"message": "Email verified successfully"
}
Error Responses:
400 BAD REQUEST (missing fields):
{
"error": "Email and OTP are required"
}
400 BAD REQUEST (invalid OTP):
{
"error": "Invalid OTP"
}
400 BAD REQUEST (expired OTP):
{
"error": "OTP expired"
}
Implementation Details:
- Validates OTP matches the one stored in user record
- Checks OTP expiration (5 minutes from creation)
- Sets
is_email_verified = Trueon success - Clears OTP and OTP creation timestamp after verification
- Users can login only after email is verified
LogoutView
Location: backend/accounts/views.py
Base Class: APIView
Permission: IsAuthenticated (requires JWT token)
POST /api/auth/logout/
Purpose: Logout user by blacklisting their refresh token
Request Headers:
Authorization: Bearer <access_token>
Request Body:
{
"refresh": "string (required, refresh token)"
}
Success Response (200 OK):
{
"success": true,
"message": "Logged out successfully"
}
Error Responses:
400 BAD REQUEST (missing token):
{
"error": "Refresh token is required"
}
400 BAD REQUEST (invalid token):
{
"error": "Invalid or expired refresh token"
}
Implementation Details:
- Uses
rest_framework_simplejwt.token_blacklistto blacklist tokens - Prevents reuse of the refresh token after logout
- Requires both access token (in header) and refresh token (in body)
TokenRefreshView
Location: rest_framework_simplejwt.views (third-party)
Base Class: TokenRefreshView
Permission: AllowAny
POST /api/auth/token/refresh/
Purpose: Obtain a new access token using a valid refresh token
Request Body:
{
"refresh": "string (required, refresh token)"
}
Success Response (200 OK):
{
"access": "eyJhbGc..."
}
Error Response (401 UNAUTHORIZED):
{
"detail": "Token is invalid or expired",
"code": "token_not_valid"
}
Implementation Details:
- Provided by
djangorestframework-simplejwtlibrary - Validates refresh token and issues new access token
- Does not issue a new refresh token (single refresh token lifecycle)
GoogleAuthView
Location: backend/accounts/views.py
Base Class: APIView
Permission: AllowAny (public access)
POST /api/auth/google/
Purpose: Authenticate user using Google OAuth token and return JWT tokens
Request Body:
{
"token": "string (required, Google OAuth ID token)"
}
Success Response (200 OK):
{
"access": "eyJhbGc...",
"refresh": "eyJhbGc..."
}
Error Responses:
400 BAD REQUEST:
{
"error": "Token is required"
}
401 UNAUTHORIZED:
{
"error": "Invalid token"
}
Implementation Details:
- Verifies Google OAuth ID token using
google.oauth2.id_token - Extracts user information (email, name) from verified token
- Creates new user if email doesn't exist, or retrieves existing user
- Automatically sets
is_email_verified=Truefor Google-authenticated users - Returns both access and refresh JWT tokens
- Requires valid Google OAuth Client ID configured in settings
Serializers
RegisterSerializer
Location: backend/accounts/serializers.py
Base Class: serializers.ModelSerializer
Purpose: Validate and create new user accounts
Model: User
Fields:
name(CharField)username(CharField)email(EmailField)password(CharField, write-only)
Extra Configuration:
extra_kwargs = {
"password": {"write_only": True}
}
Methods
create(validated_data)
Purpose: Create a new user with hashed password
Parameters:
validated_data(dict): Validated user data
Returns: User instance
Implementation:
- Calls
User.objects.create_user()to ensure password is hashed - Extracts username, email, password, and name from validated data
Utility Functions
generate_otp()
Location: backend/accounts/utils.py
Purpose: Generate a random 6-digit OTP for email verification
Parameters: None
Returns: str - 6-digit numeric string (e.g., "123456")
Implementation:
return str(random.randint(100000, 999999))
Usage: Called by SendOTPView to create verification codes
Configuration
Django Settings
Location: backend/core/settings.py
Installed Apps
django.contrib.admindjango.contrib.authdjango.contrib.contenttypesdjango.contrib.sessionsdjango.contrib.messagesdjango.contrib.staticfilesrest_frameworkcorsheadersrest_framework_simplejwt.token_blacklistaccounts
Database
- Engine: SQLite3
- Location:
backend/db.sqlite3
Email Configuration
- Backend:
django.core.mail.backends.smtp.EmailBackend - Host:
smtp.gmail.com - Port:
465 - SSL:
True - TLS:
False - From Email:
FinSight AI <oracleredbullracing.devsoc@gmail.com>
CORS Settings
- CORS_ALLOW_ALL_ORIGINS:
True
Custom User Model
- AUTH_USER_MODEL:
accounts.User
Authentication
JWT Configuration
Location: backend/core/settings.py
REST Framework Settings
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
}
JWT Token Settings
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=15),
"REFRESH_TOKEN_LIFETIME": timedelta(days=1),
"AUTH_HEADER_TYPES": ("Bearer",),
}
Token Lifetime:
- Access Token: 15 minutes
- Refresh Token: 1 day
Header Format:
Authorization: Bearer <access_token>
Authentication Flow
Registration:
- User registers with name, username, email, and password
- Account created but email NOT verified (
is_email_verified=False)
Email Verification:
- User requests OTP via
/api/auth/send-otp/ - OTP sent to registered email (valid for 5 minutes)
- User submits OTP via
/api/auth/verify-otp/ - Email verified (
is_email_verified=True)
- User requests OTP via
Login:
- User submits username/email and password
- System checks credentials and email verification status
- Returns access and refresh tokens if successful
Authenticated Requests:
- Client includes access token in
Authorizationheader - Access token valid for 15 minutes
- Client includes access token in
Token Refresh:
- Client submits refresh token to
/api/auth/token/refresh/ - Receives new access token (refresh token valid for 1 day)
- Client submits refresh token to
Logout:
- Client submits refresh token to
/api/auth/logout/ - Refresh token blacklisted and cannot be reused
- Client submits refresh token to
Application Configuration Files
WSGI Application
Location: backend/core/wsgi.py
Purpose: WSGI callable for production deployment
Exposed Variable: application (WSGI callable)
Environment Variable: DJANGO_SETTINGS_MODULE=core.settings
ASGI Application
Location: backend/core/asgi.py
Purpose: ASGI callable for asynchronous deployment
Exposed Variable: application (ASGI callable)
Environment Variable: DJANGO_SETTINGS_MODULE=core.settings
App Configurations
Accounts App
Location: backend/accounts/apps.py
Class: AccountsConfig
Name: accounts
API App
Location: backend/api/apps.py
Class: ApiConfig
Name: api
Status: Placeholder app with no models or views currently defined
URL Routing Structure
Root URLs
Location: backend/core/urls.py
urlpatterns = [
path("api/auth/", include("accounts.urls")),
]
Note: Django admin is not currently exposed in URL configuration
Accounts URLs
Location: backend/accounts/urls.py
All routes under /api/auth/ prefix:
urlpatterns = [
path("register/", RegisterView.as_view(), name="register"),
path("login/", LoginView.as_view(), name="login"),
path("me/", MeView.as_view(), name="me"),
path("send-otp/", SendOTPView.as_view()),
path("verify-otp/", VerifyOTPView.as_view()),
path("logout/", LogoutView.as_view(), name="logout"),
path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
path("google/", GoogleAuthView.as_view(), name="google-auth"),
]
Dependencies
Location: backend/requirements.txt
djangodjangorestframeworkdjango-cors-headersdjangorestframework-simplejwtpython-decouplerequestsgoogle-authgoogle-auth-oauthlib
Notes and Considerations
- Email Verification Required: Users cannot login until their email is verified via OTP
- OTP Expiration: OTPs are valid for 5 minutes only
- Token Expiration: Access tokens expire after 15 minutes; refresh tokens after 1 day
- Security: Passwords are hashed using Django's default password hasher
- CORS: Currently allows all origins (should be restricted in production)
- Database: Using SQLite for development (consider PostgreSQL for production)
- Email: Using Gmail SMTP (credentials exposed in settings.py - move to environment variables)
- Admin Panel: Not currently configured in URLs
End of Documentation