From 266452898ec414a460c63a309a7d4443d4f58926 Mon Sep 17 00:00:00 2001 From: Sparshagarwal29 Date: Tue, 12 Aug 2025 14:53:28 +0530 Subject: [PATCH 01/12] creating the basic structure --- docs/api/README.md | 0 docs/api/authentication.md | 0 docs/api/examples/curl_examples.md | 0 docs/api/examples/postman_collection.json | 0 docs/api/expenses.md | 0 docs/api/groups.md | 0 docs/api/settlements.md | 0 docs/api/users.md | 0 8 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/api/README.md create mode 100644 docs/api/authentication.md create mode 100644 docs/api/examples/curl_examples.md create mode 100644 docs/api/examples/postman_collection.json create mode 100644 docs/api/expenses.md create mode 100644 docs/api/groups.md create mode 100644 docs/api/settlements.md create mode 100644 docs/api/users.md diff --git a/docs/api/README.md b/docs/api/README.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/api/authentication.md b/docs/api/authentication.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/api/examples/curl_examples.md b/docs/api/examples/curl_examples.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/api/examples/postman_collection.json b/docs/api/examples/postman_collection.json new file mode 100644 index 00000000..e69de29b diff --git a/docs/api/expenses.md b/docs/api/expenses.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/api/groups.md b/docs/api/groups.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/api/settlements.md b/docs/api/settlements.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/api/users.md b/docs/api/users.md new file mode 100644 index 00000000..e69de29b From d4288537ce375d292fde64d923b4bebba0c28c2f Mon Sep 17 00:00:00 2001 From: Sparshagarwal29 Date: Wed, 13 Aug 2025 00:01:54 +0530 Subject: [PATCH 02/12] authentication.md completed --- docs/api/authentication.md | 271 +++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) diff --git a/docs/api/authentication.md b/docs/api/authentication.md index e69de29b..83bf2b94 100644 --- a/docs/api/authentication.md +++ b/docs/api/authentication.md @@ -0,0 +1,271 @@ +# 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 token, creates or logs in the user based on Google ID, and issue OAuth ID token + +**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.Issues a new access token and refresh token if valid, and returns them + +* **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 Unauthorized: Invalid or expired refresh 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`. \ No newline at end of file From 292c972dc552c8edccf5dd51e7b464ac29a94cb2 Mon Sep 17 00:00:00 2001 From: Sparshagarwal29 Date: Thu, 14 Aug 2025 16:34:39 +0530 Subject: [PATCH 03/12] expense.md --- docs/api/expenses.md | 203 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) diff --git a/docs/api/expenses.md b/docs/api/expenses.md index e69de29b..4ca72c8f 100644 --- a/docs/api/expenses.md +++ b/docs/api/expenses.md @@ -0,0 +1,203 @@ +# Expenses & Settlements API Documentation + +This document provides a complete and definitive specification for the API endpoints related to managing expenses, settlements, balances, and analytics within groups. All endpoints require authentication and proper group membership. + +--- + +## 1. Core Concepts & Business Logic + +### **Expenses vs. Settlements** + +* **Expense**: A single financial event, like "Dinner for $100," detailing who paid and how the cost is split among members. +* **Settlement**: A record of a specific debt created from an expense, such as "Alice owes Bob $50." When an expense is created, a settlement record is generated for each person who owes money. Manual settlements can also be created to record cash payments. + +```python +# Algorithm steps: +1. Calculate net balance for each user (indegree - outdegree) +2. Sort users into debtors (positive balance) and creditors (negative balance) +3. Use two-pointer approach to match highest debtor with highest creditor +4. Continue until all balances are settled +``` + +### **Debt Optimization Algorithms** + +The system uses two algorithms to simplify group debts into the minimum number of payments. This is a core feature for settling up. + +* **Normal (`algorithm=normal`)**: A basic simplification that only nets out direct debts between two people. If Alice owes Bob $20 and Bob owes Alice $15, it simplifies to "Alice pays Bob $5." +* **Advanced (`algorithm=advanced`)**: A powerful graph-based algorithm that minimizes the total number of transactions for the entire group. It calculates the net balance of every member, separates them into "debtors" and "creditors," and then matches them to clear all debts with the fewest possible payments. + +### **Database Collections** + +* **`expenses`**: Stores all expense documents, including descriptions, amounts, splits, and history. +* **`settlements`**: Stores all individual debt records generated from expenses or created manually. +* **`groups`** & **`users`**: Used to verify user membership, permissions, and retrieve user details like names for responses. + +--- + +## 2. Expense Management + +These endpoints handle the creation, retrieval, updating, and deletion of expenses. All endpoints are prefixed with `/groups/{group_id}`. + +### **`POST /expenses`** + +Creates a new expense within a specified group. + +* **Server-Side Logic**: + 1. Verifies the user is a member of the group. + 2. Creates the expense document in the `expenses` collection. + 3. Generates corresponding `pending` settlement records for each person who owes money. + 4. Returns the new expense object along with the generated settlements and a group summary. +* **Request Body** (`ExpenseCreateRequest`): + + ### example usage: + + ```json + { + "description": "Team Dinner", // max_length=500 + "amount": 150.75, + "splits": [ + { "userId": "user_id_1", "amount": 50.25, "type": "equal" }, + { "userId": "user_id_2", "amount": 100.50, "type": "unequal" } + ], + "splitType": "unequal", + "paidBy": "user_id_2", //User ID of who paid for the expense + "tags": ["food", "social"], + "receiptUrls": ["https://www.ramacheif.com/receipt/1234567890"] + } + ``` +* **Response** (`ExpenseCreateResponse`): + + ### example usage: + + ```json + { + "expense": { /* ... ExpenseResponse object ... */ }, + "settlements": [ /* ... list of Settlement objects ... */ ], + "groupSummary": { /* ... GroupSummary object ... */ } + } + ``` + +### **`GET /expenses`** + +Lists all expenses for a group with support for pagination and filtering. + +* **Query Parameters**: + * `page`, `limit`, `from`, `to`, `tags`. +* **Response** (`ExpenseListResponse`): + ```json + { + "expenses": [ /* ... list of ExpenseResponse objects ... */ ], + "pagination": { /* ... pagination details ... */ }, + "summary": { "totalAmount": 1234.56, "expenseCount": 50, "avgExpense": 24.69 } + } + ``` + +### **`GET /expenses/{expense_id}`** + +Retrieves the details for a single expense and its related settlements. + +* **Response**: A dictionary containing the `ExpenseResponse` object and a list of all `Settlement` objects associated with it. + +### **`PATCH /expenses/{expense_id}`** + +Updates an existing expense. + +* **Server-Side Logic**: + 1. Verifies that the user attempting the update is the one who originally created the expense. + 2. Creates a history entry to log the changes. + 3. If the amount or splits are modified, it deletes all old settlements for that expense and recalculates new ones. +* **Request Body** (`ExpenseUpdateRequest`): + ```json + { + "description": "Updated description for groceries", + "tags": ["household", "urgent"] + } + ``` +* **Response** (`ExpenseResponse`): Returns the complete, updated expense object. + +### **`DELETE /expenses/{expense_id}`** + +Deletes an expense. + +* **Server-Side Logic**: + 1. Verifies the user is the creator of the expense. + 2. Deletes all associated settlement records. + 3. Deletes the expense document itself. +* **Successful Response**: `{"success": True}` + +--- + +## 3. Settlement Management + +### **`POST /settlements`** + +Manually records a payment settlement between two users. This is for tracking payments made outside the app (e.g., cash). + +* **Request Body** (`SettlementCreateRequest`): + ```json + { + "payer_id": "user_id_1", + "payee_id": "user_id_2", + "amount": 25.00, + "description": "Paid back for coffee" + } + ``` +* **Response** (`Settlement`): Returns the newly created `completed` settlement object. + +### **`GET /settlements`** + +Retrieves a list of both pending and optimized settlements for a group. + +* **Response** (`SettlementListResponse`): Contains a list of raw settlements, a list of `OptimizedSettlement` objects, and a summary. + +### **`PATCH /settlements/{settlement_id}`** + +Updates the status of a settlement (e.g., marks it as paid). + +* **Request Body** (`SettlementUpdateRequest`): + ```json + { + "status": "completed", + "paidAt": "2025-08-13T14:00:00Z" + } + ``` +* **Response** (`Settlement`): Returns the updated settlement object. + +### **`POST /settlements/optimize`** + +Calculates and returns the most efficient way to settle all debts in a group. + +* **Query Parameters**: + * `algorithm`: `normal` or `advanced` (default). +* **Response** (`OptimizedSettlementsResponse`): + ```json + { + "optimizedSettlements": [ /* ... list of OptimizedSettlement objects ... */ ], + "savings": { + "originalTransactions": 15, + "optimizedTransactions": 4, + "reductionPercentage": 73.3 + } + } + ``` + +--- + +## 4. Balance & Analytics Endpoints + +### **User-Centric Balances (prefixed with `/users/me`)** + +* **`GET /friends-balance`**: Retrieves the current user's aggregated net balance with every friend across all shared groups. +* **`GET /balance-summary`**: Retrieves the user's overall financial summary: total amount owed to them, total amount they owe, and a breakdown of their balance in each group. + +### **Group-Specific Balances & Analytics (prefixed with `/groups/{group_id}`)** + +* **`GET /users/{user_id}/balance`**: Gets a specific user's detailed balance within one particular group. +* **`GET /analytics`**: Provides detailed expense analytics for the group over a specified period (`week`, `month`, `year`), including total spend, top categories, member contributions, and daily spending trends. + +--- + +## 5. Expense Attachments + +* **`POST /expenses/{expense_id}/attachments`**: Uploads a file (e.g., a receipt) for an expense. +* **`GET /expenses/{expense_id}/attachments/{key}`**: Downloads a previously uploaded file. *(Note: Not fully implemented).* From aa2c27346eaae3356e4dadee1b3bb874448f40ed Mon Sep 17 00:00:00 2001 From: Sparshagarwal29 Date: Thu, 14 Aug 2025 16:46:55 +0530 Subject: [PATCH 04/12] group.md --- docs/api/groups.md | 199 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) diff --git a/docs/api/groups.md b/docs/api/groups.md index e69de29b..cc199f20 100644 --- a/docs/api/groups.md +++ b/docs/api/groups.md @@ -0,0 +1,199 @@ +# Group API Documentation + +This document provides a complete and definitive specification for the API endpoints related to creating, managing, and interacting with groups. All endpoints require authentication. + +--- + +## 1. Core Concepts & Business Logic + +### **Group Roles** + +* **`admin`**: Has full permissions to manage the group, including updating its details, deleting it, and managing its members (updating roles, removing users). +* **`member`**: Can participate in the group (e.g., add expenses) but cannot perform administrative actions. + +### **Join Codes** + +* When a group is created, a unique, 6-character alphanumeric **join code** is automatically generated. This code is case-insensitive and is the primary mechanism for new users to join a private group. + +### **Database Collections** + +* **`groups`**: Stores the core group documents, including name, currency, and a list of member sub-documents. +* **`users`**: Used to enrich member data, fetching details like names and emails to display in group member lists. +* **`settlements`**: Queried to perform safety checks, specifically to prevent a user from leaving a group or being removed if they have outstanding debts. + +--- + +## 2. Group Management + +These endpoints handle the core CRUD (Create, Read, Update, Delete) operations for groups. All endpoints are prefixed with `/groups`. + +### **`POST /`** + +Creates a new group. + +* **Server-Side Logic**: + 1. Generates a unique, random 6-character join code. + 2. Creates a new group document in the `groups` collection. + 3. The user who creates the group is automatically added as the first member with the `admin` role. +* **Request Body** (`GroupCreateRequest`): + ```json + { + "name": "Trip to the Mountains", + "currency": "EUR", + "imageUrl": "[https://example.com/mountains.png](https://example.com/mountains.png)" + } + ``` +* **Response** (`GroupResponse`): + ```json + { + "id": "group_id_string", + "name": "Trip to the Mountains", + "currency": "EUR", + "joinCode": "UNIQUE_JOIN_CODE", + "createdBy": "user_id_of_creator", + "createdAt": "2025-08-14T12:00:00Z", + "imageUrl": "[https://example.com/mountains.png](https://example.com/mountains.png)", + "members": [ /* ... list of GroupMemberWithDetails ... */ ] + } + ``` + +### **`GET /`** + +Lists all groups that the current user is a member of. + +* **Response** (`GroupListResponse`): + ```json + { + "groups": [ + { /* ... GroupResponse object 1 ... */ }, + { /* ... GroupResponse object 2 ... */ } + ] + } + ``` + +### **`GET /{group_id}`** + +Retrieves the details for a single group, including its members. + +* **Server-Side Logic**: + 1. Verifies the current user is a member of the requested group. + 2. Fetches the group document. + 3. Enriches the `members` list by fetching the name, email, and image URL for each member from the `users` collection. +* **Response** (`GroupResponse`): Returns the full, enriched group object. + +### **`PATCH /{group_id}`** + +Updates a group's metadata. + +* **Permissions**: Admin only. +* **Request Body** (`GroupUpdateRequest`): + ```json + { + "name": "Awesome Trip to the Mountains" + } + ``` +* **Response** (`GroupResponse`): Returns the complete, updated group object. + +### **`DELETE /{group_id}`** + +Deletes an entire group. + +* **Permissions**: Admin only. +* **Response** (`DeleteGroupResponse`): + ```json + { + "success": true, + "message": "Group deleted successfully" + } + ``` + +--- + +## 3. Group Membership + +### **`POST /join`** + +Allows a user to join an existing group using a unique join code. + +* **Server-Side Logic**: + 1. Finds the group associated with the provided `joinCode`. + 2. Checks to ensure the user is not already a member. + 3. Adds the user to the group's `members` list with the default `member` role. +* **Request Body** (`JoinGroupRequest`): + ```json + { + "joinCode": "UNIQUE_JOIN_CODE" + } + ``` +* **Response** (`JoinGroupResponse`): + ```json + { + "group": { /* ... GroupResponse object for the joined group ... */ } + } + ``` + +### **`POST /{group_id}/leave`** + +Allows a user to leave a group. + +* **Server-Side Logic**: + 1. Verifies the user is a member of the group. + 2. **Safety Check**: Queries the `settlements` collection to ensure the user has no `pending` debts. If they do, the request is rejected with a `400 Bad Request`. + 3. **Safety Check**: Prevents the last admin from leaving the group, ensuring the group is not left without an administrator. + 4. Removes the user from the group's `members` list. +* **Response** (`LeaveGroupResponse`): + ```json + { + "success": true, + "message": "Successfully left the group" + } + ``` + +### **`GET /{group_id}/members`** + +Retrieves a detailed list of all members in a specific group. + +* **Response**: A list of `GroupMemberWithDetails` objects, enriched with user information. + ```json + [ + { + "userId": "user_id_1", + "role": "admin", + "joinedAt": "2025-08-14T12:00:00Z", + "user": { "name": "Alice", "email": "alice@example.com", "imageUrl": null } + } + ] + ``` + +### **`PATCH /{group_id}/members/{member_id}`** + +Updates the role of a specific member within a group. + +* **Permissions**: Admin only. +* **Safety Check**: Prevents an admin from demoting themselves if they are the only admin in the group. +* **Request Body** (`MemberRoleUpdateRequest`): + ```json + { + "role": "admin" + } + ``` +* **Response**: `{"message": "Member role updated to admin"}` + +### **`DELETE /{group_id}/members/{member_id}`** + +Removes a member from a group. + +* **Permissions**: Admin only. +* **Server-Side Logic**: + 1. Verifies the requesting user is an admin. + 2. Ensures an admin is not trying to remove themselves (they must use the `/leave` endpoint instead). + 3. **Safety Check**: Queries the `settlements` collection to ensure the member being removed has no `pending` debts. If they do, the request is rejected. + 4. Removes the member from the group. +* **Response** (`RemoveMemberResponse`): + ```json + { + "success": true, + "message": "Member removed successfully" + } + + From 70b14e6a322e9549345b32ebb1b4a98a9a527f9d Mon Sep 17 00:00:00 2001 From: Sparshagarwal29 Date: Thu, 14 Aug 2025 17:01:38 +0530 Subject: [PATCH 05/12] updated expenses.md --- docs/api/expenses.md | 113 +++++++------------------------------------ 1 file changed, 18 insertions(+), 95 deletions(-) diff --git a/docs/api/expenses.md b/docs/api/expenses.md index 4ca72c8f..a9f848da 100644 --- a/docs/api/expenses.md +++ b/docs/api/expenses.md @@ -1,36 +1,23 @@ -# Expenses & Settlements API Documentation +# Expenses API Documentation -This document provides a complete and definitive specification for the API endpoints related to managing expenses, settlements, balances, and analytics within groups. All endpoints require authentication and proper group membership. +This document provides a detailed specification for the API endpoints related to managing expenses, attachments, balances, and analytics within groups. All endpoints require authentication and proper group membership. + +*For details on how debts are calculated, simplified, and paid, please see the **Settlements.md** --- ## 1. Core Concepts & Business Logic -### **Expenses vs. Settlements** - -* **Expense**: A single financial event, like "Dinner for $100," detailing who paid and how the cost is split among members. -* **Settlement**: A record of a specific debt created from an expense, such as "Alice owes Bob $50." When an expense is created, a settlement record is generated for each person who owes money. Manual settlements can also be created to record cash payments. - -```python -# Algorithm steps: -1. Calculate net balance for each user (indegree - outdegree) -2. Sort users into debtors (positive balance) and creditors (negative balance) -3. Use two-pointer approach to match highest debtor with highest creditor -4. Continue until all balances are settled -``` - -### **Debt Optimization Algorithms** - -The system uses two algorithms to simplify group debts into the minimum number of payments. This is a core feature for settling up. +### **Core Concept: Expenses** -* **Normal (`algorithm=normal`)**: A basic simplification that only nets out direct debts between two people. If Alice owes Bob $20 and Bob owes Alice $15, it simplifies to "Alice pays Bob $5." -* **Advanced (`algorithm=advanced`)**: A powerful graph-based algorithm that minimizes the total number of transactions for the entire group. It calculates the net balance of every member, separates them into "debtors" and "creditors," and then matches them to clear all debts with the fewest possible payments. +* An **Expense** is a single financial event, like "Dinner for $100," that details who paid and how the cost is split among members. +* When an expense is created, the system automatically calculates the resulting debts for each member. These debts are recorded as **Settlements**. ### **Database Collections** -* **`expenses`**: Stores all expense documents, including descriptions, amounts, splits, and history. -* **`settlements`**: Stores all individual debt records generated from expenses or created manually. -* **`groups`** & **`users`**: Used to verify user membership, permissions, and retrieve user details like names for responses. +* **`expenses`**: Stores all expense documents, including descriptions, amounts, splits, and a history of edits. +* **`groups`** & **`users`**: Used to verify user membership, permissions, and retrieve user details. +* **`settlements`**: This collection is used to record the individual debts that result from expenses. --- @@ -45,30 +32,23 @@ Creates a new expense within a specified group. * **Server-Side Logic**: 1. Verifies the user is a member of the group. 2. Creates the expense document in the `expenses` collection. - 3. Generates corresponding `pending` settlement records for each person who owes money. - 4. Returns the new expense object along with the generated settlements and a group summary. + 3. Automatically calculates and records the resulting debts (settlements). + 4. Returns the new expense object, the calculated settlements, and a group summary. * **Request Body** (`ExpenseCreateRequest`): - - ### example usage: - ```json { - "description": "Team Dinner", // max_length=500 + "description": "Team Dinner", "amount": 150.75, "splits": [ { "userId": "user_id_1", "amount": 50.25, "type": "equal" }, { "userId": "user_id_2", "amount": 100.50, "type": "unequal" } ], "splitType": "unequal", - "paidBy": "user_id_2", //User ID of who paid for the expense - "tags": ["food", "social"], - "receiptUrls": ["https://www.ramacheif.com/receipt/1234567890"] + "paidBy": "user_id_2", + "tags": ["food", "social"] } ``` * **Response** (`ExpenseCreateResponse`): - - ### example usage: - ```json { "expense": { /* ... ExpenseResponse object ... */ }, @@ -105,7 +85,7 @@ Updates an existing expense. * **Server-Side Logic**: 1. Verifies that the user attempting the update is the one who originally created the expense. 2. Creates a history entry to log the changes. - 3. If the amount or splits are modified, it deletes all old settlements for that expense and recalculates new ones. + 3. If the amount or splits are modified, it automatically recalculates the associated settlements. * **Request Body** (`ExpenseUpdateRequest`): ```json { @@ -127,63 +107,7 @@ Deletes an expense. --- -## 3. Settlement Management - -### **`POST /settlements`** - -Manually records a payment settlement between two users. This is for tracking payments made outside the app (e.g., cash). - -* **Request Body** (`SettlementCreateRequest`): - ```json - { - "payer_id": "user_id_1", - "payee_id": "user_id_2", - "amount": 25.00, - "description": "Paid back for coffee" - } - ``` -* **Response** (`Settlement`): Returns the newly created `completed` settlement object. - -### **`GET /settlements`** - -Retrieves a list of both pending and optimized settlements for a group. - -* **Response** (`SettlementListResponse`): Contains a list of raw settlements, a list of `OptimizedSettlement` objects, and a summary. - -### **`PATCH /settlements/{settlement_id}`** - -Updates the status of a settlement (e.g., marks it as paid). - -* **Request Body** (`SettlementUpdateRequest`): - ```json - { - "status": "completed", - "paidAt": "2025-08-13T14:00:00Z" - } - ``` -* **Response** (`Settlement`): Returns the updated settlement object. - -### **`POST /settlements/optimize`** - -Calculates and returns the most efficient way to settle all debts in a group. - -* **Query Parameters**: - * `algorithm`: `normal` or `advanced` (default). -* **Response** (`OptimizedSettlementsResponse`): - ```json - { - "optimizedSettlements": [ /* ... list of OptimizedSettlement objects ... */ ], - "savings": { - "originalTransactions": 15, - "optimizedTransactions": 4, - "reductionPercentage": 73.3 - } - } - ``` - ---- - -## 4. Balance & Analytics Endpoints +## 3. Balance & Analytics Endpoints ### **User-Centric Balances (prefixed with `/users/me`)** @@ -197,7 +121,6 @@ Calculates and returns the most efficient way to settle all debts in a group. --- -## 5. Expense Attachments +## 4. Expense Attachments * **`POST /expenses/{expense_id}/attachments`**: Uploads a file (e.g., a receipt) for an expense. -* **`GET /expenses/{expense_id}/attachments/{key}`**: Downloads a previously uploaded file. *(Note: Not fully implemented).* From 7d813dbc520c1ec3ae39a5f1e26fb97bbaa8d4b6 Mon Sep 17 00:00:00 2001 From: Sparshagarwal29 Date: Thu, 14 Aug 2025 17:39:21 +0530 Subject: [PATCH 06/12] settlements.md --- docs/api/settlements.md | 137 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/docs/api/settlements.md b/docs/api/settlements.md index e69de29b..c374d693 100644 --- a/docs/api/settlements.md +++ b/docs/api/settlements.md @@ -0,0 +1,137 @@ +# Settlements API Documentation + +This document provides a complete and definitive specification for the API endpoints related to managing, optimizing, and recording settlements (debts) within groups. All endpoints require authentication. + +--- + +## 1. Core Concepts & Business Logic + +### **What is a Settlement?** + +A **Settlement** is a record of a specific debt between two users. It represents the fact that one person (the payee) owes another person (the payer) a certain amount of money. Settlements are the fundamental building blocks for tracking who owes whom in the application. + +* **Automatic Settlements**: When an expense is created, the system automatically generates a `pending` settlement record for each person who owes a share of the cost. +* **Manual Settlements**: Users can manually record a `completed` settlement to track a payment made outside the application (e.g., paying someone back in cash). + +### **Debt Optimization Algorithms** + +The system's most powerful feature is its ability to simplify all the individual debts in a group into the minimum number of payments required to clear all balances. This is handled by two distinct algorithms: + +* **Normal (`algorithm=normal`)**: A basic simplification that only nets out direct, two-way debts. For example, if Alice owes Bob $20 from one expense and Bob owes Alice $15 from another, this algorithm simplifies it to a single settlement: "Alice pays Bob $5." +* **Advanced (`algorithm=advanced`)**: A more powerful graph-based algorithm that minimizes the total number of transactions for the entire group. + * **Logic**: + 1. It calculates the net balance of every member (total paid - total owed). + 2. It separates all members into two lists: "debtors" (who owe money) and "creditors" (who are owed money). + 3. Using a two-pointer approach, it matches the person who owes the most with the person who is owed the most, creating a single payment to clear as much debt as possible. + 4. This process continues until all debts are consolidated into the fewest possible transactions. + +--- + +## 2. Settlement Management Endpoints + +These endpoints are for recording and managing payments between group members to settle debts. All endpoints are prefixed with `/groups/{group_id}`. + +### **`POST /settlements`** + +Manually records a payment settlement between two users. This is for tracking payments made outside the app. + +* **Server-Side Logic**: + 1. Verifies the current user is a member of the group. + 2. Creates a new settlement document in the `settlements` collection with a status of `completed`. +* **Request Body** (`SettlementCreateRequest`): + ```json + { + "payer_id": "user_id_1", + "payee_id": "user_id_2", + "amount": 25.00, + "description": "Paid back for coffee", + "paidAt": "2025-08-14T10:00:00Z" + } + ``` +* **Response** (`Settlement`): Returns the newly created `completed` settlement object. + +### **`GET /settlements`** + +Retrieves a list of both pending and optimized settlements for a group. + +* **Query Parameters**: + * `status`: Optional filter for settlement status (e.g., "pending"). + * `page` & `limit`: For paginating through the list of raw settlements. + * `algorithm`: The settlement algorithm to use (`normal` or `advanced`). +* **Response** (`SettlementListResponse`): + ```json + { + "settlements": [ /* ... list of raw Settlement objects ... */ ], + "optimizedSettlements": [ /* ... list of OptimizedSettlement objects ... */ ], + "summary": { /* ... summary dictionary ... */ }, + "pagination": { /* ... pagination details ... */ } + } + ``` + +### **`GET /settlements/{settlement_id}`** + +Retrieves the details for a single settlement. + +* **Response** (`Settlement`): + ```json + { + "id": "settlement_id_string", + "expenseId": "expense_id_string_or_null", + "groupId": "group_id_string", + "payerId": "user_id_1", + "payeeId": "user_id_2", + "payerName": "Alice", + "payeeName": "Bob", + "amount": 50.25, + "status": "pending", + "description": "Share for Team Dinner", + "paidAt": null, + "createdAt": "2025-08-13T12:00:00Z" + } + ``` + +### **`PATCH /settlements/{settlement_id}`** + +Updates the status of a settlement, typically to mark it as paid. + +* **Request Body** (`SettlementUpdateRequest`): + ```json + { + "status": "completed", + "paidAt": "2025-08-14T14:00:00Z" + } + ``` +* **Response** (`Settlement`): Returns the updated settlement object. + +### **`DELETE /settlements/{settlement_id}`** + +Deletes or undoes a recorded settlement. + +* **Successful Response**: `{"success": True, "message": "Settlement record deleted successfully."}` + +### **`POST /settlements/optimize`** + +Calculates and returns the most efficient way to settle all debts in a group. + +* **Query Parameters**: + * `algorithm`: `normal` or `advanced` (default). +* **Response** (`OptimizedSettlementsResponse`): + ```json + { + "optimizedSettlements": [ + { + "fromUserId": "user_id_A", + "toUserId": "user_id_B", + "fromUserName": "Charlie", + "toUserName": "David", + "amount": 75.50, + "consolidatedExpenses": [] + } + ], + "savings": { + "originalTransactions": 15, + "optimizedTransactions": 4, + "reductionPercentage": 73.3 + } + } + \ No newline at end of file From 9142607eb1db448d74c3599e460160c65883239e Mon Sep 17 00:00:00 2001 From: Sparshagarwal29 Date: Fri, 15 Aug 2025 15:22:47 +0530 Subject: [PATCH 07/12] user.md --- docs/api/users.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/docs/api/users.md b/docs/api/users.md index e69de29b..1b40b3a4 100644 --- a/docs/api/users.md +++ b/docs/api/users.md @@ -0,0 +1,74 @@ +# User Profile API Documentation + +This document provides a detailed specification for the API endpoints related to managing a user's own profile. All endpoints require authentication. + +--- + +## 1. User Profile Management + +These endpoints handle the retrieval, updating, and deletion of the currently authenticated user's profile. All endpoints are prefixed with `/users`. + +### **`GET /me`** +Retrieves the complete profile information for the currently authenticated user. + +* **Server-Side Logic**: + 1. The user's ID is extracted from their authentication token. + 2. The `users` collection in the database is queried to find the corresponding user document. + 3. The raw database document is transformed into the public-facing `UserProfileResponse` format, ensuring fields like `_id` are correctly mapped to `id`. +* **Response** (`UserProfileResponse`): + ```json + { + "id": "user_id_string", + "name": "John Doe", + "email": "john.doe@example.com", + "imageUrl": "[https://example.com/path/to/avatar.png](https://example.com/path/to/avatar.png)", + "currency": "USD", + "createdAt": "2025-08-12T10:00:00Z", + "updatedAt": "2025-08-15T15:00:00Z" + } + ``` + +### **`PATCH /me`** +Updates the profile information for the currently authenticated user. + +* **Server-Side Logic**: + 1. The user's ID is extracted from their authentication token. + 2. The system filters the incoming request body to ensure only allowed fields (`name`, `imageUrl`, `currency`) can be updated. + 3. The `updated_at` timestamp is automatically set to the current time. + 4. The user's document in the `users` collection is updated with the new information. +* **Request Body** (`UserProfileUpdateRequest`): + ```json + { + "name": "Johnathan Doe", + "imageUrl": "[https://example.com/path/to/new_avatar.png](https://example.com/path/to/new_avatar.png)" + } + ``` +* **Response**: A dictionary containing the updated user object. + ```json + { + "user": { + "id": "user_id_string", + "name": "Johnathan Doe", + "email": "john.doe@example.com", + "imageUrl": "[https://example.com/path/to/new_avatar.png](https://example.com/path/to/new_avatar.png)", + "currency": "USD", + "createdAt": "2025-08-12T10:00:00Z", + "updatedAt": "2025-08-15T15:05:00Z" + } + } + ``` + +### **`DELETE /me`** +Schedules the currently authenticated user's account for deletion. + +* **Server-Side Logic**: + 1. The user's ID is extracted from their authentication token. + 2. The corresponding user document is permanently deleted from the `users` collection. + *(Note: In a production system, this might be a "soft delete" where the user is marked as inactive, but the current implementation is a "hard delete".)* +* **Response** (`DeleteUserResponse`): + ```json + { + "success": true, + "message": "User account scheduled for deletion." + } + \ No newline at end of file From 692357828d8cb55f7b3514fc19e49997a4ffef29 Mon Sep 17 00:00:00 2001 From: Sparshagarwal29 Date: Fri, 15 Aug 2025 15:23:25 +0530 Subject: [PATCH 08/12] readme.md --- docs/api/README.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/docs/api/README.md b/docs/api/README.md index e69de29b..418807cb 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -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 + ``` +* **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. From e931f48ee2ea58a0dd99316627b314d2dad07027 Mon Sep 17 00:00:00 2001 From: Sparshagarwal29 Date: Fri, 15 Aug 2025 15:27:30 +0530 Subject: [PATCH 09/12] example.login --- docs/api/examples/curl_examples.md | 222 +++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) diff --git a/docs/api/examples/curl_examples.md b/docs/api/examples/curl_examples.md index e69de29b..f0e7ec17 100644 --- a/docs/api/examples/curl_examples.md +++ b/docs/api/examples/curl_examples.md @@ -0,0 +1,222 @@ +# cURL API Examples + +This document provides practical `cURL` examples for interacting with the Splitwiser API. + +## 1. Prerequisites + +Before running these commands, you'll need to set some environment variables in your terminal. This will make the examples easier to use. + +```bash +export API_URL="http://localhost:8000" + +export ACCESS_TOKEN="your_jwt_access_token_here" +export GROUP_ID="your_group_id_here" +export EXPENSE_ID="your_expense_id_here" +export SETTLEMENT_ID="your_settlement_id_here" +export MEMBER_ID="a_group_member_id_here" +``` + +## 2. Authentication (`/auth`) + +### **Sign up with Email** +```bash +curl -X POST "$API_URL/auth/signup/email" \ +-H "Content-Type: application/json" \ +-d '{ + "email": "testuser@example.com", + "password": "strongpassword123", + "name": "Test User" +}' +``` + +### **Login with Email** +```bash +curl -X POST "$API_URL/auth/login/email" \ +-H "Content-Type: application/json" \ +-d '{ + "email": "testuser@example.com", + "password": "strongpassword123" +}' +``` + +### **Refresh Token** +```bash +curl -X POST "$API_URL/auth/refresh" \ +-H "Content-Type: application/json" \ +-d '{ + "refresh_token": "your_refresh_token_here" +}' +``` + +### **Verify Token** +```bash +curl -X POST "$API_URL/auth/token/verify" \ +-H "Content-Type: application/json" \ +-d '{ + "access_token": "'"$ACCESS_TOKEN"'" +}' +``` + +### **Request Password Reset** +```bash +curl -X POST "$API_URL/auth/password/reset/request" \ +-H "Content-Type: application/json" \ +-d '{ + "email": "testuser@example.com" +}' +``` + +### **Confirm Password Reset** +```bash +curl -X POST "$API_URL/auth/password/reset/confirm" \ +-H "Content-Type: application/json" \ +-d '{ + "reset_token": "token_from_email_link", + "new_password": "newstrongpassword456" +}' +``` + +## 3. User Profile (`/users`) + +### **Get Current User Profile** +```bash +curl -X GET "$API_URL/users/me" \ +-H "Authorization: Bearer $ACCESS_TOKEN" +``` + +### **Update User Profile** +```bash +curl -X PATCH "$API_URL/users/me" \ +-H "Authorization: Bearer $ACCESS_TOKEN" \ +-H "Content-Type: application/json" \ +-d '{ + "name": "Updated Test User", + "currency": "EUR" +}' +``` + +### **Delete User Account** +```bash +curl -X DELETE "$API_URL/users/me" \ +-H "Authorization: Bearer $ACCESS_TOKEN" +``` + +## 4. Groups (`/groups`) + +### **Create a Group** +```bash +curl -X POST "$API_URL/groups" \ +-H "Authorization: Bearer $ACCESS_TOKEN" \ +-H "Content-Type: application/json" \ +-d '{ + "name": "Vacation Crew", + "currency": "USD" +}' +``` + +### **List User's Groups** +```bash +curl -X GET "$API_URL/groups" \ +-H "Authorization: Bearer $ACCESS_TOKEN" +``` + +### **Get Group Details** +```bash +curl -X GET "$API_URL/groups/$GROUP_ID" \ +-H "Authorization: Bearer $ACCESS_TOKEN" +``` + +### **Join a Group** +```bash +curl -X POST "$API_URL/groups/join" \ +-H "Authorization: Bearer $ACCESS_TOKEN" \ +-H "Content-Type: application/json" \ +-d '{ + "joinCode": "A1B2C3" +}' +``` + +### **Leave a Group** +```bash +curl -X POST "$API_URL/groups/$GROUP_ID/leave" \ +-H "Authorization: Bearer $ACCESS_TOKEN" +``` + +### **Remove a Member (Admin Only)** +```bash +curl -X DELETE "$API_URL/groups/$GROUP_ID/members/$MEMBER_ID" \ +-H "Authorization: Bearer $ACCESS_TOKEN" +``` + +## 5. Expenses (`/groups/{group_id}/expenses`) + +### **Create an Expense** +```bash +curl -X POST "$API_URL/groups/$GROUP_ID/expenses" \ +-H "Authorization: Bearer $ACCESS_TOKEN" \ +-H "Content-Type: application/json" \ +-d '{ + "description": "Dinner", + "amount": 120.00, + "paidBy": "user_id_who_paid", + "splitType": "equal", + "splits": [ + {"userId": "user_id_who_paid", "amount": 40.00}, + {"userId": "another_user_id", "amount": 40.00}, + {"userId": "third_user_id", "amount": 40.00} + ] +}' +``` + +### **List Group Expenses** +```bash +curl -X GET "$API_URL/groups/$GROUP_ID/expenses?page=1&limit=10" \ +-H "Authorization: Bearer $ACCESS_TOKEN" +``` + +### **Update an Expense** +```bash +curl -X PATCH "$API_URL/groups/$GROUP_ID/expenses/$EXPENSE_ID" \ +-H "Authorization: Bearer $ACCESS_TOKEN" \ +-H "Content-Type: application/json" \ +-d '{ + "description": "Dinner at the fancy place" +}' +``` + +## 6. Settlements (`/groups/{group_id}/settlements`) + +### **Manually Record a Payment** +```bash +curl -X POST "$API_URL/groups/$GROUP_ID/settlements" \ +-H "Authorization: Bearer $ACCESS_TOKEN" \ +-H "Content-Type: application/json" \ +-d '{ + "payer_id": "user_id_who_paid_back", + "payee_id": "user_id_who_received", + "amount": 50.00, + "description": "Cash payment for groceries" +}' +``` + +### **Get Group Settlements** +```bash +curl -X GET "$API_URL/groups/$GROUP_ID/settlements?status=pending" \ +-H "Authorization: Bearer $ACCESS_TOKEN" +``` + +### **Mark a Settlement as Paid** +```bash +curl -X PATCH "$API_URL/groups/$GROUP_ID/settlements/$SETTLEMENT_ID" \ +-H "Authorization: Bearer $ACCESS_TOKEN" \ +-H "Content-Type: application/json" \ +-d '{ + "status": "completed" +}' +``` + +### **Optimize Settlements** +```bash +curl -X POST "$API_URL/groups/$GROUP_ID/settlements/optimize?algorithm=advanced" \ +-H "Authorization: Bearer $ACCESS_TOKEN" +` \ No newline at end of file From bc104803b1e3818753d20e9ef385d148e8aeed6f Mon Sep 17 00:00:00 2001 From: Sparshagarwal29 Date: Fri, 15 Aug 2025 15:30:01 +0530 Subject: [PATCH 10/12] postman json --- docs/api/examples/postman_collection.json | 424 ++++++++++++++++++++++ 1 file changed, 424 insertions(+) diff --git a/docs/api/examples/postman_collection.json b/docs/api/examples/postman_collection.json index e69de29b..bc716504 100644 --- a/docs/api/examples/postman_collection.json +++ b/docs/api/examples/postman_collection.json @@ -0,0 +1,424 @@ +{ + "info": { + "_postman_id": "a8c1b2d3-e4f5-4a6b-8c9d-0e1f2a3b4c5d", + "name": "Splitwiser API", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "description": "A complete Postman collection for the Splitwiser API." + }, + "item": [ + { + "name": "Authentication", + "item": [ + { + "name": "Sign up with Email", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"testuser@example.com\",\n \"password\": \"strongpassword123\",\n \"name\": \"Test User\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/auth/signup/email", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "auth", + "signup", + "email" + ] + } + }, + "response": [] + }, + { + "name": "Login with Email", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"testuser@example.com\",\n \"password\": \"strongpassword123\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/auth/login/email", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "auth", + "login", + "email" + ] + } + }, + "response": [] + }, + { + "name": "Refresh Token", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"refresh_token\": \"your_refresh_token_here\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/auth/refresh", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "auth", + "refresh" + ] + } + }, + "response": [] + }, + { + "name": "Verify Token", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"access_token\": \"{{accessToken}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/auth/token/verify", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "auth", + "token", + "verify" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "User Profile", + "item": [ + { + "name": "Get Current User Profile", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/me", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "me" + ] + } + }, + "response": [] + }, + { + "name": "Update User Profile", + "request": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Updated Name\",\n \"currency\": \"EUR\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/me", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "me" + ] + } + }, + "response": [] + }, + { + "name": "Delete User Account", + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/me", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "me" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Groups", + "item": [ + { + "name": "Create Group", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"My New Group\",\n \"currency\": \"USD\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/groups", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "groups" + ] + } + }, + "response": [] + }, + { + "name": "List User's Groups", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/groups", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "groups" + ] + } + }, + "response": [] + }, + { + "name": "Join Group", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"joinCode\": \"A1B2C3\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/groups/join", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "groups", + "join" + ] + } + }, + "response": [] + }, + { + "name": "Get Group Details", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/groups/{{groupId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "groups", + "{{groupId}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Expenses", + "item": [ + { + "name": "Create Expense", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"description\": \"Dinner\",\n \"amount\": 120.00,\n \"paidBy\": \"{{userId}}\",\n \"splitType\": \"equal\",\n \"splits\": [\n {\"userId\": \"{{userId}}\", \"amount\": 60.00},\n {\"userId\": \"{{friendId}}\", \"amount\": 60.00}\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/groups/{{groupId}}/expenses", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "groups", + "{{groupId}}", + "expenses" + ] + } + }, + "response": [] + }, + { + "name": "List Group Expenses", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/groups/{{groupId}}/expenses", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "groups", + "{{groupId}}", + "expenses" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Settlements", + "item": [ + { + "name": "Manually Record Payment", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"payer_id\": \"{{userId}}\",\n \"payee_id\": \"{{friendId}}\",\n \"amount\": 50.00\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/groups/{{groupId}}/settlements", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "groups", + "{{groupId}}", + "settlements" + ] + } + }, + "response": [] + }, + { + "name": "Optimize Settlements", + "request": { + "method": "POST", + "header": [], + "url": { + "raw": "{{baseUrl}}/groups/{{groupId}}/settlements/optimize", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "groups", + "{{groupId}}", + "settlements", + "optimize" + ] + } + }, + "response": [] + } + ] + } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{accessToken}}", + "type": "string" + } + ] + }, + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:8000" + }, + { + "key": "accessToken", + "value": "" + }, + { + "key": "groupId", + "value": "" + }, + { + "key": "userId", + "value": "" + }, + { + "key": "friendId", + "value": "" + } + ] +} From cb4961da34321fcf28108f81c7f9c40ba925ab18 Mon Sep 17 00:00:00 2001 From: Sparshagarwal29 Date: Fri, 15 Aug 2025 16:25:53 +0530 Subject: [PATCH 11/12] Fix: Address review comments from coderabbitai --- docs/api/authentication.md | 3 +-- docs/api/examples/curl_examples.md | 3 ++- docs/api/groups.md | 4 ++-- docs/api/settlements.md | 2 +- docs/api/users.md | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/api/authentication.md b/docs/api/authentication.md index 83bf2b94..65e439c1 100644 --- a/docs/api/authentication.md +++ b/docs/api/authentication.md @@ -183,8 +183,7 @@ Error : - 401 Unauthorized: Invalid or expired refresh token. ### **`POST /token/verify`** -**Description**: Verifies an access token and returns the corresponding user's information.Issues a new access token and refresh token if valid, and returns them - +**Description**: Verifies an access token and returns the corresponding user's information. * **Request Body** (`TokenVerifyRequest`): ```json { diff --git a/docs/api/examples/curl_examples.md b/docs/api/examples/curl_examples.md index f0e7ec17..abf47b6a 100644 --- a/docs/api/examples/curl_examples.md +++ b/docs/api/examples/curl_examples.md @@ -215,8 +215,9 @@ curl -X PATCH "$API_URL/groups/$GROUP_ID/settlements/$SETTLEMENT_ID" \ }' ``` + ### **Optimize Settlements** ```bash curl -X POST "$API_URL/groups/$GROUP_ID/settlements/optimize?algorithm=advanced" \ -H "Authorization: Bearer $ACCESS_TOKEN" -` \ No newline at end of file +``` \ No newline at end of file diff --git a/docs/api/groups.md b/docs/api/groups.md index cc199f20..ddda8dd6 100644 --- a/docs/api/groups.md +++ b/docs/api/groups.md @@ -40,7 +40,7 @@ Creates a new group. { "name": "Trip to the Mountains", "currency": "EUR", - "imageUrl": "[https://example.com/mountains.png](https://example.com/mountains.png)" + "imageUrl": "https://example.com/mountains.png" } ``` * **Response** (`GroupResponse`): @@ -52,7 +52,7 @@ Creates a new group. "joinCode": "UNIQUE_JOIN_CODE", "createdBy": "user_id_of_creator", "createdAt": "2025-08-14T12:00:00Z", - "imageUrl": "[https://example.com/mountains.png](https://example.com/mountains.png)", + "imageUrl": "https://example.com/mountains.png", "members": [ /* ... list of GroupMemberWithDetails ... */ ] } ``` diff --git a/docs/api/settlements.md b/docs/api/settlements.md index c374d693..60bedece 100644 --- a/docs/api/settlements.md +++ b/docs/api/settlements.md @@ -8,7 +8,7 @@ This document provides a complete and definitive specification for the API endpo ### **What is a Settlement?** -A **Settlement** is a record of a specific debt between two users. It represents the fact that one person (the payee) owes another person (the payer) a certain amount of money. Settlements are the fundamental building blocks for tracking who owes whom in the application. +A Settlement records an obligation between two users. For auto-generated settlements (from an Expense): payerId is the original expense payer (the creditor — the person who paid the expense and is owed money) and payeeId is the member who owes that share (the debtor). For manual settlements (user-recorded repayments): payer_id is the member making the payment now and payee_id is the recipient. * **Automatic Settlements**: When an expense is created, the system automatically generates a `pending` settlement record for each person who owes a share of the cost. * **Manual Settlements**: Users can manually record a `completed` settlement to track a payment made outside the application (e.g., paying someone back in cash). diff --git a/docs/api/users.md b/docs/api/users.md index 1b40b3a4..1b4a807f 100644 --- a/docs/api/users.md +++ b/docs/api/users.md @@ -21,7 +21,7 @@ Retrieves the complete profile information for the currently authenticated user. "id": "user_id_string", "name": "John Doe", "email": "john.doe@example.com", - "imageUrl": "[https://example.com/path/to/avatar.png](https://example.com/path/to/avatar.png)", + "imageUrl": "https://example.com/path/to/avatar.png", "currency": "USD", "createdAt": "2025-08-12T10:00:00Z", "updatedAt": "2025-08-15T15:00:00Z" @@ -40,7 +40,7 @@ Updates the profile information for the currently authenticated user. ```json { "name": "Johnathan Doe", - "imageUrl": "[https://example.com/path/to/new_avatar.png](https://example.com/path/to/new_avatar.png)" + "imageUrl": "https://example.com/path/to/new_avatar.png" } ``` * **Response**: A dictionary containing the updated user object. @@ -50,7 +50,7 @@ Updates the profile information for the currently authenticated user. "id": "user_id_string", "name": "Johnathan Doe", "email": "john.doe@example.com", - "imageUrl": "[https://example.com/path/to/new_avatar.png](https://example.com/path/to/new_avatar.png)", + "imageUrl": "https://example.com/path/to/new_avatar.png", "currency": "USD", "createdAt": "2025-08-12T10:00:00Z", "updatedAt": "2025-08-15T15:05:00Z" From 3286c269de8df6f21c89e86cc9a675149a2b7414 Mon Sep 17 00:00:00 2001 From: Sparshagarwal29 Date: Fri, 15 Aug 2025 17:01:06 +0530 Subject: [PATCH 12/12] fiexed few more suggestions --- docs/api/authentication.md | 4 ++-- docs/api/settlements.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/authentication.md b/docs/api/authentication.md index 65e439c1..1d00bd12 100644 --- a/docs/api/authentication.md +++ b/docs/api/authentication.md @@ -140,7 +140,7 @@ Error : ### **`POST /login/google`** -**Description**: Handles Google OAuth login. Validates the Google token, creates or logs in the user based on Google ID, and issue OAuth ID token +**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): @@ -236,7 +236,7 @@ Sets a new password for a user using a valid reset token. "message": "Password has been reset successfully" } -- 400 Unauthorized: Invalid or expired refresh token. +- 400 Bad Request: Invalid or expired reset token. ## Authentication Flow diff --git a/docs/api/settlements.md b/docs/api/settlements.md index 60bedece..522db89d 100644 --- a/docs/api/settlements.md +++ b/docs/api/settlements.md @@ -107,7 +107,7 @@ Updates the status of a settlement, typically to mark it as paid. Deletes or undoes a recorded settlement. -* **Successful Response**: `{"success": True, "message": "Settlement record deleted successfully."}` +* **Successful Response**: `{"success": true, "message": "Settlement record deleted successfully."}` ### **`POST /settlements/optimize`**