-
Notifications
You must be signed in to change notification settings - Fork 24
API documentation #149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Sparshagarwal29
wants to merge
14
commits into
Devasy23:main
Choose a base branch
from
Sparshagarwal29:api-docs
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
API documentation #149
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
2664528
creating the basic structure
Sparshagarwal29 d428853
authentication.md completed
Sparshagarwal29 292c972
expense.md
Sparshagarwal29 aa2c273
group.md
Sparshagarwal29 70b14e6
updated expenses.md
Sparshagarwal29 7d813db
settlements.md
Sparshagarwal29 9142607
user.md
Sparshagarwal29 6923578
readme.md
Sparshagarwal29 e931f48
example.login
Sparshagarwal29 bc10480
postman json
Sparshagarwal29 cb4961d
Fix: Address review comments from coderabbitai
Sparshagarwal29 bb3ff46
Merge branch 'main' into api-docs
Sparshagarwal29 3286c26
fiexed few more suggestions
Sparshagarwal29 67bc7f0
Merge branch 'api-docs' of https://github.com/Sparshagarwal29/splitwi…
Sparshagarwal29 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # Splitwiser API Documentation | ||
|
|
||
| Welcome to the official API documentation for the Splitwiser backend. This document provides a comprehensive guide to understanding and interacting with our API. | ||
|
|
||
| --- | ||
|
|
||
| ## 1. Introduction | ||
|
|
||
| The Splitwiser API is a modern, RESTful service built with FastAPI that powers the Splitwiser application. It provides a complete set of endpoints for managing users, groups, expenses, and settlements, with a focus on security, performance, and ease of use. | ||
|
|
||
| This documentation is divided into several modules, each covering a distinct area of the API's functionality. | ||
|
|
||
| --- | ||
|
|
||
| ## 2. General Concepts | ||
|
|
||
| ### **Authentication** | ||
|
|
||
| All API endpoints (with the exception of sign-up and login) are protected and require a valid **JSON Web Token (JWT)** to be included in the request. | ||
|
|
||
| * **Flow**: To access protected routes, you must first authenticate using one of the login endpoints to receive an `access_token`. This token must then be sent in the `Authorization` header of all subsequent requests with the `Bearer` scheme. | ||
| ``` | ||
| Authorization: Bearer <your_access_token> | ||
| ``` | ||
| * **Token Expiry**: Access tokens are short-lived. When one expires, you must use the provided `refresh_token` to obtain a new one. | ||
|
|
||
| For a complete guide on how to register, log in, and manage tokens, please see the detailed **[Authentication API Documentation](./authentication.md)**. | ||
|
|
||
| --- | ||
|
|
||
| ## 3. API Reference | ||
|
|
||
| The API is organized into logical modules. For detailed information on the endpoints, request/response models, and business logic for each module, please refer to the documents below. | ||
|
|
||
| * **[Authentication](./authentication.md)**: User sign-up, login (email & Google), and token management. | ||
| * **[Users](./users.md)**: Managing user profiles. | ||
| * **[Groups](./groups.md)**: Creating groups, managing membership, and handling roles. | ||
| * **[Expenses](./expenses.md)**: Creating, splitting, and managing expenses within groups. | ||
| * **[Settlements](./settlements.md)**: Managing debts, recording payments, and using the debt optimization engine. | ||
|
|
||
| --- | ||
|
|
||
| ## 4. Examples & Tools | ||
|
|
||
| To help you get started quickly, we provide practical examples and tools. | ||
|
|
||
| * **[cURL Examples](./examples/curl_examples.md)**: A collection of copy-pasteable `cURL` commands for interacting with the API from your terminal. | ||
| * **[Postman Collection](./examples/postman_collection.json)**: A comprehensive Postman collection that you can import to immediately start making requests to all available endpoints. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,270 @@ | ||
| # Authentication Service | ||
|
|
||
| ## Overview | ||
| The Authentication Service in Splitwiser handles secure user registration, login, and session management using JWT (JSON Web Tokens) with refresh token rotation for enhanced security. It supports multiple authentication providers, including email/password and Google OAuth.This documentation is based on the backend implementation in `/backend/app/auth`. | ||
|
|
||
| This document provides a complete and definitive specification for the authentication API endpoints, based on the final implementation code from `routes.py`, the data models from `schemas.py`, the cryptographic logic from `security.py`, the business logic from `service.py`, and the dependency logic from `dependencies.py`. | ||
|
|
||
| --- | ||
|
|
||
| ## 1. System Architecture & Core Concepts | ||
|
|
||
| ### **Security & Token Generation** | ||
|
|
||
| * **Password Hashing**: User passwords are never stored in plaintext. They are securely hashed using the **bcrypt** algorithm. | ||
| * **Access Tokens (JWT)**: Short-lived (15 min) JSON Web Tokens signed with the HS256 algorithm. They contain the user's ID (`sub`), an expiration timestamp (`exp`), and a `type` claim set to `"access"`. | ||
| * **Refresh Tokens**: Long-lived (30 days), cryptographically secure random strings used to obtain new access tokens. They are stored in the database and rotated upon use for enhanced security. | ||
| * **Password Reset Tokens**: Secure random strings with a short expiry (1 hour) used to authorize password changes. | ||
|
|
||
| ### **Database Collections** | ||
|
|
||
| The authentication system relies on three primary MongoDB collections: | ||
|
|
||
| 1. **`users`**: Stores core user profile information, including email, name, hashed password (for email-based auth), and the authentication provider (`email` or `google`). | ||
| 2. **`refresh_tokens`**: Tracks all active refresh tokens. Each record links a token to a `user_id`, includes an expiration date, and has a `revoked` flag to manage sessions. | ||
| 3. **`password_resets`**: Temporarily stores password reset tokens, linking them to a `user_id` with an expiration date and a `used` flag. | ||
|
|
||
| ### **Firebase Integration** | ||
|
|
||
| * The **Firebase Admin SDK** is used exclusively on the server-side to verify Google ID tokens. The application is initialized using credentials from environment variables or a service account file. | ||
|
|
||
| --- | ||
|
|
||
| ## 2. Dependencies | ||
|
|
||
| The auth module relies on: | ||
| - `fastapi.security`: For OAuth2PasswordBearer . | ||
| - `pydantic`: For request/response schemas model.(pydantic model) | ||
| - `jose`: For JWT encoding/decoding. | ||
| - `passlib`: For password hashing. | ||
| - `MongoDB driver`: (e.g.,`pymongo`) for user storage. | ||
|
|
||
| --- | ||
|
|
||
| ## 3. Data Models and Schemas | ||
|
|
||
| ### User Model (in `schemas.py`) | ||
| Represents a user in the database: | ||
|
|
||
| ### **Usage Example** | ||
|
|
||
| ```python | ||
|
|
||
| from pydantic import BaseModel, EmailStr | ||
| from typing import Optional | ||
|
|
||
| class User(BaseModel): | ||
| id: str = Field(alias="_id") | ||
| email: EmailStr #EmailStr to check the syntax of email | ||
| name: str | ||
| imageUrl: Optional[str] = None #Optional field | ||
| currency: str = "USD" | ||
| created_at: datetime | ||
| ``` | ||
|
|
||
| ### Token Schemas (in `schemas.py`) | ||
|
|
||
| ### **Usage Example** | ||
|
|
||
| ```python | ||
| class TokenData(BaseModel): | ||
| sub: str # The user's ID | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## 4.API Endpoints | ||
|
|
||
| All endpoints are prefixed with `/auth` via an APIRouter in `routes.py`. | ||
|
|
||
| ### **`POST /signup/email`** | ||
| **Description**: Registers a new user with their email, password, and name and returns authentication tokens and user information. | ||
|
|
||
| **Parameters**: | ||
| - Request Body (JSON): | ||
| - `email`: string (required, valid email) | ||
| - `password`: string (required) | ||
| - `name` : string (required) | ||
|
|
||
| **Request BODY** (`EmailSignupRequest`): | ||
| ```json | ||
| { | ||
| "email": "user@example.com", | ||
| "password": "a-strong-password", // min_length: 6 | ||
| "name": "John Doe" // min_length: 1 | ||
| } | ||
| ``` | ||
|
|
||
| **Responses** (`AuthResponse`): | ||
| - Note: AuthResponse conatin another pydhantic model : `UserResponse` | ||
| - 201 Created: Successful registration. | ||
| ```json | ||
| { | ||
| "access_token": "your_access_token_jwt", | ||
| "refresh_token": "your_refresh_token", | ||
| "user": { | ||
| "id": "mongodb_user_id", | ||
| "email": "user@example.com", | ||
| "name": "John Doe", | ||
| "imageUrl": null, | ||
| "currency": "USD", | ||
| "created_at": "2025-08-12T18:49:48.000Z" | ||
| } | ||
| } | ||
| ``` | ||
| - 400 Bad Request: User already exists or invalid input. | ||
| - 422 Unprocessable Entity: Validation error (e.g., invalid email). | ||
|
|
||
| **Authentication**: None. | ||
|
|
||
| ### **`POST /login/email`** | ||
| **Description**: Authenticates a user with email and password. Verifies credentials, generates JWT tokens, and adds a new session. | ||
|
|
||
| **Parameters**: | ||
| - Request Body (JSON): | ||
| - `email`: string (required) | ||
| - `password`: string (required) | ||
|
|
||
| **Request Example**: | ||
| * **Request Body** (`EmailLoginRequest`): | ||
| ```json | ||
| { | ||
| "email": "user@example.com", | ||
| "password": "the-correct-password" | ||
| } | ||
| ``` | ||
| * **Response** (`AuthResponse`): The response format is identical to the sign-up endpoint. | ||
|
|
||
| Error : | ||
| - 500 if authentication fails due to an unexpected error | ||
|
|
||
|
|
||
| ### **`POST /login/google`** | ||
| **Description**: Handles Google OAuth login. Validates the Google ID token, creates or logs in the user, and returns Splitwiser access and refresh tokens. | ||
|
|
||
| **Parameters**: | ||
| - Request Body (JSON): | ||
| - `GoogleLoginRequest`: string (required, Google ID token) | ||
|
|
||
|
|
||
| * **Request Body** (`GoogleLoginRequest`): | ||
| ```json | ||
| { | ||
| "id_token": "google_id_token_from_client" | ||
| } | ||
| ``` | ||
| * **Response** (`AuthResponse`): The response format is identical to the sign-up endpoint. | ||
|
|
||
| - 500 If Google authentication fails. | ||
|
|
||
|
|
||
| ### **`POST /refresh`** | ||
| **Description**: Refreshes the access token using a valid refresh token. Rotates the refresh token and updates the session. | ||
|
|
||
| **Parameters**: | ||
| - Request Body (JSON): | ||
| - `RefreshTokenRequest`: string (required) | ||
|
|
||
| * **Request Body** (`RefreshTokenRequest`): | ||
| ```json | ||
| { | ||
| "refresh_token": "the_valid_refresh_token" | ||
| } | ||
| ``` | ||
|
|
||
| * **Response** (`TokenResponse`): | ||
| - 200 OK: New tokens issued. | ||
| ```json | ||
| { | ||
| "access_token": "your_new_access_token", | ||
| "refresh_token": "your_new_rotated_refresh_token" | ||
| } | ||
| ``` | ||
| - 401 Unauthorized: Invalid or expired refresh token. | ||
|
|
||
| ### **`POST /token/verify`** | ||
| **Description**: Verifies an access token and returns the corresponding user's information. | ||
| * **Request Body** (`TokenVerifyRequest`): | ||
| ```json | ||
| { | ||
| "access_token": "the_access_token_to_verify" | ||
| } | ||
| ``` | ||
| * **Response** (`UserResponse`): | ||
| ```json | ||
| { | ||
| "id": "mongodb_user_id", | ||
| "email": "user@example.com", | ||
| "name": "John Doe", | ||
| "imageUrl": "url_to_avatar_or_null", | ||
| "currency": "USD", | ||
| "created_at": "2025-08-12T18:49:48.000Z" | ||
| } | ||
| ``` | ||
|
|
||
| ### **`POST /password/reset/request`** | ||
| **Description**: Initiates the password reset process for a user.Initiates a password reset process by sending a reset link to the provided email address. | ||
|
|
||
| * **Request Body** (`PasswordResetRequest`): | ||
| ```json | ||
| { | ||
| "email": "user-who-forgot-password@example.com" | ||
| } | ||
| ``` | ||
| * **Response** (`SuccessResponse`): | ||
| ```json | ||
| { | ||
| "success": true, | ||
| "message": "If the email exists, a reset link has been sent" | ||
| } | ||
| ``` | ||
| ### **`POST /password/reset/confirm`** | ||
|
|
||
| Sets a new password for a user using a valid reset token. | ||
|
|
||
| * **Request Body** (`PasswordResetConfirm`): | ||
| ```json | ||
| { | ||
| "reset_token": "the_token_from_the_reset_email", | ||
| "new_password": "a_new_strong_password" // min_length: 6 | ||
| } | ||
| ``` | ||
| * **Response** (`SuccessResponse`): | ||
| ```json | ||
| { | ||
| "success": true, | ||
| "message": "Password has been reset successfully" | ||
| } | ||
|
|
||
| - 400 Bad Request: Invalid or expired reset token. | ||
|
|
||
|
|
||
| ## Authentication Flow | ||
|
|
||
| 1. **Registration/Login**: User sends credentials to /signup or /login. Server validates, creates/hashes, and issues tokens. | ||
| 2. **Protected Routes**: Use `Depends(get_current_user)` in FastAPI, which verifies the access token. | ||
| 3. **Token Refresh**: Client monitors access token expiry and calls /refresh with refresh token. | ||
| 4. **Rotation**: On refresh, new refresh token is issued, old one invalidated. | ||
| 5. **Google OAuth**: Client gets Google token, sends to server. Server verifies with Google API, links to user. | ||
|
|
||
| ## Error Codes | ||
|
|
||
| - 400: Bad request (e.g., duplicate email). | ||
| - 401: Unauthorized (invalid credentials/token). | ||
| - 403: Forbidden (inactive user). | ||
| - 422: Validation error (Pydantic errors). | ||
| - 500: Internal server error. | ||
|
|
||
| ## Common Use Cases | ||
|
|
||
| - **New User Signup**: POST /auth/signup/email → Receive tokens → Use access token for API calls. | ||
| - **Existing User Login**: POST /auth/login/email → Tokens. | ||
| - **Google Sign-In**: Integrate with Google SDK on frontend, send token to /auth/google/login. | ||
| - **Session Refresh**: When access token expires, use refresh token to get new pair. | ||
|
|
||
| ## Security Considerations | ||
|
|
||
| - Store access tokens in memory (not localStorage for web). | ||
| - Regularly rotate secrets for JWT signing. | ||
|
|
||
| For more details on the overall API, see `micro-plan.md`. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify field naming consistency (snake_case vs camelCase)
Users in this doc use created_at (snake_case) while other resources (e.g., settlements) use createdAt (camelCase). Please verify what the backend actually returns for user payloads and align docs consistently.
Run this script to check user schema/response conventions in the backend:
Also applies to: 111-112, 200-202
🏁 Script executed:
Length of output: 17782
🏁 Script executed:
Length of output: 23496
Fix: unify user timestamp field casing (createdAt vs created_at)
Verified: the codebase is inconsistent — user endpoints return camelCase timestamps, while auth responses use snake_case and the docs currently show snake_case. Please standardize.
Findings (verified):
Recommended minimal fixes:
Prefer camelCase (createdAt) to match most existing resources (groups/expenses/etc.). Update auth schema to expose camelCase while accepting current DB field:
Change in backend/app/auth/schemas.py:
Before
After
This accepts the DB key created_at but exposes createdAt in API responses, keeping backwards-safe population and aligning with other resources.
Update docs/api/authentication.md examples to use createdAt / updatedAt (camelCase).
Optional: consider normalizing service code to consistently return the same shape (e.g., reuse user_service.transform_user_document in auth flows) to avoid future drift.
Files to update:
🤖 Prompt for AI Agents