Route Quick Reference
Every endpoint exposed by the API. All routes are prefixed with /api and require the
X-API-KEY header. Auth level indicates the minimum requirement beyond the API key.
| Method | Endpoint | Description | Auth Level |
|---|---|---|---|
| Authentication | |||
| POST | /api/auth/register | Register a new user account | Public |
| POST | /api/auth/login | Login and receive a Sanctum token | Public |
| POST | /api/auth/send-otp | Send OTP to the registered email | Public |
| POST | /api/auth/verify-otp | Verify OTP code for email confirmation | Public |
| POST | /api/auth/forgot-password | Send OTP for password reset flow | Public |
| POST | /api/auth/check-forgot-password-otp | Check the forgot-password OTP validity | Public |
| POST | /api/auth/verify-forgot-password-otp | Verify OTP and reset the password | Public |
| POST | /api/auth/logout | Revoke the current token | Sanctum |
| POST | /api/auth/logout-all | Revoke all tokens for the user | Sanctum |
| POST | /api/auth/change-password | Change the authenticated user's password | Sanctum |
| DELETE | /api/auth/delete-account | Permanently delete the user account | Sanctum |
| User Info | |||
| GET | /api/user | Retrieve the authenticated user resource | Sanctum |
| Employee Profile (Self) | |||
| GET | /api/profile | Get the authenticated employee's profile | Sanctum |
| POST | /api/profile/complete | Complete the employee profile for the first time | Sanctum |
| PUT | /api/profile | Update the authenticated employee's profile | Sanctum |
| Attendance | |||
| POST | /api/attendance/check-in | Clock in with geolocation verification | Profile Required |
| POST | /api/attendance/check-out | Clock out and finalize the attendance record | Profile Required |
| GET | /api/attendance/today | Get today's attendance record for the authenticated employee | Profile Required |
| GET | /api/attendance/history | Get paginated attendance history for the authenticated employee | Profile Required |
| POST | /api/attendance/break/start | Start a break on the current attendance record | Profile Required |
| POST | /api/attendance/break/end | End the current break and resume work | Profile Required |
| GET | /api/attendance | List all employees' attendance records | Manager+ |
| GET | /api/attendance/report | Generate an attendance report for a date range | Manager+ |
| GET | /api/attendance/{id} | Get a specific attendance record by ID | Manager+ |
| GET | /api/attendance/{id}/details | Get logs, breaks, and total hours for a record | Manager+ |
| Leave Management | |||
| GET | /api/leaves/types | List all available leave types | Sanctum |
| GET | /api/leaves | List the authenticated employee's leave requests | Profile Required |
| POST | /api/leaves | Submit a new leave request | Profile Required |
| GET | /api/leaves/balance | Get the employee's remaining leave balance | Profile Required |
| GET | /api/leaves/{id} | Get a specific leave request | Profile Required |
| DELETE | /api/leaves/{id} | Cancel a pending leave request | Profile Required |
| POST | /api/leaves/types | Create a new leave type | Manager+ |
| GET | /api/leaves/all | List all employees' leave requests | Manager+ |
| GET | /api/leaves/pending | List all pending leave requests | Manager+ |
| PUT | /api/leaves/{id}/status | Approve or reject a leave request | Manager+ |
| Task Management | |||
| GET | /api/tasks | List tasks assigned to the authenticated employee | Profile Required |
| GET | /api/tasks/{id} | Get a specific task | Profile Required |
| PUT | /api/tasks/{id}/status | Update task status (e.g. in_progress β done) | Profile Required |
| GET | /api/tasks/{id}/comments | List comments on a task | Profile Required |
| POST | /api/tasks/{id}/comments | Add a comment to a task | Profile Required |
| GET | /api/tasks/{id}/attachments | List attachments on a task | Profile Required |
| POST | /api/tasks/{id}/attachments | Upload an attachment to a task | Profile Required |
| GET | /api/tasks/all | List all tasks (all employees) | Manager+ |
| POST | /api/tasks | Create and assign a new task | Manager+ |
| PUT | /api/tasks/{id} | Update a task | Manager+ |
| DELETE | /api/tasks/{id} | Delete a task | Manager+ |
| Expense Management | |||
| GET | /api/expenses | List the authenticated employee's expense claims | Sanctum |
| POST | /api/expenses | Submit a new expense claim | Sanctum |
| GET | /api/expenses/{id} | Get a specific expense claim | Sanctum |
| PUT | /api/expenses/{id} | Update a pending expense claim | Sanctum |
| DELETE | /api/expenses/{id} | Delete a pending expense claim | Sanctum |
| GET | /api/expenses/all | List all employees' expense claims | Manager+ |
| GET | /api/expenses/pending | List all pending expense claims | Manager+ |
| PUT | /api/expenses/{id}/status | Approve or reject an expense claim | Manager+ |
| Office Assets | |||
| GET | /api/assets/my | List assets assigned to the authenticated employee | Sanctum |
| GET | /api/assets | List all company assets | Admin Only |
| POST | /api/assets | Create a new asset record | Admin Only |
| GET | /api/assets/{id} | Get a specific asset | Admin Only |
| PUT | /api/assets/{id} | Update an asset record | Admin Only |
| DELETE | /api/assets/{id} | Delete an asset record | Admin Only |
| POST | /api/assets/{id}/assign | Assign an asset to an employee | Admin Only |
| POST | /api/assets/{id}/unassign | Unassign an asset from an employee | Admin Only |
| Messages | |||
| GET | /api/messages/inbox | List received messages (inbox) | Sanctum |
| GET | /api/messages/sent | List sent messages | Sanctum |
| POST | /api/messages | Send a new message to another user | Sanctum |
| GET | /api/messages/{id} | Get a single message by ID | Sanctum |
| DELETE | /api/messages/{id} | Delete a message | Sanctum |
| Notifications | |||
| GET | /api/notifications | List notifications for the authenticated user | Sanctum |
| PUT | /api/notifications/{id}/read | Mark a single notification as read | Sanctum |
| PUT | /api/notifications/read-all | Mark all notifications as read | Sanctum |
| DELETE | /api/notifications/{id} | Delete a single notification | Sanctum |
| DELETE | /api/notifications/read | Delete all read notifications | Sanctum |
| Dashboard | |||
| GET | /api/dashboard/employee | Employee dashboard β personal stats & today's summary | Sanctum |
| GET | /api/dashboard/burnout-stats | Employee burnout indicators (overtime, leave ratio) | Sanctum |
| GET | /api/dashboard/manager | Manager dashboard β team overview & attendance | Manager+ |
| GET | /api/dashboard/stats | Company-wide counts (employees, departments, etc.) | Admin Only |
| GET | /api/dashboard/admin | Admin dashboard β full company snapshot | Admin Only |
| Employee Management | |||
| GET | /api/employees | List all employees | Sanctum |
| GET | /api/employees/{id} | Get a single employee by ID | Sanctum |
| POST | /api/employees | Create a new employee record | Manager+ |
| PUT | /api/employees/{id} | Update an employee record | Manager+ |
| PUT | /api/employees/{Employeecode}/profile | Update employee profile (Manager/Admin) | Manager+ |
| DELETE | /api/employees/{id} | Delete an employee record | Manager+ |
| Departments | |||
| GET | /api/departments | List all departments | Sanctum |
| GET | /api/departments/{id} | Get a single department by ID | Sanctum |
| POST | /api/departments | Create a new department | Manager+ |
| PUT | /api/departments/{id} | Update department details | Manager+ |
| PUT | /api/departments/{id}/location | Update department geofence location | Manager+ |
| POST | /api/departments/set-department | Assign employee to a department for the first time | Manager+ |
| POST | /api/departments/update-department | Move employee to a different department | Manager+ |
| DELETE | /api/departments/{id} | Delete a department | Manager+ |
| Payroll | |||
| GET | /api/payroll | List the authenticated employee's payroll records | Profile Required |
| GET | /api/payroll/{id} | Get a specific payroll record | Profile Required |
| GET | /api/payroll/all | List all employees' payroll records | Admin Only |
| GET | /api/payroll/report | Generate a payroll summary report | Admin Only |
| POST | /api/payroll/generate | Generate payroll for a pay period | Admin Only |
| PUT | /api/payroll/{id}/status | Update payroll status (e.g. mark as paid) | Admin Only |
| Reports | |||
| GET | /api/reports/attendance | Company-wide attendance report | Admin Only |
| GET | /api/reports/leaves | Company-wide leave report | Admin Only |
| GET | /api/reports/payroll | Payroll summary report | Admin Only |
| GET | /api/reports/expenses | Company-wide expense report | Admin Only |
| File Uploads | |||
| POST | /api/uploads | Upload a single file | Sanctum |
| POST | /api/uploads/multiple | Upload multiple files in one request | Sanctum |
| POST | /api/uploads/profile-image | Upload and set the employee profile picture | Sanctum |
| POST | /api/uploads/receipt | Upload an expense receipt image | Sanctum |
| POST | /api/uploads/task-attachment | Upload a file attachment for a task | Sanctum |
| DELETE | /api/uploads | Delete a previously uploaded file by path | Sanctum |
Introduction
Welcome to the HR System API v2 documentation. This API follows RESTful conventions, returns JSON for all responses, and is secured with API Key + Sanctum Bearer Token authentication.
https://api.mohammedzom.online/api
{
"success": true,
"message": "Operation successful.",
"data": { ... }
}
600 requests / minute. Auth routes (login, OTP) are throttled at
60 requests / minute.
Authentication
Every request requires an API Key header validated by the
CheckApiKey middleware. Protected routes additionally require a
Sanctum Bearer Token issued at login.
All requests must include this header. Requests without a valid API key are rejected before reaching any controller.
X-API-KEY: your-api-key-here
After a successful login, pass the returned token as a Bearer token. All
auth:sanctum-guarded routes require this header.
Authorization: Bearer your-sanctum-token-here
Accept: application/json
Error Codes
All errors use the standard response envelope with "success": false.
Use the HTTP status code to determine the error category.
| Code | Meaning | Common Cause |
|---|---|---|
400 | Bad Request | Malformed request body or missing required parameters |
401 | Unauthenticated | Missing or expired Bearer token; invalid API key |
403 | Forbidden | Authenticated but insufficient role (CheckRole middleware) |
404 | Not Found | Resource does not exist or does not belong to the requester |
422 | Validation Error | Request passed but failed server-side validation rules |
429 | Too Many Requests | Rate limit exceeded β wait before retrying |
500 | Server Error | Unexpected server-side exception β check Laravel logs |
{
"success": false,
"message": "Validation failed.",
"errors": {
"email": ["The email field is required."],
"password": ["The password must be at least 8 characters."]
}
}
Auth & OTP
All authentication flows use a two-step process: register/request OTP β verify OTP. Every request must include
X-API-KEY: your-api-key and Accept: application/json headers.
/api/auth/register
Create a new user account. A 6-digit OTP is sent to the provided email or phone for verification before the account is activated.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
login_type |
string | Required | email or phone |
email |
string | Required if email | Valid, unique email address |
phone |
string | Required if phone | Valid, unique phone number |
password |
string | Required | 8β32 chars. Must contain uppercase, lowercase, and a digit |
password_confirmation |
string | Required | Must match password |
role |
string | Optional | employee, manager, or admin. Defaults to
employee
|
first_name |
string | Optional | First name (max 100) |
last_name |
string | Optional | Last name (max 100) |
curl -X POST https://api.mohammedzom.online/api/auth/register \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"login_type": "email",
"email": "john.doe@example.com",
"password": "Secret123!",
"role": "employee"
}'
{
"success": true,
"message": "Account created successfully. Please verify your OTP code.",
"data": {
"user_id": 42,
"identifier": "john.doe@example.com",
"login_type": "email",
"otp_type": "registration"
}
}
{
"message": "The email has already been taken.",
"errors": {
"email": ["The email has already been taken."]
}
}
/api/auth/send-otp
Request a new OTP code for registration (resend) or
password_reset. Password reset is only available for email accounts.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | Required | registration or password_reset |
login_type |
string | Required | email or phone |
identifier |
string | Required | Email or phone number matching login_type |
curl -X POST https://api.mohammedzom.online/api/auth/send-otp \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"type": "registration",
"login_type": "email",
"identifier": "john.doe@example.com"
}'
{
"success": true,
"message": "OTP code sent successfully.",
"data": {
"identifier": "john.doe@example.com",
"login_type": "email",
"otp_type": "registration"
}
}
{
"success": false,
"message": "Please register first.",
"data": null,
"error_code": "User_NOT_Registered"
}
/api/auth/verify-otp
Verify the OTP for account registration. On success, the account is activated and a Bearer token is returned.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
identifier |
string | Required | Email or phone number |
code |
string | Required | 6-digit OTP code |
type |
string | Required | Must be registration |
curl -X POST https://api.mohammedzom.online/api/auth/verify-otp \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"identifier": "john.doe@example.com",
"code": "482910",
"type": "registration"
}'
{
"success": true,
"message": "OTP verified successfully.",
"data": {
"user": {
"id": 42,
"email": "john.doe@example.com",
"role": "employee",
"is_active": true
},
"access_token": "1|abc123xyz...",
"token_type": "Bearer"
}
}
{
"success": false,
"message": "Invalid or expired OTP code.",
"data": null,
"error_code": "INVALID_OTP"
}
/api/auth/check-forgot-password-otp
Validate the password-reset OTP without changing the password. Use this to verify the OTP is correct before rendering the new-password form.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
identifier |
string | Required | User email address |
code |
string | Required | 6-digit OTP code (size:6) |
curl -X POST https://api.mohammedzom.online/api/auth/check-forgot-password-otp \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"identifier": "john.doe@example.com",
"code": "291847"
}'
{
"success": true,
"message": "OTP code is valid.",
"data": null
}
/api/auth/forgot-password
Reset the user's password using a valid OTP code. All existing tokens are revoked on success and a new Bearer token is issued.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
identifier |
string (email) | Required | User email address |
code |
string | Required | 6-digit OTP code |
password |
string | Required | New password (min:6) |
password_confirmation |
string | Required | Must match password |
curl -X POST https://api.mohammedzom.online/api/auth/forgot-password \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"identifier": "john.doe@example.com",
"code": "291847",
"password": "NewSecret456!",
"password_confirmation": "NewSecret456!"
}'
{
"success": true,
"message": "Password has been reset successfully.",
"data": {
"user": { "id": 42, "email": "john.doe@example.com" },
"access_token": "2|def456uvw...",
"token_type": "Bearer"
}
}
/api/auth/login
Authenticate a user and receive a Bearer token. The response also includes the
employee profile object (or null if not yet completed) and a profile_completed
flag.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
login_type |
string | Required | email or phone |
identifier |
string | Required | Email or phone number |
password |
string | Required | Account password |
403 ACCOUNT_NOT_VERIFIED error.
curl -X POST https://api.mohammedzom.online/api/auth/login \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"login_type": "email",
"identifier": "john.doe@example.com",
"password": "Secret123!"
}'
{
"success": true,
"message": "Login successful.",
"data": {
"user": {
"id": 42,
"email": "john.doe@example.com",
"role": "employee",
"login_type": "email",
"is_active": true
},
"employee": {
"id": 7,
"first_name": "John",
"last_name": "Doe",
"employee_code": "EMP000042",
"job_title": "Software Engineer"
},
"access_token": "1|abc123xyz...",
"token_type": "Bearer",
"profile_completed": true
}
}
{
"success": false,
"message": "Invalid credentials.",
"data": null,
"error_code": "INVALID_CREDENTIALS"
}
/api/auth/logout
Revoke the current access token. Use /api/auth/logout-all to revoke
all tokens from all devices.
Headers
| Header | Value |
|---|---|
Authorization |
Bearer {token} |
X-API-KEY |
your-api-key |
curl -X POST https://api.mohammedzom.online/api/auth/logout \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Logout successful.",
"data": null
}
/api/auth/change-password
Change the authenticated user's password. All existing tokens are revoked on success β the user must log in again. New password must differ from the current one.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
current_password |
string | Required | User's current password |
new_password |
string | Required | New password (min:6) |
new_password_confirmation |
string | Required | Must match new_password |
curl -X POST https://api.mohammedzom.online/api/auth/change-password \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"current_password": "Secret123!",
"new_password": "NewSecret456!",
"new_password_confirmation": "NewSecret456!"
}'
{
"success": true,
"message": "Password changed successfully. Please log in again.",
"data": null
}
{
"success": false,
"message": "New password must be different from the current password.",
"error_code": "SAME_PASSWORD"
}
/api/auth/delete-account
Permanently delete the authenticated user's account and all associated data.
curl -X DELETE https://api.mohammedzom.online/api/auth/delete-account \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Account has been deleted successfully.",
"data": null
}
My Profile
Manage the authenticated user's employee profile. A profile must be completed before accessing attendance, leaves, tasks, and other profile-restricted endpoints.
/api/profile
Retrieve the authenticated user's employee profile including department and manager details.
curl -X GET https://api.mohammedzom.online/api/profile \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Profile retrieved successfully.",
"data": {
"id": 7,
"user_id": 42,
"employee_code": "EMP000042",
"first_name": "John",
"last_name": "Doe",
"phone": "+966501234567",
"date_of_birth": "1995-04-15",
"gender": "male",
"address": "Riyadh, Saudi Arabia",
"job_title": "Software Engineer",
"employment_type": "full_time",
"hire_date": "2024-01-15",
"status": "active",
"profile_image": "https://cdn.example.com/profiles/emp42.jpg",
"department": { "id": 3, "name": "Engineering" },
"manager": { "id": 5, "first_name": "Sara", "last_name": "Al-Rashidi" }
}
}
{
"success": false,
"message": "Profile not completed yet.",
"data": { "profile_completed": false },
"error_code": "PROFILE_NOT_COMPLETED"
}
/api/profile/complete
Create the employee profile for the authenticated user. Can only be called once β
subsequent calls should use the update endpoint. Returns 409 if a profile already exists.
multipart/form-data when uploading a
profile_image, otherwise application/json is fine.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
first_name |
string | Required | Max 100 characters |
last_name |
string | Required | Max 100 characters |
phone |
string | Optional | Phone number |
date_of_birth |
date | Optional | Format: YYYY-MM-DD |
gender |
string | Optional | male or female |
address |
string | Optional | Full address text |
profile_image |
file | Optional | Image file (jpg/png, max 2MB) |
curl -X POST https://api.mohammedzom.online/api/profile/complete \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-F "first_name=John" \
-F "last_name=Doe" \
-F "gender=male" \
-F "date_of_birth=1995-04-15" \
-F "address=Riyadh, Saudi Arabia" \
-F "profile_image=@/path/to/photo.jpg"
{
"success": true,
"message": "Profile created successfully.",
"data": {
"id": 7,
"employee_code": "EMP000042",
"first_name": "John",
"last_name": "Doe",
"status": "pending",
"employment_type": "full_time",
"hire_date": "2026-02-22"
}
}
{
"success": false,
"message": "Profile already exists. Use update endpoint instead.",
"data": { "id": 7, "first_name": "John", ... }
}
/api/profile
Update the authenticated user's employee profile. All fields are optional (partial
update). Send as multipart/form-data if uploading a new profile image.
Request Body (all optional)
| Field | Type | Description |
|---|---|---|
first_name |
string | Max 100 characters |
last_name |
string | Max 100 characters |
phone |
string | New phone number |
date_of_birth |
date | Format: YYYY-MM-DD |
gender |
string | male or female |
address |
string | Full address text |
profile_image |
file | Replaces existing image |
curl -X PUT https://api.mohammedzom.online/api/profile \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"address": "Jeddah, Saudi Arabia",
"phone": "+966509876543"
}'
{
"success": true,
"message": "Profile updated successfully.",
"data": {
"id": 7,
"first_name": "John",
"last_name": "Doe",
"phone": "+966509876543",
"address": "Jeddah, Saudi Arabia"
}
}
Attendance
Track employee attendance with GPS geofencing. Check-in validates distance from the office location (configured per department). Employees can have breaks within a single attendance record.
OFFICE_LOCATION_NOT_SET.
/api/attendance/check-in
Clock in for the working day. The device's GPS coordinates are validated against
the department's geofence. Status is automatically set to present or late
based on the office work start time.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
latitude |
numeric | Required | Device GPS latitude (e.g. 24.7136) |
longitude |
numeric | Required | Device GPS longitude (e.g. 46.6753) |
proof_image |
string | Optional | URL/path to a check-in selfie (after file upload) |
notes |
string | Optional | Additional notes |
curl -X POST https://api.mohammedzom.online/api/attendance/check-in \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"latitude": 24.7136,
"longitude": 46.6753,
"notes": "Working from office"
}'
{
"success": true,
"message": "Checked in successfully.",
"data": {
"id": 155,
"employee_id": 7,
"date": "2026-02-22",
"check_in_time": "08:52:10",
"check_in_location": "Lat: 24.7136, Long: 46.6753",
"check_out_time": null,
"hours_worked": null,
"overtime_hours": null,
"status": "present",
"notes": "Working from office"
}
}
{
"success": false,
"message": "You are 850 meters away from the office. Allowed radius is 200 meters.",
"error_code": "OUTSIDE_GEOFENCE",
"data": {
"distance_meters": 850,
"allowed_radius": 200,
"department_name": "Engineering"
}
}
/api/attendance/check-out
Clock out and finalize the attendance record. Calculates hours_worked
and overtime_hours automatically. Cannot check out while on an active break.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
location |
string | Optional | Check-out location description |
notes |
string | Optional | End-of-day notes |
curl -X POST https://api.mohammedzom.online/api/attendance/check-out \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "notes": "Done for today" }'
{
"success": true,
"message": "Checked out successfully.",
"data": {
"id": 155,
"check_in_time": "08:52:10",
"check_out_time": "17:05:42",
"hours_worked": 8.22,
"overtime_hours": 0.22,
"status": "present"
}
}
{
"success": false,
"message": "You cannot check out while on break. Please end your break first.",
"error_code": "ACTIVE_BREAK_EXISTS"
}
/api/attendance/today
Get the authenticated employee's attendance record for today. Returns
null data if not yet checked in.
curl -X GET https://api.mohammedzom.online/api/attendance/today \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "No attendance record for today.",
"data": null
}
/api/attendance/history
Retrieve paginated attendance history for the authenticated employee. Defaults to the current month. Supports date-range filtering.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
month |
integer | current month | Month (1β12). Ignored if start_date provided. |
year |
integer | current year | Year. Ignored if start_date provided. |
start_date |
date (Y-m-d) | β | Start of date range (requires end_date) |
end_date |
date (Y-m-d) | β | End of date range (must be β₯ start_date) |
curl -X GET "https://api.mohammedzom.online/api/attendance/history?month=2&year=2026" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Attendance history retrieved.",
"data": {
"month": 2,
"year": 2026,
"summary": {
"total_days": 18,
"present_days": 16,
"late_days": 2,
"absent_days": 0,
"total_hours": 143.5,
"overtime_hours": 7.2
},
"records": [ ... ]
}
}
/api/attendance/break/start
Start a break on the currently active (checked-in, not checked-out) attendance record. Only one break can be active at a time.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
reason |
string | Optional | Reason for break (e.g. lunch, prayer) |
curl -X POST https://api.mohammedzom.online/api/attendance/break/start \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "reason": "Lunch break" }'
{
"success": true,
"message": "Break started successfully.",
"data": {
"id": 88,
"attendance_id": 155,
"break_start": "2026-02-22T12:00:00Z",
"break_end": null,
"reason": "Lunch break",
"duration_minutes": null
}
}
{
"success": false,
"message": "You already have an active break. Please end it first.",
"error_code": "ACTIVE_BREAK_EXISTS"
}
/api/attendance/break/end
End the current active break. The break_end timestamp and
duration_minutes are automatically calculated.
curl -X POST https://api.mohammedzom.online/api/attendance/break/end \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Break ended successfully.",
"data": {
"id": 88,
"break_start": "2026-02-22T12:00:00Z",
"break_end": "2026-02-22T13:00:00Z",
"duration_minutes": 60
}
}
/api/attendance/{id}/details
Get detailed attendance data for a specific record: check-in/out info, all breaks, total break hours, and overtime. Employees can only access their own records.
curl -X GET https://api.mohammedzom.online/api/attendance/155/details \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Attendance details retrieved.",
"data": {
"id": 155,
"employee": { "id": 7, "name": "John Doe", "employee_number": "EMP000042" },
"date": "2026-02-22",
"check_in": { "time": "08:52:10", "location": "Lat: 24.7136, Long: 46.6753" },
"check_out": { "time": "17:05:42", "location": null },
"hours_worked": 8.22,
"overtime_hours": 0.22,
"total_break_hours": 1.0,
"breaks": [
{
"id": 88,
"break_start": "2026-02-22T12:00:00Z",
"break_end": "2026-02-22T13:00:00Z",
"duration_minutes": 60,
"reason": "Lunch break"
}
],
"status": "present",
"notes": "Working from office"
}
}
/api/attendance
List all employees' attendance records with filtering and pagination. Results are ordered by date descending.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
employee_id |
integer | Filter by specific employee |
date |
date (Y-m-d) | Filter by specific date |
status |
string | Filter: present, late, absent,
on_leave
|
per_page |
integer | Records per page (1β100, default 20) |
curl -X GET "https://api.mohammedzom.online/api/attendance?date=2026-02-22&status=late&per_page=10" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Attendance records retrieved.",
"data": [ ... ],
"meta": {
"current_page": 1,
"last_page": 3,
"per_page": 10,
"total": 27,
"from": 1,
"to": 10
}
}
/api/attendance/report
Generate a daily attendance summary report with present/late/absent/on-leave counts, optionally filtered by department.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
date |
date (Y-m-d) | today | The date to report on |
department_id |
integer | β | Filter by department |
curl -X GET "https://api.mohammedzom.online/api/attendance/report?date=2026-02-22&department_id=3" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Attendance report retrieved.",
"data": {
"summary": {
"date": "2026-02-22",
"total_employees": 12,
"present": 9,
"late": 2,
"absent": 1,
"on_leave": 0
},
"records": [ ... ]
}
}
Leaves
Manage leave requests, check leave balances, and handle manager/admin approvals. Weekends (Friday & Saturday) are automatically excluded from working day calculations.
/api/leaves/types
Retrieve all active leave types (e.g., Annual, Sick, Emergency) along with their days-per-year allocation and whether they are paid.
curl -X GET https://api.mohammedzom.online/api/leaves/types \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Leave types retrieved successfully.",
"data": [
{
"id": 1,
"name": "Annual Leave",
"days_per_year": 21,
"is_paid": true,
"is_active": true
},
{
"id": 2,
"name": "Sick Leave",
"days_per_year": 14,
"is_paid": true,
"is_active": true
}
]
}
/api/leaves
List the authenticated employee's own leave requests, ordered by newest first.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status |
string | Filter: pending, approved, rejected,
cancelled
|
curl -X GET "https://api.mohammedzom.online/api/leaves?status=pending" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Leave requests retrieved successfully.",
"data": [
{
"id": 22,
"leave_type": { "id": 1, "name": "Annual Leave" },
"start_date": "2026-03-01",
"end_date": "2026-03-05",
"total_days": 5,
"status": "pending",
"reason": "Family vacation"
}
]
}
/api/leaves
Submit a new leave request. The system checks for overlapping requests, insufficient balance (using locking for transaction safety), and ensures at least one working day is included.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
leave_type_id |
integer | Required | ID from GET /api/leaves/types |
start_date |
date (Y-m-d) | Required | Leave start date |
end_date |
date (Y-m-d) | Required | Leave end date (β₯ start_date) |
reason |
string | Required | Reason for leave (max 1000 chars) |
attachment |
string | Optional | Path to supporting document (after file upload) |
curl -X POST https://api.mohammedzom.online/api/leaves \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"leave_type_id": 1,
"start_date": "2026-03-01",
"end_date": "2026-03-05",
"reason": "Family vacation"
}'
{
"success": true,
"message": "Leave request submitted successfully.",
"data": {
"id": 22,
"leave_type": { "id": 1, "name": "Annual Leave" },
"start_date": "2026-03-01",
"end_date": "2026-03-05",
"total_days": 5,
"status": "pending",
"reason": "Family vacation"
}
}
{
"success": false,
"message": "Insufficient leave balance.",
"data": {
"requested_days": 5,
"remaining_balance": 3
},
"error_code": "INSUFFICIENT_LEAVE_BALANCE"
}
/api/leaves/balance
Get the authenticated employee's leave balance for all active leave types for a given year.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
year |
integer | current year | The year to check balance for |
curl -X GET "https://api.mohammedzom.online/api/leaves/balance?year=2026" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Leave balance retrieved successfully.",
"data": {
"year": 2026,
"balance": [
{
"leave_type": { "id": 1, "name": "Annual Leave" },
"total_days": 21,
"used_days": 5,
"remaining_days": 16
},
{
"leave_type": { "id": 2, "name": "Sick Leave" },
"total_days": 14,
"used_days": 0,
"remaining_days": 14
}
]
}
}
/api/leaves/{id}
Cancel a pending leave request. Only the employee who submitted it can cancel it. Approved requests cannot be cancelled.
curl -X DELETE https://api.mohammedzom.online/api/leaves/22 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Leave request cancelled successfully."
}
/api/leaves/types
Create a new leave type that employees can subsequently request.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Required | Leave type name (max 255) |
code |
string | Required | Unique short code (e.g. ANNUAL, max 255) |
days_per_year |
integer | Required | Annual allowance in working days (β₯ 0) |
is_paid |
boolean | Required | Whether this leave type is paid |
is_active |
boolean | Required | Whether this leave type is currently available |
required_attachment |
boolean | Required | Whether employees must upload an attachment |
max_consecutive_days |
integer | Required | Maximum consecutive days allowed (β₯ 0) |
description |
string | Optional | Internal description (max 255) |
curl -X POST https://api.mohammedzom.online/api/leaves/types \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "Emergency Leave",
"days_per_year": 3,
"is_paid": true
}'
{
"success": true,
"message": "Leave type created successfully.",
"data": { "id": 5, "name": "Emergency Leave", "days_per_year": 3, "is_paid": true }
}
/api/leaves/all
List all employees' leave requests with pagination and filtering.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status |
string | pending, approved, rejected,
cancelled
|
employee_id |
integer | Filter by employee |
per_page |
integer | Records per page (1β100, default 20) |
curl -X GET "https://api.mohammedzom.online/api/leaves/all?status=pending&per_page=20" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
/api/leaves/pending
List all pending leave requests ordered oldest-first (suitable for an approval queue). Optionally filter by department.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
department_id |
integer | Filter by department |
curl -X GET "https://api.mohammedzom.online/api/leaves/pending?department_id=3" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
/api/leaves/{id}/status
Approve or reject a pending leave request. Managers can only approve requests for employees in their own department. A notification is automatically sent to the employee.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
status |
string | Required | approved or rejected |
rejection_reason |
string | Required if rejected | Reason for rejection |
curl -X PUT https://api.mohammedzom.online/api/leaves/22/status \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "status": "approved" }'
{
"success": true,
"message": "Leave request approved successfully.",
"data": {
"id": 22,
"status": "approved",
"approved_by": { "id": 5, "first_name": "Sara" },
"approved_at": "2026-02-22T14:30:00Z"
}
}
{
"success": false,
"message": "You can only approve leave requests for employees in your own department.",
"error_code": "CROSS_DEPARTMENT_APPROVAL_DENIED"
}
Tasks
Create, assign, and track tasks. Employees can view and update tasks assigned to or created by them. Managers and admins have access to all tasks. Status updates trigger automatic notifications.
/api/tasks
List all tasks assigned to the authenticated user, ordered by due date ascending. Includes comment and attachment counts.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status |
string | pending, in_progress, completed,
cancelled |
priority |
string | low, medium, high, urgent |
curl -X GET "https://api.mohammedzom.online/api/tasks?status=in_progress" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Tasks retrieved successfully.",
"data": [
{
"id": 33,
"title": "Implement login screen",
"description": "Build the Flutter login UI",
"status": "in_progress",
"priority": "high",
"due_date": "2026-03-01",
"progress_percentage": 40,
"comments_count": 2,
"attachments_count": 1,
"assigned_to": { "id": 42, "email": "john.doe@example.com" },
"created_by": { "id": 5, "email": "sara@example.com" }
}
]
}
/api/tasks
Create a new task and assign it to a user. The assignee receives an automatic notification upon creation.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | Required | Task title (max 255) |
description |
string | Optional | Detailed task description |
assigned_to_id |
integer | Optional | User ID to assign task to |
priority |
string | Optional | low, medium, high, urgent |
due_date |
date | Optional | Task deadline (Y-m-d) |
status |
string | Optional | Default: pending |
curl -X POST https://api.mohammedzom.online/api/tasks \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"title": "Implement login screen",
"description": "Build the Flutter login UI with validation",
"assigned_to_id": 42,
"priority": "high",
"due_date": "2026-03-01"
}'
{
"success": true,
"message": "Task created successfully.",
"data": {
"id": 33,
"title": "Implement login screen",
"status": "pending",
"priority": "high",
"progress_percentage": 0,
"due_date": "2026-03-01"
}
}
/api/tasks/{id}/status
Update the status (and optionally the progress percentage) of a task. Setting
status to completed automatically sets progress to 100%. The other party (assignee or
creator) receives a notification.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
status |
string | Required | pending, in_progress, completed,
cancelled |
progress_percentage |
integer | Optional | 0β100 (auto-set to 100 if status=completed) |
curl -X PUT https://api.mohammedzom.online/api/tasks/33/status \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "status": "in_progress", "progress_percentage": 40 }'
{
"success": true,
"message": "Task status updated successfully.",
"data": { "id": 33, "status": "in_progress", "progress_percentage": 40 }
}
/api/tasks/{id}/comments
Add a comment to a task. The other party receives a notification.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
comment |
string | Required | Comment text (max 1000 characters) |
curl -X POST https://api.mohammedzom.online/api/tasks/33/comments \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "comment": "I started working on the login form validation." }'
{
"success": true,
"message": "Comment added successfully.",
"data": {
"id": 19,
"task_id": 33,
"comment": "I started working on the login form validation.",
"user": { "id": 42, "email": "john.doe@example.com" },
"created_at": "2026-02-22T15:00:00Z"
}
}
/api/tasks/{id}/attachments
Attach a file reference to a task. Upload the actual file first via the File
Upload API (POST /api/uploads/attachment) and use the returned path here.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
file_name |
string | Required | Display name for the file (max 255) |
file_path |
string | Required | Storage path from the File Upload response |
file_type |
string | Optional | MIME type (max 50 chars) |
file_size |
integer | Optional | File size in bytes |
curl -X POST https://api.mohammedzom.online/api/tasks/33/attachments \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"file_name": "login_mockup.pdf",
"file_path": "attachments/2026/02/login_mockup.pdf",
"file_type": "application/pdf",
"file_size": 204800
}'
/api/tasks/all
List all tasks across all employees with pagination (20 per page).
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status |
string | Filter by status |
assigned_to_id |
integer | Filter by assignee user ID |
curl -X GET "https://api.mohammedzom.online/api/tasks/all?status=pending" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
/api/tasks/{id}
Update any task field. Only the task creator, assignee, or a manager/admin can perform this action.
Request Body (all optional on update)
| Field | Type | Description |
|---|---|---|
title |
string | Task title |
description |
string | Task description |
assigned_to_id |
integer | Reassign to another user |
priority |
string | low, medium, high, urgent |
due_date |
date | New deadline |
curl -X PUT https://api.mohammedzom.online/api/tasks/33 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "due_date": "2026-03-15", "priority": "urgent" }'
/api/tasks/{id}
Delete a task. Only the task creator, assignee, or a manager/admin can delete.
curl -X DELETE https://api.mohammedzom.online/api/tasks/33 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{ "success": true, "message": "Task deleted successfully." }
Expenses
Submit and track employee expense claims. Employees can submit, edit (if still pending), and view their own expenses. Managers and admins can approve/reject expenses and generate reports.
/api/expenses
List the authenticated employee's own expense claims, ordered newest-first.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status |
string | pending, approved, rejected |
category |
string | travel, meals, supplies, equipment,
other
|
curl -X GET "https://api.mohammedzom.online/api/expenses?status=pending" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Expenses retrieved successfully.",
"data": [
{
"id": 55,
"title": "Team Lunch",
"amount": 350.00,
"category": "meals",
"expense_date": "2026-02-20",
"status": "pending",
"description": "Q1 team standup lunch"
}
]
}
/api/expenses
Submit a new expense claim. Status defaults to pending.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | Required | Expense title (max 255) |
amount |
numeric | Required | Amount in SAR, β₯ 0 |
currency |
string | Optional | 3-letter ISO currency code (e.g. SAR) |
category |
string | Required | travel, meals, supplies, equipment,
other
|
expense_date |
date | Required | Date expense occurred (β€ today) |
description |
string | Optional | Additional details |
receipt_path |
string | Optional | Storage path after File Upload |
curl -X POST https://api.mohammedzom.online/api/expenses \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"title": "Team Lunch",
"amount": 350.00,
"category": "meals",
"expense_date": "2026-02-20",
"description": "Q1 team standup lunch"
}'
{
"success": true,
"message": "Expense submitted successfully.",
"data": {
"id": 55,
"title": "Team Lunch",
"amount": 350.00,
"category": "meals",
"status": "pending",
"expense_date": "2026-02-20"
}
}
/api/expenses/{id}
Update a pending expense. Returns 403 if the expense has been approved
or rejected (i.e., already processed).
Request Body (all optional)
| Field | Type | Description |
|---|---|---|
title |
string | Updated title |
amount |
numeric | Updated amount β₯ 0.01 |
category |
string | travel, meals, supplies, equipment,
other
|
expense_date |
date | Date β€ today |
description |
string | Updated description |
curl -X PUT https://api.mohammedzom.online/api/expenses/55 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "amount": 420.00, "description": "Updated: included coffee" }'
{
"success": false,
"message": "Cannot modify a processed expense.",
"error_code": "EXPENSE_ALREADY_PROCESSED"
}
/api/expenses/{id}
Delete a pending expense claim. Approved or rejected expenses cannot be deleted.
curl -X DELETE https://api.mohammedzom.online/api/expenses/55 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{ "success": true, "message": "Expense deleted successfully." }
/api/expenses/all
List all employees' expense claims with filtering and pagination.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status |
string | Filter by status |
employee_id |
integer | Filter by employee |
category |
string | Filter by category |
per_page |
integer | Max 100, default 20 |
curl -X GET "https://api.mohammedzom.online/api/expenses/all?status=pending" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
/api/expenses/{id}/status
Approve or reject a pending expense. The employee receives a notification.
approved_by_id is set to the authenticated employee's ID.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
status |
string | Required | approved or rejected |
rejection_reason |
string | Required if rejected | Reason for rejection |
curl -X PUT https://api.mohammedzom.online/api/expenses/55/status \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "status": "approved" }'
{
"success": true,
"message": "Expense approved successfully.",
"data": {
"id": 55,
"status": "approved",
"approved_by_id": 5,
"approved_at": "2026-02-22T15:00:00Z"
}
}
/api/expenses/report
Generate an expense summary broken down by month, category, and status.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
year |
integer | current year | Year to report |
employee_id |
integer | β | Filter by employee |
curl -X GET "https://api.mohammedzom.online/api/expenses/report?year=2026" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Expense report retrieved.",
"data": {
"year": 2026,
"total_amount": 15820.00,
"approved_amount": 12500.00,
"pending_amount": 3320.00,
"by_category": {
"travel": 6200.00,
"meals": 4100.00,
"supplies": 2200.00,
"equipment": 3320.00
}
}
}
System Expenses
Organization-wide expense management for Managers and Admins. View all employee expenses, filter pending items, approve or reject claims, and generate summary reports.
/api/expenses/all
List all employees' expense claims with optional filtering and pagination.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status |
string | Filter by status: pending, approved, rejected |
employee_id |
integer | Filter by employee |
category |
string | Filter by category |
per_page |
integer | Max 100, default 20 |
curl -X GET "https://api.mohammedzom.online/api/expenses/all?status=pending&per_page=50" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Expenses retrieved successfully.",
"data": [
{
"id": 55,
"title": "Team Lunch",
"amount": 350.00,
"category": "meals",
"status": "pending",
"expense_date": "2026-02-20",
"employee": { "id": 7, "first_name": "Ahmed", "last_name": "Al-Rashidi" }
}
]
}
/api/expenses/pending
List all pending expense claims awaiting manager approval, ordered oldest-first.
curl -X GET https://api.mohammedzom.online/api/expenses/pending \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Pending expenses retrieved successfully.",
"data": [
{
"id": 55,
"title": "Team Lunch",
"amount": 350.00,
"category": "meals",
"status": "pending",
"expense_date": "2026-02-20",
"employee": { "id": 7, "first_name": "Ahmed", "last_name": "Al-Rashidi" }
}
]
}
/api/expenses/{id}/status
Approve or reject a pending expense. The employee receives a notification.
approved_by_id is set to the authenticated manager's employee ID.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
status |
string | Required | approved or rejected |
rejection_reason |
string | Required if rejected | Reason for rejection |
curl -X PUT https://api.mohammedzom.online/api/expenses/55/status \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "status": "approved" }'
{
"success": true,
"message": "Expense approved successfully.",
"data": {
"id": 55,
"status": "approved",
"approved_by_id": 5,
"approved_at": "2026-02-22T15:00:00Z"
}
}
/api/reports/expenses
Generate an expense summary report broken down by month, category, and status.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
year |
integer | current year | Year to report |
employee_id |
integer | β | Filter by specific employee |
curl -X GET "https://api.mohammedzom.online/api/reports/expenses?year=2026" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Expense report retrieved.",
"data": {
"year": 2026,
"total_amount": 15820.00,
"approved_amount": 12500.00,
"pending_amount": 3320.00,
"by_category": {
"travel": 6200.00,
"meals": 4100.00,
"supplies": 2200.00,
"equipment": 3320.00
}
}
}
Office Assets
Manage company-owned assets (laptops, phones, furniture, etc.). Admins manage the inventory and handle assignments. Employees can view assets assigned to them.
/api/assets/my
Retrieve all office assets currently assigned to the authenticated employee.
curl -X GET https://api.mohammedzom.online/api/assets/my \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Your assets retrieved successfully.",
"data": [
{
"id": 14,
"name": "MacBook Pro 16\"",
"asset_code": "AST-00014",
"category": "laptop",
"serial_number": "C02XY123",
"condition": "good",
"status": "assigned",
"assigned_date": "2025-01-15"
}
]
}
/api/assets
List all office assets in the inventory. Includes a summary of asset counts by
status (available, assigned, maintenance).
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status |
string | available, assigned, maintenance,
disposed |
category |
string | laptop, phone, furniture, equipment,
other |
assigned_to_id |
integer | Filter by assigned employee ID |
curl -X GET "https://api.mohammedzom.online/api/assets?category=laptop&status=available" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Assets retrieved successfully.",
"data": {
"summary": {
"total": 42,
"available": 15,
"assigned": 25,
"maintenance": 2
},
"assets": [ ... ]
}
}
/api/assets
Add a new asset to the inventory. The asset code must be unique. Status defaults to
available.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Required | Asset name (max 255) |
asset_code |
string | Required | Unique code (max 50) |
category |
string | Required | laptop, phone, furniture, equipment,
other |
description |
string | Optional | Asset description |
serial_number |
string | Optional | Manufacturer serial number (max 100) |
purchase_price |
numeric | Optional | Purchase price β₯ 0 |
purchase_date |
date | Optional | Date of purchase |
condition |
string | Optional | new, good, fair, poor |
notes |
string | Optional | Internal notes |
curl -X POST https://api.mohammedzom.online/api/assets \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "MacBook Pro 16",
"asset_code": "AST-00014",
"category": "laptop",
"condition": "new",
"purchase_price": 12000,
"purchase_date": "2026-01-10"
}'
{
"success": true,
"message": "Asset created successfully.",
"data": { "id": 14, "name": "MacBook Pro 16", "asset_code": "AST-00014", "status": "available" }
}
/api/assets/{id}/assign
Assign an available asset to an employee. The asset status is set to
assigned and the employee receives a notification.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
employee_id |
integer | Required | ID of the employee to assign the asset to |
curl -X POST https://api.mohammedzom.online/api/assets/14/assign \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "employee_id": 7 }'
{
"success": true,
"message": "Asset assigned successfully.",
"data": {
"id": 14,
"name": "MacBook Pro 16",
"status": "assigned",
"assigned_date": "2026-02-22",
"assigned_to": { "id": 7, "first_name": "John", "last_name": "Doe" }
}
}
{
"success": false,
"message": "Asset is already assigned to another employee."
}
/api/assets/{id}/unassign
Return an asset to the available pool. Clears the assigned_to_id and
resets status to available.
curl -X POST https://api.mohammedzom.online/api/assets/14/unassign \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Asset unassigned successfully.",
"data": { "id": 14, "status": "available", "assigned_to_id": null }
}
/api/assets/{id}
Update asset metadata. Use status maintenance or
disposed to mark the lifecycle state.
Request Body (all optional)
| Field | Type | Description |
|---|---|---|
name |
string | Updated name |
category |
string | laptop, phone, furniture, equipment,
other |
condition |
string | new, good, fair, poor |
status |
string | available, assigned, maintenance,
disposed |
notes |
string | Internal notes |
curl -X PUT https://api.mohammedzom.online/api/assets/14 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "condition": "fair", "notes": "Screen has minor scratch" }'
/api/assets/{id}
Permanently delete an asset record from the inventory.
curl -X DELETE https://api.mohammedzom.online/api/assets/14 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{ "success": true, "message": "Asset deleted successfully." }
System Assets
Admin-level asset inventory management. Create assets, update their details, remove them from inventory, and manage employee assignments. Use the employee-facing Office Assets section for read and assignment endpoints available to Managers.
/api/assets
Add a new asset to the inventory. The asset code must be unique. Status defaults
to available.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Required | Asset name (max 255) |
asset_code |
string | Required | Unique asset code (max 50) |
category |
string | Required | laptop, phone, furniture, equipment, other |
serial_number |
string | Optional | Manufacturer serial number (max 100) |
condition |
string | Optional | new, good, fair, poor |
purchase_date |
date | Optional | Date of purchase |
purchase_price |
numeric | Optional | Purchase price β₯ 0 |
description |
string | Optional | Asset description or notes |
curl -X POST https://api.mohammedzom.online/api/assets \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "MacBook Pro 16\"",
"asset_code": "AST-00020",
"category": "laptop",
"serial_number": "C02XY456",
"condition": "new",
"purchase_date": "2026-01-15",
"purchase_price": 12000.00,
"description": "Work laptop for engineering team"
}'
{
"success": true,
"message": "Asset created successfully.",
"data": { "id": 20, "name": "MacBook Pro 16\"", "asset_code": "AST-00020", "status": "available" }
}
/api/assets/{id}
Update asset metadata. Use status maintenance or
disposed to reflect lifecycle changes.
Request Body (all optional)
| Field | Type | Description |
|---|---|---|
name |
string | Updated asset name |
category |
string | laptop, phone, furniture, equipment, other |
condition |
string | new, good, fair, poor |
status |
string | available, assigned, maintenance, disposed |
notes |
string | Internal notes |
curl -X PUT https://api.mohammedzom.online/api/assets/20 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "condition": "fair", "notes": "Screen has minor scratch" }'
{
"success": true,
"message": "Asset updated successfully.",
"data": { "id": 20, "condition": "fair", "notes": "Screen has minor scratch" }
}
/api/assets/{id}
Permanently delete an asset record from the inventory. Cannot delete an asset that is currently assigned to an employee.
curl -X DELETE https://api.mohammedzom.online/api/assets/20 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{ "success": true, "message": "Asset deleted successfully." }
{ "success": false, "message": "Unauthorized. Admin access required." }
/api/assets/{id}/assign
Assign an available asset to an employee. The asset status changes to
assigned and the employee receives a notification.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
employee_id |
integer | Required | ID of the employee to assign the asset to |
curl -X POST https://api.mohammedzom.online/api/assets/20/assign \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "employee_id": 7 }'
{
"success": true,
"message": "Asset assigned successfully.",
"data": {
"id": 20,
"name": "MacBook Pro 16\"",
"status": "assigned",
"assigned_date": "2026-02-24",
"assigned_to": { "id": 7, "first_name": "Ahmed", "last_name": "Al-Rashidi" }
}
}
/api/assets/{id}/unassign
Return an asset to the available pool. Clears the assigned_to_id
and resets status to available.
curl -X POST https://api.mohammedzom.online/api/assets/20/unassign \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Asset unassigned successfully.",
"data": { "id": 20, "status": "available", "assigned_to_id": null }
}
Messages
Internal direct messaging between users. Messages support soft-deletion: deleted messages are hidden only for the deleting party (either sender or receiver).
/api/messages/inbox
List all received messages for the authenticated user, excluding soft-deleted ones. Returns unread count alongside the message list.
curl -X GET https://api.mohammedzom.online/api/messages/inbox \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Inbox retrieved successfully.",
"data": {
"unread_count": 3,
"messages": [
{
"id": 101,
"message": "Can you submit your timesheet?",
"is_read": false,
"created_at": "2026-02-22T09:00:00Z",
"sender": { "id": 5, "email": "sara@example.com", "name": "Sara Al-Rashidi" }
}
]
}
}
/api/messages/sent
List all messages sent by the authenticated user, excluding soft-deleted ones.
curl -X GET https://api.mohammedzom.online/api/messages/sent \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Sent messages retrieved successfully.",
"data": [
{
"id": 99,
"message": "Please review the attendance report.",
"is_read": true,
"created_at": "2026-02-21T14:00:00Z",
"receiver": { "id": 3, "email": "ali@example.com", "name": "Ali Hassan" }
}
]
}
/api/messages
Send a message to another user. The receiver automatically receives a notification.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
receiver_id |
integer | Required | User ID of the recipient (must exist) |
message |
string | Required | Message body (max 2000 characters) |
curl -X POST https://api.mohammedzom.online/api/messages \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"receiver_id": 5,
"message": "Please review the attendance report."
}'
{
"success": true,
"message": "Message sent successfully.",
"data": {
"id": 101,
"message": "Please review the attendance report.",
"is_read": false,
"created_at": "2026-02-22T09:00:00Z",
"sender": { "id": 42, "email": "john.doe@example.com" },
"receiver": { "id": 5, "email": "sara@example.com" }
}
}
/api/messages/{id}
Retrieve a single message. If the authenticated user is the receiver and the message is unread, it is automatically marked as read.
curl -X GET https://api.mohammedzom.online/api/messages/101 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
/api/messages/{id}
Soft-delete a message for the authenticated user only. If you are the sender,
deleted_by_sender_at is set. If receiver, deleted_by_receiver_at is set. The
message still exists for the other party.
curl -X DELETE https://api.mohammedzom.online/api/messages/101 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{ "success": true, "message": "Message deleted successfully." }
Notifications
In-app notifications are automatically generated by the system for events such as leave approvals, task assignments, payroll updates, and new messages. Employees can list, filter, mark as read, and delete their notifications.
/api/notifications
Retrieve all notifications for the authenticated user, ordered newest-first. Includes a global unread count.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
unread |
boolean (1/0) | Set to 1 to return only unread notifications |
type |
string | Filter by type: task, leave, payroll,
asset, expense, message |
curl -X GET "https://api.mohammedzom.online/api/notifications?unread=1" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Notifications retrieved successfully.",
"data": {
"unread_count": 4,
"notifications": [
{
"id": 211,
"title": "Leave Request Approved",
"message": "Your annual leave request (Mar 1β5) has been approved.",
"type": "leave",
"is_read": false,
"read_at": null,
"created_at": "2026-02-22T11:00:00Z"
},
{
"id": 209,
"title": "Payroll Status Updated",
"message": "Your payroll for 2/2026 is now paid.",
"type": "payroll",
"is_read": false,
"read_at": null,
"created_at": "2026-02-20T09:00:00Z"
}
]
}
}
/api/notifications/{id}/read
Mark a single notification as read. Sets is_read = true and records
the read_at timestamp.
curl -X PUT https://api.mohammedzom.online/api/notifications/211/read \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{ "success": true, "message": "Notification marked as read." }
/api/notifications/read-all
Mark all unread notifications as read in a single request.
curl -X PUT https://api.mohammedzom.online/api/notifications/read-all \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{ "success": true, "message": "All notifications marked as read." }
/api/notifications/{id}
Permanently delete a single notification. Returns 404 if the notification belongs to a different user.
curl -X DELETE https://api.mohammedzom.online/api/notifications/211 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{ "success": true, "message": "Notification deleted successfully." }
/api/notifications/read
Bulk delete all read notifications for the authenticated user. Useful for clearing notification history.
curl -X DELETE https://api.mohammedzom.online/api/notifications/read \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{ "success": true, "message": "Read notifications deleted successfully." }
Dashboard
Pre-aggregated dashboard summaries tailored to each user role. Each endpoint returns read-only statistics in a single request β designed to power frontend home screens.
/api/dashboard/employee
Returns a personal snapshot: today's check-in/out status, this month's attendance summary (present/late/absent/total hours), pending task counts, and leave usage for the current year.
curl -X GET https://api.mohammedzom.online/api/dashboard/employee \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Employee dashboard retrieved.",
"data": {
"employee": {
"id": 7,
"name": "John Doe",
"job_title": "Software Engineer",
"department": "Engineering"
},
"today": {
"date": "2026-02-22",
"checked_in": true,
"checked_out": false,
"status": "present"
},
"this_month": {
"present_days": 16,
"late_days": 2,
"absent_days": 0,
"total_hours": 143.5
},
"tasks": {
"pending": 3,
"overdue": 1
},
"leaves": {
"pending_requests": 0,
"used_days": 5
}
}
}
/api/dashboard/manager
Returns a team overview: today's team presence/absence, pending leave requests from subordinates, and a team task summary.
curl -X GET https://api.mohammedzom.online/api/dashboard/manager \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Manager dashboard retrieved.",
"data": {
"team": {
"total_members": 8,
"present_today": 6,
"absent_today": 2
},
"pending_approvals": {
"leave_requests": 3
},
"tasks": {
"team_pending": 12
}
}
}
/api/dashboard/admin
Returns a company-wide snapshot: employee headcount, today's attendance rates, pending approvals (leaves, tasks, overdue tasks), and current month's payroll totals.
curl -X GET https://api.mohammedzom.online/api/dashboard/admin \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Admin dashboard retrieved.",
"data": {
"employees": { "total": 48, "active": 44, "on_leave": 4 },
"departments": { "total": 6, "active": 6 },
"today_attendance": {
"present": 38,
"late": 3,
"absent": 3,
"attendance_rate": 79.2
},
"pending_items": {
"leave_requests": 5,
"tasks": 18,
"overdue_tasks": 2
},
"payroll": {
"month": 2,
"year": 2026,
"total": 440000.00,
"paid": 350000.00,
"pending": 90000.00
}
}
}
/api/dashboard/stats
Compact key metrics: total employees, active count, department count, today's check-ins, pending leaves, and active task count.
curl -X GET https://api.mohammedzom.online/api/dashboard/stats \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Statistics retrieved.",
"data": {
"date": "2026-02-22",
"employees": { "total": 48, "active": 44 },
"departments": 6,
"today_attendance": 41,
"pending_leaves": 5,
"active_tasks": 20
}
}
/api/dashboard/burnout-stats
Employee wellness endpoint. Returns a burnout risk score (0β100) and risk level (low,
medium, high) based on:
overtime hours, overdue/pending tasks, attendance patterns, and leave usage. Includes personalized
recommendations.
curl -X GET https://api.mohammedzom.online/api/dashboard/burnout-stats \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Burnout stats retrieved.",
"data": {
"period": { "month": 2, "year": 2026 },
"work_hours": {
"total_hours": 172.5,
"overtime_hours": 20.5,
"expected_hours": 160,
"overtime_percentage": 12.8
},
"attendance": {
"working_days": 20,
"late_days": 3,
"late_percentage": 15.0
},
"tasks": {
"pending": 5,
"overdue": 2,
"completed_this_month": 8
},
"leaves": { "days_taken_this_year": 3 },
"burnout_assessment": {
"risk_score": 52,
"risk_level": "medium",
"recommendations": [
"You have not taken enough leave days. Rest is important!",
"You have several overdue tasks. Consider prioritizing or delegating."
]
}
}
}
Employee Management
Manage employee records across the organization. Managers can list and view employees; only Admins can create, update, or delete employee accounts.
inactive) via the EmployeeObserver. This action is irreversible
without direct database access.
/api/employees
List all employees with optional filtering. Results include department and user details.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
department_id |
integer | Filter by department |
status |
string | active, inactive, on_leave |
search |
string | Search by name, email, or employee code |
curl -X GET "https://api.mohammedzom.online/api/employees?department_id=3&status=active" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Employees retrieved successfully.",
"data": [
{
"id": 7,
"employee_code": "EMP000007",
"first_name": "Ahmed",
"last_name": "Al-Rashidi",
"job_title": "Software Engineer",
"employment_type": "full_time",
"hire_date": "2025-01-15",
"status": "active",
"base_salary": 8000.00,
"department": { "id": 3, "name": "Engineering" },
"user": { "id": 42, "email": "ahmed@company.com" }
}
]
}
/api/employees/{id}
Retrieve full details for a single employee record.
curl -X GET https://api.mohammedzom.online/api/employees/7 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Employee retrieved successfully.",
"data": {
"id": 7,
"employee_code": "EMP000007",
"first_name": "Ahmed",
"last_name": "Al-Rashidi",
"phone": "+966501234567",
"date_of_birth": "1995-01-15",
"gender": "male",
"national_id": "1234567890",
"address": "Riyadh, Saudi Arabia",
"job_title": "Software Engineer",
"employment_type": "full_time",
"hire_date": "2026-02-01",
"status": "active",
"base_salary": 8000.00,
"department": { "id": 3, "name": "Engineering" },
"user": { "id": 42, "email": "ahmed@company.com" }
}
}
{ "success": false, "message": "Employee not found." }
/api/employees
Create a new employee account. A user account is automatically created and linked to the employee record.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Required | Unique email address |
password |
string | Required | Min 8 characters |
first_name |
string | Required | Employee first name |
last_name |
string | Required | Employee last name |
phone |
string | Optional | Phone number |
date_of_birth |
date | Optional | Format: YYYY-MM-DD |
gender |
string | Optional | male or female |
national_id |
string | Optional | National ID number |
address |
string | Optional | Home address |
department_id |
integer | Required | ID of the department |
job_title |
string | Required | Job title (max 100) |
employment_type |
string | Required | full_time, part_time, contract |
hire_date |
date | Required | Format: YYYY-MM-DD |
base_salary |
numeric | Required | Monthly base salary β₯ 0 |
role |
string | Optional | employee, manager, admin (default: employee) |
curl -X POST https://api.mohammedzom.online/api/employees \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"email": "new@company.com",
"password": "Password123!",
"first_name": "Ahmed",
"last_name": "Al-Rashidi",
"phone": "+966501234567",
"date_of_birth": "1995-01-15",
"gender": "male",
"national_id": "1234567890",
"address": "Riyadh, Saudi Arabia",
"department_id": 1,
"job_title": "Software Engineer",
"employment_type": "full_time",
"hire_date": "2026-02-01",
"base_salary": 8000,
"role": "employee"
}'
{
"success": true,
"message": "Employee created successfully.",
"data": {
"id": 7,
"employee_code": "EMP000007",
"first_name": "Ahmed",
"last_name": "Al-Rashidi",
"job_title": "Software Engineer",
"status": "active"
}
}
{
"success": false,
"message": "Validation failed.",
"errors": { "email": ["The email has already been taken."] }
}
/api/employees/{id}
Update an existing employee's details. All fields are optional.
Request Body (all optional)
| Field | Type | Description |
|---|---|---|
department_id |
integer | Transfer to another department |
job_title |
string | Updated job title |
base_salary |
numeric | Updated monthly base salary |
status |
string | active, inactive, on_leave |
hire_date |
date | Updated hire date |
curl -X PUT https://api.mohammedzom.online/api/employees/7 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "job_title": "Senior Software Engineer", "base_salary": 10000 }'
{
"success": true,
"message": "Employee updated successfully.",
"data": {
"id": 7,
"job_title": "Senior Software Engineer",
"base_salary": 10000.00
}
}
/api/employees/{id}
Soft-delete an employee record. The associated user account is automatically
deactivated by the EmployeeObserver.
curl -X DELETE https://api.mohammedzom.online/api/employees/7 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{ "success": true, "message": "Employee deleted successfully." }
{ "success": false, "message": "Unauthorized. Admin access required." }
/api/employees/{Employeecode}/profile
Allows a Manager to update the professional profile of an employee under their
supervision, or an Admin to update any employee's profile. Uses
employee_code as the identifier in the URL.
manager_id matches their own user ID.
Admins bypass this check and can update any employee.
URL Parameter
| Parameter | Type | Description |
|---|---|---|
Employeecode |
string | The unique employee code, e.g. EMP000007 |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
job_title |
string | Required | Job title (max 255 chars) |
hire_date |
date | Required | Format: YYYY-MM-DD |
base_salary |
numeric | Required | Monthly base salary |
employment_type |
string | Required | full_time, part_time, contract |
status |
string | Required | active, on_leave, terminated |
department_id |
integer | Optional | Must exist in departments table |
manager_id |
integer | Optional | Must exist in employees table |
hourly_rate |
numeric | Optional | Hourly rate (for part-time / contract) |
termination_date |
date | Optional | Required if status is terminated |
curl -X PUT https://api.mohammedzom.online/api/employees/EMP000007/profile \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"job_title": "Senior Software Engineer",
"hire_date": "2025-01-15",
"base_salary": 10000,
"employment_type": "full_time",
"status": "active",
"department_id": 3,
"manager_id": 2
}'
{
"success": true,
"message": "Employee profile updated successfully.",
"data": {
"id": 7,
"employee_code": "EMP000007",
"first_name": "Ahmed",
"last_name": "Al-Rashidi",
"job_title": "Senior Software Engineer",
"employment_type": "full_time",
"hire_date": "2025-01-15",
"status": "active",
"base_salary": 10000.00,
"department": { "id": 3, "name": "Engineering" },
"manager": { "id": 2, "first_name": "Sara", "last_name": "Ahmed" }
}
}
{ "message": "You are not authorized to update employee profile." }
{ "message": "No query results for model [Employee]." }
Departments
Manage organizational departments including geofencing settings for attendance verification. All authenticated users can read department data; Managers can create and update departments; only Admins can update geofencing locations or delete departments.
latitude, longitude, and radius_meters fields define
the allowed geographic zone for attendance check-in. When an employee clocks in, their GPS
coordinates are compared against their department's geofence. Check-ins outside the radius
are flagged or rejected depending on system configuration.
/api/departments
List all active departments in the organization.
curl -X GET https://api.mohammedzom.online/api/departments \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Departments retrieved successfully.",
"data": [
{
"id": 3,
"name": "Engineering",
"description": "Software development team",
"is_active": true,
"employees_count": 12
}
]
}
/api/departments/{id}
Get full details for a single department, including manager info and geofencing coordinates.
curl -X GET https://api.mohammedzom.online/api/departments/3 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Department retrieved successfully.",
"data": {
"id": 3,
"name": "Engineering",
"description": "Software development team",
"is_active": true,
"latitude": 24.7136,
"longitude": 46.6753,
"radius_meters": 300,
"manager": {
"id": 5,
"first_name": "Sara",
"last_name": "Al-Rashidi"
},
"employees_count": 12
}
}
{ "success": false, "message": "Department not found." }
/api/departments
Create a new department. The department name must be unique.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Required | Unique department name (max 100) |
description |
string | Optional | Department description |
manager_id |
integer | Optional | Employee ID of the department manager |
is_active |
boolean | Optional | Defaults to true |
curl -X POST https://api.mohammedzom.online/api/departments \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "Engineering",
"description": "Software development team",
"manager_id": 5,
"is_active": true
}'
{
"success": true,
"message": "Department created successfully.",
"data": {
"id": 3,
"name": "Engineering",
"description": "Software development team",
"is_active": true
}
}
/api/departments/{id}
Update department name, description, manager, or active status. All fields are optional.
Request Body (all optional)
| Field | Type | Description |
|---|---|---|
name |
string | Updated name (must remain unique) |
description |
string | Updated description |
manager_id |
integer | Change department manager |
is_active |
boolean | Activate or deactivate the department |
curl -X PUT https://api.mohammedzom.online/api/departments/3 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "manager_id": 8, "description": "Backend and frontend engineering" }'
{
"success": true,
"message": "Department updated successfully.",
"data": { "id": 3, "name": "Engineering", "manager_id": 8 }
}
/api/departments/{id}/location
Update the geofencing coordinates for a department. These coordinates are used to validate employee attendance check-ins.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
latitude |
numeric | Required | Latitude of the office location (β90 to 90) |
longitude |
numeric | Required | Longitude of the office location (β180 to 180) |
radius_meters |
integer | Required | Allowed check-in radius in meters (e.g. 300) |
curl -X PUT https://api.mohammedzom.online/api/departments/3/location \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"latitude": 24.7136,
"longitude": 46.6753,
"radius_meters": 300
}'
{
"success": true,
"message": "Department location updated successfully.",
"data": {
"id": 3,
"name": "Engineering",
"latitude": 24.7136,
"longitude": 46.6753,
"radius_meters": 300
}
}
/api/departments/set-department
Assign an employee to a department for the first time. The employee must not already belong to a
department.
If the authenticated user is an Admin, they can optionally specify a custom
manager_id;
otherwise the authenticated manager is automatically set as the employee's manager.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
employee_code |
string | Required | Unique employee code, e.g. EMP000012 |
department_id |
integer | Required | ID of the target department |
manager_id |
integer | Optional | Admin only β ID of the user to set as manager. Defaults to authenticated user's ID. |
curl -X POST https://api.mohammedzom.online/api/departments/set-department \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"employee_code": "EMP000012",
"department_id": 3,
"manager_id": 5
}'
{
"success": true,
"message": "Department set for employee successfully.",
"data": {
"id": 12,
"first_name": "Ahmed",
"last_name": "Hassan",
"department_id": 3,
"manager_id": 5
}
}
{ "success": false, "message": "Employee has already a department.\nUse update endpoint instead." }
/api/departments/update-department
Move an employee to a different department. A Manager can only update employees they
directly manage.
An Admin can update any employee and optionally reassign the manager.
If manager_id is not sent, the employee's current manager remains unchanged.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
employee_code |
string | Required | Unique employee code, e.g. EMP000012 |
department_id |
integer | Required | ID of the new department |
manager_id |
integer | Optional | Admin only β reassign the employee's manager. If omitted, manager stays unchanged. |
curl -X POST https://api.mohammedzom.online/api/departments/update-department \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"employee_code": "EMP000012",
"department_id": 5
}'
{
"success": true,
"message": "Department updated for employee successfully.",
"data": {
"id": 12,
"first_name": "Ahmed",
"last_name": "Hassan",
"department_id": 5,
"manager_id": 5
}
}
{ "success": false, "message": "You are not the manager of this employee." }
/api/departments/{id}
Delete a department. Cannot delete a department that still has active employees assigned to it.
curl -X DELETE https://api.mohammedzom.online/api/departments/3 \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{ "success": true, "message": "Department deleted successfully." }
{ "success": false, "message": "Unauthorized. Admin access required." }
Payroll
Auto-generated payroll based on attendance, leaves, and overtime. Employees view their own payslips; admins generate and manage payroll records. The generation engine handles pro-rating, absence deductions, overtime pay, and paid leave inclusion.
/api/payroll
List all payroll records for the authenticated employee, ordered by year and month descending.
curl -X GET https://api.mohammedzom.online/api/payroll \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Payroll records retrieved successfully.",
"data": [
{
"id": 88,
"month": 2,
"year": 2026,
"basic_salary": 10000.00,
"allowances": 0,
"bonuses": 0,
"overtime_pay": 375.00,
"deductions": 500.00,
"tax": 0,
"net_salary": 9875.00,
"working_days": 20,
"present_days": 19,
"absent_days": 1,
"total_hours": 152.5,
"status": "paid",
"payment_date": "2026-02-28",
"payment_method": "bank_transfer"
}
]
}
/api/payroll/all
List all payroll records for all employees with filtering and pagination.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
employee_id |
integer | Filter by employee |
month |
integer | Filter by month (1β12) β requires year |
year |
integer | Filter by year β requires month |
status |
string | draft, processed, paid |
curl -X GET "https://api.mohammedzom.online/api/payroll/all?month=2&year=2026&status=draft" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
/api/payroll/generate
Auto-generate payroll for a given month and year. The engine calculates:
pro-rated base salary, absence deductions, overtime
pay, and paid leave credits.
Employees with no salary or existing payroll for the period are skipped (reported in
skipped array).
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
month |
integer | Required | 1β12 |
year |
integer | Required | Minimum 2020 |
employee_ids |
array | Optional | Specific employee IDs to generate for. Omit to generate for ALL active employees. |
curl -X POST https://api.mohammedzom.online/api/payroll/generate \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "month": 2, "year": 2026 }'
{
"success": true,
"message": "14 payroll record(s) generated, 2 skipped (already exist).",
"data": {
"generated": [ ... ],
"skipped": [
{
"employee_id": 3,
"employee_name": "Ali Hassan",
"reason": "Payroll already exists for this period.",
"existing_id": 55
}
]
}
}
/api/payroll/{id}/status
Transition a payroll record through the workflow: draft β
processed β paid. When marked as paid, a notification is sent to
the employee.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
status |
string | Required | draft, processed, or paid |
payment_date |
date | Required if status=paid |
Date payment was made |
payment_method |
string | Optional | e.g. bank_transfer, cash |
curl -X PUT https://api.mohammedzom.online/api/payroll/88/status \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"status": "paid",
"payment_date": "2026-02-28",
"payment_method": "bank_transfer"
}'
{
"success": true,
"message": "Payroll status updated successfully.",
"data": {
"id": 88,
"status": "paid",
"payment_date": "2026-02-28",
"payment_method": "bank_transfer"
}
}
/api/payroll/report
Generate a payroll summary report for a specific month/year, including totals for salary, deductions, bonuses, and draft/processed/paid counts.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
month |
integer | current month | 1β12 |
year |
integer | current year | Year to report |
curl -X GET "https://api.mohammedzom.online/api/payroll/report?month=2&year=2026" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Payroll report retrieved successfully.",
"data": {
"summary": {
"month": 2,
"year": 2026,
"total_employees": 14,
"total_basic_salary": 140000.00,
"total_allowances": 0,
"total_bonuses": 0,
"total_deductions": 3500.00,
"total_net_salary": 141750.00,
"draft_count": 0,
"processed_count": 2,
"paid_count": 12
},
"records": [ ... ]
}
}
Reports
Aggregated organizational reports for admins and managers. Each report returns summary statistics for a given period. All endpoints require admin or manager privileges.
/api/reports/attendance
Generate a monthly attendance summary broken down by status (present/late/absent/on_leave), total hours worked, and overtime hours. Optionally filter by department.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
month |
integer | current month | Month (1β12) |
year |
integer | current year | Year |
department_id |
integer | β | Filter by department |
curl -X GET "https://api.mohammedzom.online/api/reports/attendance?month=2&year=2026" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Attendance report retrieved.",
"data": {
"month": 2,
"year": 2026,
"total_records": 880,
"present": 780,
"late": 60,
"absent": 30,
"on_leave": 10,
"total_hours": 6240.0,
"overtime_hours": 145.5
}
}
/api/reports/leave
Generate a yearly leave report showing total requests by status and total days taken.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
year |
integer | current year | Year to report |
curl -X GET "https://api.mohammedzom.online/api/reports/leave?year=2026" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Leave report retrieved.",
"data": {
"year": 2026,
"total_requests": 87,
"approved": 72,
"rejected": 8,
"pending": 5,
"cancelled": 2,
"total_days_taken": 285
}
}
/api/reports/payroll
Generate a year-over-year payroll report with monthly breakdowns including employee count, total salary, and paid amount per month.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
year |
integer | current year | Year to report |
curl -X GET "https://api.mohammedzom.online/api/reports/payroll?year=2026" \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json"
{
"success": true,
"message": "Payroll report retrieved.",
"data": {
"year": 2026,
"total_paid": 4400000.00,
"total_pending": 880000.00,
"monthly": [
{ "month": 1, "total_employees": 44, "total_salary": 440000.00, "paid": 440000.00 },
{ "month": 2, "total_employees": 44, "total_salary": 441250.00, "paid": 350000.00 },
...
]
}
}
File Uploads
Upload files to cloud storage and receive a path that can be used in other API endpoints.
All upload endpoints accept multipart/form-data.
- Upload the file first β receive a
pathin the response. - Pass that
pathvalue to the relevant endpoint field, e.g.:proof_imagewhen checking in attendancereceipt_pathwhen submitting an expenseattachment_pathwhen adding a task attachment
/api/uploads
Upload a single file to cloud storage. Returns the storage path and public URL.
Request Body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
file |
file | Required | The file to upload (binary) |
curl -X POST https://api.mohammedzom.online/api/uploads \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-F "file=@/path/to/receipt.jpg"
{
"success": true,
"message": "File uploaded successfully.",
"data": {
"path": "uploads/2026/02/abc123.jpg",
"url": "https://api.mohammedzom.online/storage/uploads/2026/02/abc123.jpg",
"original_name": "receipt.jpg",
"size": 204800,
"mime_type": "image/jpeg"
}
}
/api/uploads/multiple
Upload multiple files in a single request. Returns an array of file data for each uploaded file.
Request Body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
files[] |
file[] | Required | Array of files to upload |
curl -X POST https://api.mohammedzom.online/api/uploads/multiple \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-F "files[]=@/path/to/file1.pdf" \
-F "files[]=@/path/to/file2.jpg"
{
"success": true,
"message": "Files uploaded successfully.",
"data": [
{
"path": "uploads/2026/02/abc123.pdf",
"url": "https://api.mohammedzom.online/storage/uploads/2026/02/abc123.pdf",
"original_name": "file1.pdf",
"size": 512000,
"mime_type": "application/pdf"
},
{
"path": "uploads/2026/02/def456.jpg",
"url": "https://api.mohammedzom.online/storage/uploads/2026/02/def456.jpg",
"original_name": "file2.jpg",
"size": 102400,
"mime_type": "image/jpeg"
}
]
}
/api/uploads/profile-image
Upload and set the authenticated employee's profile picture. The previous profile image is automatically removed.
Request Body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
image |
file | Required | Profile image (JPEG/PNG, max 2MB) |
curl -X POST https://api.mohammedzom.online/api/uploads/profile-image \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-F "image=@/path/to/avatar.jpg"
{
"success": true,
"message": "Profile image updated successfully.",
"data": {
"path": "profile-images/2026/02/emp7_avatar.jpg",
"url": "https://api.mohammedzom.online/storage/profile-images/2026/02/emp7_avatar.jpg"
}
}
/api/uploads/receipt
Upload an expense receipt image. The returned path should be passed
as receipt_path when submitting an expense claim.
Request Body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
receipt |
file | Required | Receipt image or PDF (max 5MB) |
curl -X POST https://api.mohammedzom.online/api/uploads/receipt \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-F "receipt=@/path/to/receipt.jpg"
{
"success": true,
"message": "Receipt uploaded successfully.",
"data": {
"path": "receipts/2026/02/abc123.jpg",
"url": "https://api.mohammedzom.online/storage/receipts/2026/02/abc123.jpg",
"original_name": "receipt.jpg",
"size": 204800,
"mime_type": "image/jpeg"
}
}
/api/uploads/task-attachment
Upload a file attachment for a task. The returned path should be
passed when updating a task with an attachment.
Request Body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
attachment |
file | Required | Any file type (max 10MB) |
curl -X POST https://api.mohammedzom.online/api/uploads/task-attachment \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-F "attachment=@/path/to/document.pdf"
{
"success": true,
"message": "Attachment uploaded successfully.",
"data": {
"path": "task-attachments/2026/02/abc123.pdf",
"url": "https://api.mohammedzom.online/storage/task-attachments/2026/02/abc123.pdf",
"original_name": "document.pdf",
"size": 512000,
"mime_type": "application/pdf"
}
}
/api/uploads
Delete a previously uploaded file from storage using its path.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
path |
string | Required | Storage path returned by the upload endpoint |
curl -X DELETE https://api.mohammedzom.online/api/uploads \
-H "Authorization: Bearer 1|abc123xyz..." \
-H "X-API-KEY: your-api-key" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "path": "uploads/2026/02/abc123.jpg" }'
{ "success": true, "message": "File deleted successfully." }
{ "success": false, "message": "File not found." }