# Split Bill App - API Documentation

Base URL: `http://localhost:3000/api`

## Response Format

All API responses follow this standardized format:

### Success Response
```json
{
   "error": false,
   "message": "Success",
   "data": { ... }
}
```

### Error Response
```json
{
   "error": true,
   "message": "Error message",
   "data": null
}
```

## Authentication

All protected endpoints require a JWT token in the Authorization header:

```
Authorization: Bearer <token>
```

---

## Auth Endpoints

### 1. Register

Create a new user account.

- **URL:** `/auth/register`
- **Method:** `POST`
- **Auth Required:** No

#### Request Body

| Field        | Type   | Required | Description                      |
|--------------|--------|----------|----------------------------------|
| phone_number | string | Yes      | User's phone number (unique)     |
| password     | string | Yes      | Password (min 6 characters)      |
| name         | string | Yes      | User's display name              |

#### Example Request
```json
{
   "phone_number": "+6281234567890",
   "password": "secret123",
   "name": "John Doe"
}
```

#### Example Response (201 Created)
```json
{
   "error": false,
   "message": "Registration successful",
   "data": {
      "user": {
         "id": 1,
         "name": "John Doe",
         "phone_number": "+6281234567890",
         "currency": "IDR",
         "img_url": null
      },
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
   }
}
```

#### Error Responses
- `400` - Phone number, password, and name are required
- `400` - Password must be at least 6 characters
- `400` - Phone number already registered

---

### 2. Login

Authenticate user and receive JWT token.

- **URL:** `/auth/login`
- **Method:** `POST`
- **Auth Required:** No

#### Request Body

| Field        | Type   | Required | Description          |
|--------------|--------|----------|----------------------|
| phone_number | string | Yes      | User's phone number  |
| password     | string | Yes      | User's password      |

#### Example Request
```json
{
   "phone_number": "+6281234567890",
   "password": "secret123"
}
```

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Login successful",
   "data": {
      "user": {
         "id": 1,
         "name": "John Doe",
         "phone_number": "+6281234567890",
         "currency": "IDR",
         "img_url": null,
         "theme": "light"
      },
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
   }
}
```

#### Error Responses
- `400` - Phone number and password are required
- `401` - Invalid phone number or password

---

### 3. Reset Password

Reset user password after successful OTP verification on frontend.

> **Note:** OTP request and verification is handled entirely on the frontend using Firebase Authentication. Call this endpoint only after the user has successfully verified their OTP via Firebase.

- **URL:** `/auth/reset-password`
- **Method:** `POST`
- **Auth Required:** No

#### Request Body

| Field        | Type   | Required | Description                 |
|--------------|--------|----------|-----------------------------|
| phone_number | string | Yes      | User's phone number         |
| new_password | string | Yes      | New password (min 6 chars)  |

#### Example Request
```json
{
   "phone_number": "+6281234567890",
   "new_password": "newpassword123"
}
```

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Password reset successful",
   "data": null
}
```

#### Error Responses
- `400` - Phone number and new password are required
- `400` - Password must be at least 6 characters
- `404` - Phone number not registered

#### Frontend Flow
1. User enters phone number on forgot password screen
2. Frontend requests OTP via Firebase Auth (`verifyPhoneNumber`)
3. User receives and enters OTP
4. Frontend verifies OTP via Firebase Auth
5. On successful verification, frontend calls this endpoint to set new password

---

## User Endpoints

### 4. Get Profile

Get current user's profile information.

- **URL:** `/user/profile`
- **Method:** `GET`
- **Auth Required:** Yes

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Success",
   "data": {
      "id": 1,
      "name": "John Doe",
      "phone_number": "+6281234567890",
      "currency": "IDR",
      "img_url": "https://example.com/photo.jpg",
      "theme": "light"
   }
}
```

---

### 5. Search Users

Search for registered users by phone number or name. Useful for adding participants when creating a bill.

- **URL:** `/user/search`
- **Method:** `GET`
- **Auth Required:** Yes

#### Query Parameters

| Parameter | Type   | Required | Description                              |
|-----------|--------|----------|------------------------------------------|
| q         | string | Yes      | Search query (min 2 characters)          |

#### Example Request
```
GET /api/user/search?q=john
```

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Success",
   "data": [
      {
         "id": 2,
         "name": "John Smith",
         "phone_number": "+6281234567891",
         "img_url": "https://example.com/john.jpg"
      },
      {
         "id": 3,
         "name": "Johnny Depp",
         "phone_number": "+6281234567892",
         "img_url": null
      }
   ]
}
```

#### Error Responses
- `400` - Search query must be at least 2 characters

#### Notes
- Searches both phone number and name fields
- Returns maximum 20 results
- Current user is excluded from search results

---

### 6. Edit Profile

Update user profile information.

- **URL:** `/user/profile`
- **Method:** `PUT`
- **Auth Required:** Yes

#### Request Body

| Field   | Type   | Required | Description           |
|---------|--------|----------|-----------------------|
| name    | string | No       | New display name      |
| img_url | string | No       | Profile image URL     |

#### Example Request
```json
{
   "name": "John Updated",
   "img_url": "https://example.com/new-photo.jpg"
}
```

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Profile updated successfully",
   "data": {
      "id": 1,
      "name": "John Updated",
      "phone_number": "+6281234567890",
      "currency": "IDR",
      "img_url": "https://example.com/new-photo.jpg",
      "theme": "light"
   }
}
```

---

### 7. Change Password

Change user's password.

- **URL:** `/user/change-password`
- **Method:** `PUT`
- **Auth Required:** Yes

#### Request Body

| Field        | Type   | Required | Description                |
|--------------|--------|----------|----------------------------|
| old_password | string | Yes      | Current password           |
| new_password | string | Yes      | New password (min 6 chars) |

#### Example Request
```json
{
   "old_password": "secret123",
   "new_password": "newsecret456"
}
```

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Password changed successfully",
   "data": null
}
```

#### Error Responses
- `400` - Old password and new password are required
- `400` - New password must be at least 6 characters
- `401` - Current password is incorrect

---

### 8. Change Default Currency

Update user's default currency.

- **URL:** `/user/currency`
- **Method:** `PUT`
- **Auth Required:** Yes

#### Request Body

| Field    | Type   | Required | Description              |
|----------|--------|----------|--------------------------|
| currency | string | Yes      | Currency code: IDR or USD |

#### Example Request
```json
{
   "currency": "USD"
}
```

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Currency updated successfully",
   "data": {
      "currency": "USD"
   }
}
```

#### Error Responses
- `400` - Currency must be IDR or USD

---

### 9. Toggle Theme

Switch between dark and light mode.

- **URL:** `/user/theme`
- **Method:** `PUT`
- **Auth Required:** Yes

#### Request Body

| Field | Type   | Required | Description               |
|-------|--------|----------|---------------------------|
| theme | string | Yes      | Theme: dark or light      |

#### Example Request
```json
{
   "theme": "dark"
}
```

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Theme updated successfully",
   "data": {
      "theme": "dark"
   }
}
```

#### Error Responses
- `400` - Theme must be dark or light

---

## Bill Endpoints

### 10. Create Bill

Create a new bill with items and participants.

- **URL:** `/bills`
- **Method:** `POST`
- **Auth Required:** Yes

#### Request Body

| Field           | Type   | Required | Description                              |
|-----------------|--------|----------|------------------------------------------|
| title           | string | Yes      | Bill title                               |
| items           | array  | Yes      | Array of bill items                      |
| participants    | array  | Yes      | Array of participants                    |
| tax_percent     | number | No       | Tax percentage (default: 0)              |
| service_percent | number | No       | Service charge percentage (default: 0)   |
| currency        | string | No       | Currency code (default: IDR)             |

#### Item Object

| Field       | Type   | Required | Description                   |
|-------------|--------|----------|-------------------------------|
| name        | string | Yes      | Item name                     |
| price       | number | Yes      | Item price (per unit)         |
| quantity    | number | No       | Item quantity (default: 1)    |
| discount    | number | No       | Discount amount (default: 0)  |
| assignments | array  | Yes      | Array of item assignments     |

> **Price Calculation:** Net price = `(price × quantity) - discount`

#### Assignment Object

| Field          | Type   | Required | Description                              |
|----------------|--------|----------|------------------------------------------|
| participant_id | number | Yes      | Index of participant in participants array |
| share_percent  | number | Yes      | Share percentage (0-100)                 |

#### Participant Object

| Field      | Type   | Required | Description                        |
|------------|--------|----------|------------------------------------|
| user_id    | number | No       | Registered user ID (nullable)      |
| guest_name | string | No       | Guest name if not registered user  |

#### Example Request
```json
{
   "title": "Lunch at Restaurant ABC",
   "tax_percent": 10,
   "service_percent": 5,
   "currency": "IDR",
   "participants": [
      { "user_id": 1 },
      { "user_id": 2 },
      { "guest_name": "Guest User" }
   ],
   "items": [
      {
         "name": "Nasi Goreng",
         "price": 35000,
         "quantity": 1,
         "discount": 0,
         "assignments": [
            { "participant_id": 0, "share_percent": 100 }
         ]
      },
      {
         "name": "Mie Ayam",
         "price": 25000,
         "quantity": 2,
         "discount": 5000,
         "assignments": [
            { "participant_id": 1, "share_percent": 50 },
            { "participant_id": 2, "share_percent": 50 }
         ]
      },
      {
         "name": "Es Teh",
         "price": 10000,
         "quantity": 3,
         "discount": 0,
         "assignments": [
            { "participant_id": 0, "share_percent": 33.33 },
            { "participant_id": 1, "share_percent": 33.33 },
            { "participant_id": 2, "share_percent": 33.34 }
         ]
      }
   ]
}
```

#### Example Response (201 Created)
```json
{
   "error": false,
   "message": "Bill created successfully",
   "data": {
      "id": 1,
      "owner_id": 1,
      "title": "Lunch at Restaurant ABC",
      "tax_percent": "10.00",
      "service_percent": "5.00",
      "currency": "IDR",
      "created_at": "2026-02-05T10:30:00.000Z",
      "updated_at": "2026-02-05T10:30:00.000Z",
      "owner": {
         "id": 1,
         "name": "John Doe",
         "phone_number": "+6281234567890"
      },
      "items": [...],
      "participants": [...],
      "payments": [...]
   }
}
```

#### Error Responses
- `400` - Title is required
- `400` - At least one item is required
- `400` - At least one participant is required
- `400` - Each item must have a name and price
- `400` - Invalid participant_id

---

### 11. Get Bill List

Get list of bills (history).

- **URL:** `/bills`
- **Method:** `GET`
- **Auth Required:** Yes

#### Query Parameters

| Parameter | Type   | Required | Description                                    |
|-----------|--------|----------|------------------------------------------------|
| type      | string | No       | Filter: `created` (my bills) or `joined` (others' bills) |

#### Example Request
```
GET /api/bills?type=created
```

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Success",
   "data": [
      {
         "id": 1,
         "owner_id": 1,
         "title": "Lunch at Restaurant ABC",
         "tax_percent": "10.00",
         "service_percent": "5.00",
         "currency": "IDR",
         "created_at": "2026-02-05T10:30:00.000Z",
         "owner": {
            "id": 1,
            "name": "John Doe",
            "phone_number": "+6281234567890"
         },
         "participants": [...],
         "payments": [...]
      }
   ]
}
```

---

### 12. Get Bill Detail

Get detailed information about a specific bill.

- **URL:** `/bills/:billId`
- **Method:** `GET`
- **Auth Required:** Yes

#### URL Parameters

| Parameter | Type   | Required | Description |
|-----------|--------|----------|-------------|
| billId    | number | Yes      | Bill ID     |

#### Example Request
```
GET /api/bills/1
```

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Success",
   "data": {
      "id": 1,
      "owner_id": 1,
      "title": "Lunch at Restaurant ABC",
      "tax_percent": "10.00",
      "service_percent": "5.00",
      "currency": "IDR",
      "created_at": "2026-02-05T10:30:00.000Z",
      "owner": {
         "id": 1,
         "name": "John Doe",
         "phone_number": "+6281234567890",
         "img_url": null
      },
      "items": [
         {
            "id": 1,
            "bill_id": 1,
            "name": "Nasi Goreng",
            "price": "35000.00",
            "quantity": 1,
            "discount": "0.00",
            "sub_total": 35000,
            "assignments": [
               {
                  "id": 1,
                  "share_percent": "100.00",
                  "participant": {
                     "id": 1,
                     "user_id": 1,
                     "guest_name": null,
                     "user": {
                        "id": 1,
                        "name": "John Doe",
                        "phone_number": "+6281234567890"
                     }
                  }
               }
            ]
         }
      ],
      "participants": [
         {
            "id": 1,
            "bill_id": 1,
            "user_id": 1,
            "guest_name": null,
            "user": {
               "id": 1,
               "name": "John Doe",
               "phone_number": "+6281234567890"
            }
         }
      ],
      "payments": [
         {
            "id": 1,
            "bill_id": 1,
            "participant_id": 1,
            "amount": "40250.00",
            "confirmed": false,
            "confirmed_at": null,
            "participant": {...}
         }
      ],
      "summary": {
         "subtotal": 65000,
         "tax_amount": 6500,
         "service_amount": 3250,
         "total": 74750
      }
   }
}
```

#### Error Responses
- `403` - You do not have access to this bill
- `404` - Bill not found

---

### 13. Confirm Payment

Confirm payment for a participant in a bill.

- **URL:** `/bills/:billId/confirm-payment`
- **Method:** `POST`
- **Auth Required:** Yes

#### URL Parameters

| Parameter | Type   | Required | Description |
|-----------|--------|----------|-------------|
| billId    | number | Yes      | Bill ID     |

#### Request Body

| Field          | Type   | Required | Description    |
|----------------|--------|----------|----------------|
| participant_id | number | Yes      | Participant ID |

#### Example Request
```json
{
   "participant_id": 2
}
```

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Payment confirmed successfully",
   "data": {
      "id": 2,
      "bill_id": 1,
      "participant_id": 2,
      "amount": "12000.00",
      "confirmed": true,
      "confirmed_at": "2026-02-05T11:00:00.000Z",
      "created_at": "2026-02-05T10:30:00.000Z",
      "updated_at": "2026-02-05T11:00:00.000Z"
   }
}
```

#### Error Responses
- `400` - Participant ID is required
- `400` - Payment already confirmed
- `403` - You can only confirm your own payment
- `404` - Bill not found
- `404` - Participant not found in this bill
- `404` - Payment record not found

---

### 14. Delete Bill

Delete a bill and all its related data. Only the bill owner (creator) can delete.

- **URL:** `/bills/:billId`
- **Method:** `DELETE`
- **Auth Required:** Yes

#### URL Parameters

| Parameter | Type   | Required | Description |
|-----------|--------|----------|-------------|
| billId    | number | Yes      | Bill ID     |

#### Example Request
```
DELETE /api/bills/1
```

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Bill deleted successfully",
   "data": null
}
```

#### Error Responses
- `403` - Only the bill owner can delete this bill
- `404` - Bill not found

---

## Dashboard Endpoints

### 15. Get Dashboard Summary

Get summary data for dashboard display.

- **URL:** `/dashboard/summary`
- **Method:** `GET`
- **Auth Required:** Yes

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Success",
   "data": {
      "outstanding": {
         "amount": 125000,
         "count": 3
      },
      "monthly": {
         "total": 450000,
         "count": 8,
         "month": "February 2026"
      },
      "owned_bills_monthly": {
         "total": 320000,
         "count": 5
      }
   }
}
```

---

## Common Error Responses

| Code | Message                    | Description                           |
|------|----------------------------|---------------------------------------|
| 400  | Bad request                | Invalid request body or parameters    |
| 401  | Unauthorized               | Missing or invalid JWT token          |
| 401  | Token has expired          | JWT token has expired                 |
| 403  | Forbidden                  | Access denied to resource             |
| 404  | Not found                  | Resource not found                    |
| 500  | Internal server error      | Server-side error                     |

---

## Health Check

### Check Server Status

- **URL:** `/health`
- **Method:** `GET`
- **Auth Required:** No

#### Example Response (200 OK)
```json
{
   "error": false,
   "message": "Server is running",
   "data": {
      "status": "ok"
   }
}
```
