SmartSpend API Documentation

PHP + MySQL backend for the SmartSpend family expense app. Every endpoint below shows exactly what you send and what you get back.

Running on LIVE SERVER - connected to database "czsoft_smartspend". The API is ready to use.

Setup and base URL

This copy is running on the live server, so there is only one address. It works from the browser, from Postman, from the emulator and from a real phone anywhere in the world.

Calling fromBase URL
Everywhere https://www.smartspend.creamerzsoft.com/
Put this in the Android app https://www.smartspend.creamerzsoft.com/api/

Test accounts

RoleEmailPassword
Adminadmin@smartspend.comadmin123
Memberayesha@smartspend.commember123
Memberhamza@smartspend.commember123
Membersara@smartspend.commember123

Sending the token

Call Login first. It returns a token. Save it in the app, then send it as a header on every endpoint marked Login required or Admin only:

Authorization: Bearer d449b6b99cefda157444058487d862d6...

While testing you can also put it in the URL instead: ?token=d449b6b9...

Every response has the same shape

So in the app you always check success first, show message to the user, and read the real content from data.

When it works
{
    "success": true,
    "message": "Login successful",
    "data": {
        "...": "..."
    }
}
When it fails
{
    "success": false,
    "message": "Incorrect email or password",
    "errors": {
        "email": "Invalid email"
    }
}

Status codes used

CodeMeaning
200OK
201Created - signup, add expense, add member
400Bad request
401Not logged in, or wrong password
403Logged in, but not allowed (not the admin)
404Not found
405Wrong method - you sent GET to a POST endpoint
409Email already registered
422Validation failed - check the errors object
500Server or database error

Authentication

Start here. Login gives you a token - every other endpoint needs it.

POST Sign up No login needed
api/auth/signup.php

Creates a NEW household and makes this person its ADMIN. Use this on the Register screen. Other family members are added later by the admin using Add Member.

What you send
Headers
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
name string required Full name of the person
email string required Must be a valid email and not already registered
password string required At least 6 characters
householdName string optional Family name. If you leave it out we use "<name>'s Family"
monthlyBudget number optional Budget for the whole family. Default 0
Example request body
{
    "name": "Abdul Rehman",
    "email": "abdul@example.com",
    "password": "secret123",
    "householdName": "Khan Family",
    "monthlyBudget": 150000
}
What you get back
HTTP 201  ·  Content-Type: application/json
{
    "success": true,
    "message": "Account created successfully",
    "data": {
        "token": "7f3a9c2e1b4d...64 characters",
        "user": {
            "id": 1,
            "householdId": 1,
            "name": "Abdul Rehman",
            "email": "abdul@example.com",
            "role": "ADMIN",
            "assignedBudget": 150000
        }
    }
}
If something goes wrong
Codemessage you get back
422 Please fill all required fields
422 Please enter a valid email address
422 Password must be at least 6 characters
409 This email is already registered
POST Login No login needed
api/auth/login.php

Checks the email and password. Save the token you get back - you must send it on every protected request.

What you send
Headers
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
email string required The registered email address
password string required The account password
Example request body
{
    "email": "admin@smartspend.com",
    "password": "admin123"
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Login successful",
    "data": {
        "token": "d449b6b99cefda157444058487d862d6...",
        "user": {
            "id": 1,
            "householdId": 1,
            "name": "Abdul Rehman",
            "email": "admin@smartspend.com",
            "role": "ADMIN",
            "assignedBudget": 50000
        }
    }
}
If something goes wrong
Codemessage you get back
401 Incorrect email or password
422 Please fill all required fields
GET Who am I Login required
api/auth/me.php

Call this when the app opens to check the saved token is still valid. Also fills the profile screen.

What you send
Headers
Authorization: Bearer <your token>
Fields

Nothing to send - just the headers above.

What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "User loaded",
    "data": {
        "user": {
            "id": 1,
            "householdId": 1,
            "name": "Abdul Rehman",
            "email": "admin@smartspend.com",
            "role": "ADMIN",
            "assignedBudget": 50000
        },
        "householdName": "Khan Family",
        "totalSpent": 27700,
        "remaining": 22300
    }
}
If something goes wrong
Codemessage you get back
401 Please login first (missing or expired token)
POST Forgot password No login needed
api/auth/forgot_password.php

Creates a 6-digit code that works for 15 minutes. While DEBUG_MODE is true the code comes back in the response so you can test without an email server. The message is always the same whether the email exists or not, so nobody can use this to find out which emails are registered.

What you send
Headers
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
email string required The email to send the reset code to
Example request body
{
    "email": "admin@smartspend.com"
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "If that email is registered, a reset code has been sent",
    "data": {
        "code": "874545",
        "note": "Shown only because DEBUG_MODE is true"
    }
}
If something goes wrong
Codemessage you get back
422 Please enter a valid email address
POST Reset password No login needed
api/auth/reset_password.php

Sets a new password using the 6-digit code. The code can only be used once. All old tokens are deleted, so the user must login again.

What you send
Headers
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
email string required Same email used in Forgot password
code string required The 6-digit code
newPassword string required At least 6 characters
Example request body
{
    "email": "admin@smartspend.com",
    "code": "874545",
    "newPassword": "newpass123"
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Password changed successfully. Please login again.",
    "data": null
}
If something goes wrong
Codemessage you get back
400 This code is wrong or has expired
422 Password must be at least 6 characters
POST Change password Login required
api/auth/change_password.php

For the settings screen, when the user is already logged in and knows their current password.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
currentPassword string required The password they use right now
newPassword string required At least 6 characters
Example request body
{
    "currentPassword": "admin123",
    "newPassword": "admin456"
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Password updated successfully",
    "data": null
}
If something goes wrong
Codemessage you get back
401 Your current password is incorrect
422 New password must be at least 6 characters
POST Logout Login required
api/auth/logout.php

Deletes the current token from the database so it can never be used again. The app should also delete its saved copy.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields

Nothing to send - just the headers above.

What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Logged out successfully",
    "data": null
}
If something goes wrong
Codemessage you get back
401 Please login first (missing or expired token)

Dashboard and Profile

One call fills the whole home screen - no need to call members and expenses separately.

GET Dashboard Login required
api/dashboard.php

Everything the home screen needs in ONE request: the logged-in user, the family budget, how much was spent this month, every member with their own numbers, the 5 newest expenses, spending grouped by category for the chart, and the unread count for the bell icon.

What you send
Headers
Authorization: Bearer <your token>
Fields

Nothing to send - just the headers above.

What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Dashboard loaded",
    "data": {
        "user": {
            "id": 1,
            "householdId": 1,
            "name": "Abdul Rehman",
            "email": "admin@smartspend.com",
            "role": "ADMIN",
            "assignedBudget": 50000
        },
        "household": {
            "id": 1,
            "name": "Khan Family",
            "monthlyBudget": 150000,
            "totalSpent": 63850,
            "remaining": 86150,
            "usedPercent": 42.60000000000000142108547152020037174224853515625,
            "expenseCount": 11,
            "monthStart": "2026-08-01",
            "monthLabel": "August 2026"
        },
        "mySpending": {
            "assignedBudget": 50000,
            "totalSpent": 27700,
            "remaining": 22300
        },
        "members": [
            {
                "id": 1,
                "name": "Abdul Rehman",
                "email": "admin@smartspend.com",
                "role": "ADMIN",
                "assignedBudget": 50000,
                "totalSpent": 27700,
                "remaining": 22300,
                "usedPercent": 55.39999999999999857891452847979962825775146484375,
                "lastActive": "Just now"
            },
            {
                "id": 2,
                "name": "Ayesha Khan",
                "email": "ayesha@smartspend.com",
                "role": "MEMBER",
                "assignedBudget": 30000,
                "totalSpent": 17500,
                "remaining": 12500,
                "usedPercent": 58.2999999999999971578290569595992565155029296875,
                "lastActive": "2 hours ago"
            }
        ],
        "recentExpenses": [
            {
                "id": 11,
                "title": "Bus Card Top-up",
                "amount": 1200,
                "category": "Transport",
                "date": "2026-08-12",
                "memberId": 4,
                "memberName": "Sara Khan"
            }
        ],
        "spendingByCategory": [
            {
                "category": "Groceries",
                "amount": 21900,
                "percent": 34.2999999999999971578290569595992565155029296875
            },
            {
                "category": "Education",
                "amount": 14750,
                "percent": 23.10000000000000142108547152020037174224853515625
            }
        ],
        "unreadCount": 2
    }
}
If something goes wrong
Codemessage you get back
401 Please login first (missing or expired token)
POST Edit my profile Login required
api/profile.php

Lets a user change their OWN name or email. Send only the field you want to change - anything you leave out keeps its old value.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
name string optional New display name
email string optional New email. Must not belong to someone else
Example request body
{
    "name": "Abdul Rehman Khan"
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Profile updated successfully",
    "data": {
        "user": {
            "id": 1,
            "householdId": 1,
            "name": "Abdul Rehman Khan",
            "email": "admin@smartspend.com",
            "role": "ADMIN",
            "assignedBudget": 50000
        }
    }
}
If something goes wrong
Codemessage you get back
422 Please enter a valid email address
409 This email is already used by someone else

Expenses

By default every list shows only the CURRENT month. Add allMonths=1 to see everything.

GET List expenses Login required
api/expenses/list.php?category=Bills&page=1&limit=20

The main expense list. Every filter below is optional and they can be combined, for example ?memberId=3&category=Bills&page=2

What you send
Headers
Authorization: Bearer <your token>
Values added to the URL
FieldTypeRequiredWhat it means
memberId int optional Only this member's expenses
category string optional Groceries, Bills, Transport, Food, Health, Education, Shopping, Rent, Other
search string optional Search inside the expense title
from date optional Start date, format 2026-08-01
to date optional End date, format 2026-08-31
allMonths 0 or 1 optional Send 1 to ignore the current-month filter
page int optional Page number. Default 1
limit int optional Rows per page. Default 50, maximum 100
Example request
GET api/expenses/list.php?category=Bills&page=1&limit=20
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Expenses loaded",
    "data": {
        "expenses": [
            {
                "id": 12,
                "title": "Internet Bill",
                "amount": 4500,
                "category": "Bills",
                "date": "2026-08-18",
                "memberId": 1,
                "memberName": "Abdul Rehman"
            },
            {
                "id": 7,
                "title": "Mobile Load",
                "amount": 1500,
                "category": "Bills",
                "date": "2026-08-08",
                "memberId": 3,
                "memberName": "Hamza Khan"
            }
        ],
        "totalCount": 3,
        "totalSpent": 15200,
        "page": 1,
        "limit": 20,
        "totalPages": 1,
        "categories": [
            "Groceries",
            "Bills",
            "Transport",
            "Food",
            "Health",
            "Education",
            "Shopping",
            "Rent",
            "Other"
        ]
    }
}
If something goes wrong
Codemessage you get back
401 Please login first (missing or expired token)
POST Add expense Login required
api/expenses/add.php

Saves a new expense. It also creates a notification for the family, and if the member goes past their assigned budget it creates a Budget Exceeded warning too. The response tells you overBudget so the app can show a message straight away.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
title string required What the money was spent on
amount number required Must be greater than 0
category string optional One of the 9 categories. Anything else becomes "Other"
date date optional Format 2026-08-18. Defaults to today
memberId int optional Who the expense belongs to. Defaults to you. Only an ADMIN may put someone else's id here
Example request body
{
    "title": "Internet Bill",
    "amount": 4500,
    "category": "Bills",
    "date": "2026-08-18"
}
What you get back
HTTP 201  ·  Content-Type: application/json
{
    "success": true,
    "message": "Expense added successfully",
    "data": {
        "expense": {
            "id": 12,
            "title": "Internet Bill",
            "amount": 4500,
            "category": "Bills",
            "date": "2026-08-18",
            "memberId": 1,
            "memberName": "Abdul Rehman"
        },
        "memberSpent": 32200,
        "memberBudget": 50000,
        "overBudget": false
    }
}
If something goes wrong
Codemessage you get back
422 Please fill all required fields
422 Amount must be greater than 0
422 Date must look like 2026-08-19
403 You can only add expenses for yourself
404 That member is not part of your household
POST Edit expense Login required
api/expenses/update.php

Changes an existing expense. Send only the fields you want to change. A normal member can only edit their own expenses; an ADMIN can edit any expense in the household.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
id int required Which expense to edit
title string optional New title
amount number optional New amount, greater than 0
category string optional New category
date date optional New date, format 2026-08-18
Example request body
{
    "id": 12,
    "title": "Internet Bill (August)",
    "amount": 5000
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Expense updated successfully",
    "data": {
        "expense": {
            "id": 12,
            "title": "Internet Bill (August)",
            "amount": 5000,
            "category": "Bills",
            "date": "2026-08-18",
            "memberId": 1,
            "memberName": "Abdul Rehman"
        }
    }
}
If something goes wrong
Codemessage you get back
404 Expense not found
403 You can only edit your own expenses
422 Amount must be greater than 0
POST Delete expense Login required
api/expenses/delete.php

Removes one expense. A normal member can only delete their own; an ADMIN can delete any.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
id int required Which expense to delete
Example request body
{
    "id": 12
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Expense deleted successfully",
    "data": null
}
If something goes wrong
Codemessage you get back
404 Expense not found
403 You can only delete your own expenses
GET Category list No login needed
api/expenses/categories.php

The 9 categories for the dropdown on the Add Expense screen. No login needed, so the app can load it early.

What you send
Headers
(no special headers needed)
Fields

Nothing to send - just the headers above.

What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Categories loaded",
    "data": {
        "categories": [
            "Groceries",
            "Bills",
            "Transport",
            "Food",
            "Health",
            "Education",
            "Shopping",
            "Rent",
            "Other"
        ]
    }
}

Family Members

Anyone logged in can VIEW members. Only the ADMIN can add, edit or remove them.

GET List members Login required
api/members/list.php

Every member of the household with their assigned budget, how much they spent this month, what is left, the percentage used and when they were last active. The admin is always first.

What you send
Headers
Authorization: Bearer <your token>
Fields

Nothing to send - just the headers above.

What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Members loaded",
    "data": {
        "members": [
            {
                "id": 1,
                "name": "Abdul Rehman",
                "email": "admin@smartspend.com",
                "role": "ADMIN",
                "assignedBudget": 50000,
                "totalSpent": 27700,
                "remaining": 22300,
                "usedPercent": 55.39999999999999857891452847979962825775146484375,
                "lastActive": "Just now"
            },
            {
                "id": 3,
                "name": "Hamza Khan",
                "email": "hamza@smartspend.com",
                "role": "MEMBER",
                "assignedBudget": 25000,
                "totalSpent": 12800,
                "remaining": 12200,
                "usedPercent": 51.2000000000000028421709430404007434844970703125,
                "lastActive": "1 day ago"
            }
        ],
        "totalMembers": 4
    }
}
If something goes wrong
Codemessage you get back
401 Please login first (missing or expired token)
GET Member detail Login required
api/members/get.php?id=3

One member plus all of their expenses this month and their spending grouped by category. Use this for the Member Detail screen.

What you send
Headers
Authorization: Bearer <your token>
Values added to the URL
FieldTypeRequiredWhat it means
id int required Which member to load
Example request
GET api/members/get.php?id=3
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Member loaded",
    "data": {
        "member": {
            "id": 3,
            "name": "Hamza Khan",
            "email": "hamza@smartspend.com",
            "role": "MEMBER",
            "assignedBudget": 25000,
            "totalSpent": 12800,
            "remaining": 12200,
            "usedPercent": 51.2000000000000028421709430404007434844970703125,
            "lastActive": "1 day ago"
        },
        "expenses": [
            {
                "id": 8,
                "title": "Cricket Kit",
                "amount": 4800,
                "category": "Shopping",
                "date": "2026-08-11",
                "memberId": 3,
                "memberName": "Hamza Khan"
            }
        ],
        "expenseCount": 3,
        "spendingByCategory": [
            {
                "category": "Transport",
                "amount": 6500
            },
            {
                "category": "Shopping",
                "amount": 4800
            },
            {
                "category": "Bills",
                "amount": 1500
            }
        ]
    }
}
If something goes wrong
Codemessage you get back
422 Please fill all required fields
404 Member not found
GET Member expenses only Login required
api/members/expenses.php?id=3

A lighter version of Member detail - just the expense list and the total. Useful for a "see all" screen.

What you send
Headers
Authorization: Bearer <your token>
Values added to the URL
FieldTypeRequiredWhat it means
id int required Which member
allMonths 0 or 1 optional Send 1 to include older months as well
Example request
GET api/members/expenses.php?id=3
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Member expenses loaded",
    "data": {
        "expenses": [
            {
                "id": 6,
                "title": "Petrol",
                "amount": 6500,
                "category": "Transport",
                "date": "2026-08-04",
                "memberId": 3,
                "memberName": "Hamza Khan"
            }
        ],
        "totalSpent": 12800,
        "count": 3
    }
}
If something goes wrong
Codemessage you get back
404 Member not found
POST Add member Admin only
api/members/add.php

The admin creates a login for a family member. The member can then login with the email and password given here.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
name string required Full name
email string required Must be valid and not already registered
password string required At least 6 characters. Give it to the member
assignedBudget number optional Their spending limit. Default 0
role string optional MEMBER or ADMIN. Default MEMBER
Example request body
{
    "name": "Bilal Khan",
    "email": "bilal@smartspend.com",
    "password": "bilal123",
    "assignedBudget": 15000,
    "role": "MEMBER"
}
What you get back
HTTP 201  ·  Content-Type: application/json
{
    "success": true,
    "message": "Member added successfully",
    "data": {
        "member": {
            "id": 5,
            "name": "Bilal Khan",
            "email": "bilal@smartspend.com",
            "role": "MEMBER",
            "assignedBudget": 15000,
            "totalSpent": 0,
            "remaining": 15000,
            "usedPercent": 0,
            "lastActive": "Never"
        }
    }
}
If something goes wrong
Codemessage you get back
403 Only the household admin can do this
422 Please fill all required fields
422 Password must be at least 6 characters
409 This email is already registered
POST Edit member Admin only
api/members/update.php

Changes a member's name, email, role or budget. Send only what you want to change. The API refuses to remove the last ADMIN from a household.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
id int required Which member to edit
name string optional New name
email string optional New email
role string optional MEMBER or ADMIN
assignedBudget number optional New budget
Example request body
{
    "id": 2,
    "name": "Ayesha K.",
    "assignedBudget": 32000
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Member updated successfully",
    "data": {
        "member": {
            "id": 2,
            "name": "Ayesha K.",
            "email": "ayesha@smartspend.com",
            "role": "MEMBER",
            "assignedBudget": 32000,
            "totalSpent": 17500,
            "remaining": 14500,
            "usedPercent": 54.7000000000000028421709430404007434844970703125,
            "lastActive": "2 hours ago"
        }
    }
}
If something goes wrong
Codemessage you get back
403 Only the household admin can do this
404 Member not found
409 This email is already used by someone else
400 The household must have at least one admin
POST Set member budget Admin only
api/members/update_budget.php

The quick version of Edit member for the "Assign Budget" screen - it only changes the money. The response comes back with the member's fresh spending numbers so the screen can refresh immediately.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
id int required Which member
assignedBudget number required The new limit. Cannot be negative
Example request body
{
    "id": 3,
    "assignedBudget": 26000
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Budget updated successfully",
    "data": {
        "member": {
            "id": 3,
            "name": "Hamza Khan",
            "email": "hamza@smartspend.com",
            "role": "MEMBER",
            "assignedBudget": 26000,
            "totalSpent": 12800,
            "remaining": 13200,
            "usedPercent": 49.2000000000000028421709430404007434844970703125,
            "lastActive": "1 day ago"
        }
    }
}
If something goes wrong
Codemessage you get back
403 Only the household admin can do this
422 Budget cannot be negative
404 Member not found
POST Remove member Admin only
api/members/delete.php

Deletes the member AND all of their expenses and tokens. The admin cannot delete themselves.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
id int required Which member to remove
Example request body
{
    "id": 5
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Member removed successfully",
    "data": null
}
If something goes wrong
Codemessage you get back
403 Only the household admin can do this
400 You cannot remove yourself
404 Member not found

Household

The household is the family itself - its name, its monthly budget and which month is running.

GET Get household Login required
api/household/get.php

The family name, monthly budget, how much is spent and left this month, and how many members there are.

What you send
Headers
Authorization: Bearer <your token>
Fields

Nothing to send - just the headers above.

What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Household loaded",
    "data": {
        "household": {
            "id": 1,
            "name": "Khan Family",
            "monthlyBudget": 150000,
            "totalSpent": 63850,
            "remaining": 86150,
            "usedPercent": 42.60000000000000142108547152020037174224853515625,
            "monthStart": "2026-08-01",
            "monthLabel": "August 2026",
            "memberCount": 4
        }
    }
}
If something goes wrong
Codemessage you get back
401 Please login first (missing or expired token)
POST Edit household Admin only
api/household/update.php

Changes the family name or the total monthly budget. Send only what you want to change.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
name string optional New family name
monthlyBudget number optional New total budget. Cannot be negative
Example request body
{
    "name": "Khan Family",
    "monthlyBudget": 160000
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Household updated successfully",
    "data": {
        "household": {
            "id": 1,
            "name": "Khan Family",
            "monthlyBudget": 160000
        }
    }
}
If something goes wrong
Codemessage you get back
403 Only the household admin can do this
422 Budget cannot be negative
POST Start new month Admin only
api/household/new_month.php

The Start New Month button. It does NOT delete anything - old expenses stay in the database so the report screen still works. It only moves the month start date forward, so every screen begins counting from zero again. The response tells you what the closed month totalled, which is nice to show in a summary dialog.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
monthlyBudget number optional Set a different budget for the new month. Leave it out to keep the same one
Example request body
{
    "monthlyBudget": 160000
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "New month started successfully",
    "data": {
        "closedMonth": {
            "from": "2026-08-01",
            "to": "2026-09-01",
            "totalSpent": 63850,
            "expenseCount": 11
        },
        "newMonthStart": "2026-09-01",
        "monthlyBudget": 160000
    }
}
If something goes wrong
Codemessage you get back
403 Only the household admin can do this
GET Reports Login required
api/household/report.php?months=6

Totals for the reports and charts screen: month by month, then per member, then per category. Unlike the other endpoints this one looks at ALL months, not just the current one.

What you send
Headers
Authorization: Bearer <your token>
Values added to the URL
FieldTypeRequiredWhat it means
months int optional How many months of history. Default 6, maximum 24
Example request
GET api/household/report.php?months=6
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Report loaded",
    "data": {
        "monthly": [
            {
                "month": "2026-08",
                "label": "August 2026",
                "totalSpent": 63850,
                "expenseCount": 11
            },
            {
                "month": "2026-07",
                "label": "July 2026",
                "totalSpent": 58200,
                "expenseCount": 9
            }
        ],
        "byMember": [
            {
                "memberId": 1,
                "name": "Abdul Rehman",
                "role": "ADMIN",
                "totalSpent": 32700,
                "expenseCount": 3
            },
            {
                "memberId": 2,
                "name": "Ayesha Khan",
                "role": "MEMBER",
                "totalSpent": 17500,
                "expenseCount": 3
            }
        ],
        "byCategory": [
            {
                "category": "Groceries",
                "totalSpent": 21900,
                "expenseCount": 2
            },
            {
                "category": "Bills",
                "totalSpent": 15700,
                "expenseCount": 3
            }
        ]
    }
}
If something goes wrong
Codemessage you get back
401 Please login first (missing or expired token)

Notifications

The API creates these by itself when an expense is added, a member joins, a budget is passed or a new month starts.

GET List notifications Login required
api/notifications/list.php?limit=20

Messages for this user plus the ones sent to the whole family. Newest first. type is INFO, EXPENSE_ADDED or BUDGET_WARNING so the app can show a different icon for each.

What you send
Headers
Authorization: Bearer <your token>
Values added to the URL
FieldTypeRequiredWhat it means
limit int optional How many to return. Default 50, maximum 100
Example request
GET api/notifications/list.php?limit=20
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "Notifications loaded",
    "data": {
        "notifications": [
            {
                "id": 4,
                "title": "New Expense Added",
                "message": "Abdul Rehman added \"Internet Bill\" for Rs 4,500.00",
                "type": "EXPENSE_ADDED",
                "isRead": false,
                "createdAt": "2026-08-19 01:52:14",
                "timeAgo": "Just now"
            },
            {
                "id": 2,
                "title": "Budget Warning",
                "message": "Hamza Khan has used more than 50% of the assigned budget.",
                "type": "BUDGET_WARNING",
                "isRead": true,
                "createdAt": "2026-08-19 01:29:03",
                "timeAgo": "23 mins ago"
            }
        ],
        "unreadCount": 1
    }
}
If something goes wrong
Codemessage you get back
401 Please login first (missing or expired token)
POST Mark as read Login required
api/notifications/mark_read.php

Send id to mark ONE notification as read, or send all=1 to clear the whole list. Use all=1 behind a "Mark all as read" button.

What you send
Headers
Authorization: Bearer <your token>
Content-Type: application/json
Fields in the JSON body
FieldTypeRequiredWhat it means
id int optional Which notification. Required unless you send all
all 0 or 1 optional Send 1 to mark every notification as read
Example request body
{
    "all": 1
}
What you get back
HTTP 200  ·  Content-Type: application/json
{
    "success": true,
    "message": "All notifications marked as read",
    "data": null
}
If something goes wrong
Codemessage you get back
422 Please fill all required fields
404 Notification not found

Debug mode is OFF. Because this is the live server, database errors are hidden and Forgot password no longer returns the code in the response.