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/registerRegister a new user accountPublic
POST/api/auth/loginLogin and receive a Sanctum tokenPublic
POST/api/auth/send-otpSend OTP to the registered emailPublic
POST/api/auth/verify-otpVerify OTP code for email confirmationPublic
POST/api/auth/forgot-passwordSend OTP for password reset flowPublic
POST/api/auth/check-forgot-password-otpCheck the forgot-password OTP validityPublic
POST/api/auth/verify-forgot-password-otpVerify OTP and reset the passwordPublic
POST/api/auth/logoutRevoke the current tokenSanctum
POST/api/auth/logout-allRevoke all tokens for the userSanctum
POST/api/auth/change-passwordChange the authenticated user's passwordSanctum
DELETE/api/auth/delete-accountPermanently delete the user accountSanctum
User Info
GET/api/userRetrieve the authenticated user resourceSanctum
Employee Profile (Self)
GET/api/profileGet the authenticated employee's profileSanctum
POST/api/profile/completeComplete the employee profile for the first timeSanctum
PUT/api/profileUpdate the authenticated employee's profileSanctum
Attendance
POST/api/attendance/check-inClock in with geolocation verificationProfile Required
POST/api/attendance/check-outClock out and finalize the attendance recordProfile Required
GET/api/attendance/todayGet today's attendance record for the authenticated employeeProfile Required
GET/api/attendance/historyGet paginated attendance history for the authenticated employeeProfile Required
POST/api/attendance/break/startStart a break on the current attendance recordProfile Required
POST/api/attendance/break/endEnd the current break and resume workProfile Required
GET/api/attendanceList all employees' attendance recordsManager+
GET/api/attendance/reportGenerate an attendance report for a date rangeManager+
GET/api/attendance/{id}Get a specific attendance record by IDManager+
GET/api/attendance/{id}/detailsGet logs, breaks, and total hours for a recordManager+
Leave Management
GET/api/leaves/typesList all available leave typesSanctum
GET/api/leavesList the authenticated employee's leave requestsProfile Required
POST/api/leavesSubmit a new leave requestProfile Required
GET/api/leaves/balanceGet the employee's remaining leave balanceProfile Required
GET/api/leaves/{id}Get a specific leave requestProfile Required
DELETE/api/leaves/{id}Cancel a pending leave requestProfile Required
POST/api/leaves/typesCreate a new leave typeManager+
GET/api/leaves/allList all employees' leave requestsManager+
GET/api/leaves/pendingList all pending leave requestsManager+
PUT/api/leaves/{id}/statusApprove or reject a leave requestManager+
Task Management
GET/api/tasksList tasks assigned to the authenticated employeeProfile Required
GET/api/tasks/{id}Get a specific taskProfile Required
PUT/api/tasks/{id}/statusUpdate task status (e.g. in_progress β†’ done)Profile Required
GET/api/tasks/{id}/commentsList comments on a taskProfile Required
POST/api/tasks/{id}/commentsAdd a comment to a taskProfile Required
GET/api/tasks/{id}/attachmentsList attachments on a taskProfile Required
POST/api/tasks/{id}/attachmentsUpload an attachment to a taskProfile Required
GET/api/tasks/allList all tasks (all employees)Manager+
POST/api/tasksCreate and assign a new taskManager+
PUT/api/tasks/{id}Update a taskManager+
DELETE/api/tasks/{id}Delete a taskManager+
Expense Management
GET/api/expensesList the authenticated employee's expense claimsSanctum
POST/api/expensesSubmit a new expense claimSanctum
GET/api/expenses/{id}Get a specific expense claimSanctum
PUT/api/expenses/{id}Update a pending expense claimSanctum
DELETE/api/expenses/{id}Delete a pending expense claimSanctum
GET/api/expenses/allList all employees' expense claimsManager+
GET/api/expenses/pendingList all pending expense claimsManager+
PUT/api/expenses/{id}/statusApprove or reject an expense claimManager+
Office Assets
GET/api/assets/myList assets assigned to the authenticated employeeSanctum
GET/api/assetsList all company assetsAdmin Only
POST/api/assetsCreate a new asset recordAdmin Only
GET/api/assets/{id}Get a specific assetAdmin Only
PUT/api/assets/{id}Update an asset recordAdmin Only
DELETE/api/assets/{id}Delete an asset recordAdmin Only
POST/api/assets/{id}/assignAssign an asset to an employeeAdmin Only
POST/api/assets/{id}/unassignUnassign an asset from an employeeAdmin Only
Messages
GET/api/messages/inboxList received messages (inbox)Sanctum
GET/api/messages/sentList sent messagesSanctum
POST/api/messagesSend a new message to another userSanctum
GET/api/messages/{id}Get a single message by IDSanctum
DELETE/api/messages/{id}Delete a messageSanctum
Notifications
GET/api/notificationsList notifications for the authenticated userSanctum
PUT/api/notifications/{id}/readMark a single notification as readSanctum
PUT/api/notifications/read-allMark all notifications as readSanctum
DELETE/api/notifications/{id}Delete a single notificationSanctum
DELETE/api/notifications/readDelete all read notificationsSanctum
Dashboard
GET/api/dashboard/employeeEmployee dashboard β€” personal stats & today's summarySanctum
GET/api/dashboard/burnout-statsEmployee burnout indicators (overtime, leave ratio)Sanctum
GET/api/dashboard/managerManager dashboard β€” team overview & attendanceManager+
GET/api/dashboard/statsCompany-wide counts (employees, departments, etc.)Admin Only
GET/api/dashboard/adminAdmin dashboard β€” full company snapshotAdmin Only
Employee Management
GET/api/employeesList all employeesSanctum
GET/api/employees/{id}Get a single employee by IDSanctum
POST/api/employeesCreate a new employee recordManager+
PUT/api/employees/{id}Update an employee recordManager+
PUT/api/employees/{Employeecode}/profileUpdate employee profile (Manager/Admin)Manager+
DELETE/api/employees/{id}Delete an employee recordManager+
Departments
GET/api/departmentsList all departmentsSanctum
GET/api/departments/{id}Get a single department by IDSanctum
POST/api/departmentsCreate a new departmentManager+
PUT/api/departments/{id}Update department detailsManager+
PUT/api/departments/{id}/locationUpdate department geofence locationManager+
POST/api/departments/set-departmentAssign employee to a department for the first timeManager+
POST/api/departments/update-departmentMove employee to a different departmentManager+
DELETE/api/departments/{id}Delete a departmentManager+
Payroll
GET/api/payrollList the authenticated employee's payroll recordsProfile Required
GET/api/payroll/{id}Get a specific payroll recordProfile Required
GET/api/payroll/allList all employees' payroll recordsAdmin Only
GET/api/payroll/reportGenerate a payroll summary reportAdmin Only
POST/api/payroll/generateGenerate payroll for a pay periodAdmin Only
PUT/api/payroll/{id}/statusUpdate payroll status (e.g. mark as paid)Admin Only
Reports
GET/api/reports/attendanceCompany-wide attendance reportAdmin Only
GET/api/reports/leavesCompany-wide leave reportAdmin Only
GET/api/reports/payrollPayroll summary reportAdmin Only
GET/api/reports/expensesCompany-wide expense reportAdmin Only
File Uploads
POST/api/uploadsUpload a single fileSanctum
POST/api/uploads/multipleUpload multiple files in one requestSanctum
POST/api/uploads/profile-imageUpload and set the employee profile pictureSanctum
POST/api/uploads/receiptUpload an expense receipt imageSanctum
POST/api/uploads/task-attachmentUpload a file attachment for a taskSanctum
DELETE/api/uploadsDelete a previously uploaded file by pathSanctum

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.

Base URL https://api.mohammedzom.online/api
Standard Response Envelope Every response follows the same shape:
JSON
{
  "success": true,
  "message": "Operation successful.",
  "data": { ... }
}
Rate Limiting Protected routes are throttled at 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.

HEADER X-API-KEY Required on ALL requests

All requests must include this header. Requests without a valid API key are rejected before reaching any controller.

HTTP Header
X-API-KEY: your-api-key-here
HEADER Authorization Protected routes only

After a successful login, pass the returned token as a Bearer token. All auth:sanctum-guarded routes require this header.

HTTP Headers
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
400Bad RequestMalformed request body or missing required parameters
401UnauthenticatedMissing or expired Bearer token; invalid API key
403ForbiddenAuthenticated but insufficient role (CheckRole middleware)
404Not FoundResource does not exist or does not belong to the requester
422Validation ErrorRequest passed but failed server-side validation rules
429Too Many RequestsRate limit exceeded β€” wait before retrying
500Server ErrorUnexpected server-side exception β€” check Laravel logs
422 Validation Error Example
{
  "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.

POST /api/auth/register
Public β–Ό

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
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"
  }'
RESPONSE β€” 201 Created
{
  "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"
  }
}
RESPONSE β€” 422 Validation Error
{
  "message": "The email has already been taken.",
  "errors": {
    "email": ["The email has already been taken."]
  }
}
POST /api/auth/send-otp
Public β–Ό

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
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"
  }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "OTP code sent successfully.",
  "data": {
    "identifier": "john.doe@example.com",
    "login_type": "email",
    "otp_type": "registration"
  }
}
RESPONSE β€” 404 Not Registered
{
  "success": false,
  "message": "Please register first.",
  "data": null,
  "error_code": "User_NOT_Registered"
}
POST /api/auth/verify-otp
Public β–Ό

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
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"
  }'
RESPONSE β€” 200 OK
{
  "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"
  }
}
RESPONSE β€” 400 Invalid OTP
{
  "success": false,
  "message": "Invalid or expired OTP code.",
  "data": null,
  "error_code": "INVALID_OTP"
}
POST /api/auth/check-forgot-password-otp
Public β–Ό

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
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"
  }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "OTP code is valid.",
  "data": null
}
POST /api/auth/forgot-password
Public β–Ό

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
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!"
  }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Password has been reset successfully.",
  "data": {
    "user": { "id": 42, "email": "john.doe@example.com" },
    "access_token": "2|def456uvw...",
    "token_type": "Bearer"
  }
}
POST /api/auth/login
Public β–Ό

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
Account Activation Required β€” Accounts not yet verified via OTP will receive a 403 ACCOUNT_NOT_VERIFIED error.
cURL
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!"
  }'
RESPONSE β€” 200 OK
{
  "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
  }
}
RESPONSE β€” 401 Invalid Credentials
{
  "success": false,
  "message": "Invalid credentials.",
  "data": null,
  "error_code": "INVALID_CREDENTIALS"
}
POST /api/auth/logout
Sanctum β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Logout successful.",
  "data": null
}
POST /api/auth/change-password
Sanctum β–Ό

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
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!"
  }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Password changed successfully. Please log in again.",
  "data": null
}
RESPONSE β€” 422 Same Password
{
  "success": false,
  "message": "New password must be different from the current password.",
  "error_code": "SAME_PASSWORD"
}
DELETE /api/auth/delete-account
Sanctum β–Ό

Permanently delete the authenticated user's account and all associated data.

⚠️ Irreversible. This action cannot be undone. All tokens, employee data, and records will be deleted.
cURL
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"
RESPONSE β€” 200 OK
{
  "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.

GET /api/profile
Sanctum β–Ό

Retrieve the authenticated user's employee profile including department and manager details.

cURL
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"
RESPONSE β€” 200 OK
{
  "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" }
  }
}
RESPONSE β€” 404 Profile Not Found
{
  "success": false,
  "message": "Profile not completed yet.",
  "data": { "profile_completed": false },
  "error_code": "PROFILE_NOT_COMPLETED"
}
POST /api/profile/complete
Sanctum β–Ό

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.

Content-Type: Use 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
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"
RESPONSE β€” 201 Created
{
  "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"
  }
}
RESPONSE β€” 409 Already Exists
{
  "success": false,
  "message": "Profile already exists. Use update endpoint instead.",
  "data": { "id": 7, "first_name": "John", ... }
}
PUT /api/profile
Sanctum β–Ό

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
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"
  }'
RESPONSE β€” 200 OK
{
  "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.

Geofencing: The office GPS coordinates and allowed radius are set per Department by an admin. If coordinates are not configured, check-in will be rejected with OFFICE_LOCATION_NOT_SET.
POST /api/attendance/check-in
Profile Required β–Ό

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
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"
  }'
RESPONSE β€” 201 Created
{
  "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"
  }
}
RESPONSE β€” 400 Outside Geofence
{
  "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"
  }
}
POST /api/attendance/check-out
Profile Required β–Ό

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
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" }'
RESPONSE β€” 200 OK
{
  "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"
  }
}
RESPONSE β€” 400 Active Break
{
  "success": false,
  "message": "You cannot check out while on break. Please end your break first.",
  "error_code": "ACTIVE_BREAK_EXISTS"
}
GET /api/attendance/today
Profile Required β–Ό

Get the authenticated employee's attendance record for today. Returns null data if not yet checked in.

cURL
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"
RESPONSE β€” 200 OK (Not checked in)
{
  "success": true,
  "message": "No attendance record for today.",
  "data": null
}
GET /api/attendance/history
Profile Required β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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": [ ... ]
  }
}
POST /api/attendance/break/start
Profile Required β–Ό

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
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" }'
RESPONSE β€” 201 Created
{
  "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
  }
}
RESPONSE β€” 400 Already on Break
{
  "success": false,
  "message": "You already have an active break. Please end it first.",
  "error_code": "ACTIVE_BREAK_EXISTS"
}
POST /api/attendance/break/end
Profile Required β–Ό

End the current active break. The break_end timestamp and duration_minutes are automatically calculated.

cURL
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"
RESPONSE β€” 200 OK
{
  "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
  }
}
GET /api/attendance/{id}/details
Manager+ β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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"
  }
}
GET /api/attendance
Manager+ β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Attendance records retrieved.",
  "data": [ ... ],
  "meta": {
    "current_page": 1,
    "last_page": 3,
    "per_page": 10,
    "total": 27,
    "from": 1,
    "to": 10
  }
}
GET /api/attendance/report
Manager+ β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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.

GET /api/leaves/types
Sanctum β–Ό

Retrieve all active leave types (e.g., Annual, Sick, Emergency) along with their days-per-year allocation and whether they are paid.

cURL
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"
RESPONSE β€” 200 OK
{
  "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
    }
  ]
}
GET /api/leaves
Profile Required β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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"
    }
  ]
}
POST /api/leaves
Profile Required β–Ό

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
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"
  }'
RESPONSE β€” 201 Created
{
  "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"
  }
}
RESPONSE β€” 422 Insufficient Balance
{
  "success": false,
  "message": "Insufficient leave balance.",
  "data": {
    "requested_days": 5,
    "remaining_balance": 3
  },
  "error_code": "INSUFFICIENT_LEAVE_BALANCE"
}
GET /api/leaves/balance
Profile Required β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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
      }
    ]
  }
}
DELETE /api/leaves/{id}
Profile Required β–Ό

Cancel a pending leave request. Only the employee who submitted it can cancel it. Approved requests cannot be cancelled.

cURL
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"
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Leave request cancelled successfully."
}
POST /api/leaves/types
Manager+ β–Ό

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
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
  }'
RESPONSE β€” 201 Created
{
  "success": true,
  "message": "Leave type created successfully.",
  "data": { "id": 5, "name": "Emergency Leave", "days_per_year": 3, "is_paid": true }
}
GET /api/leaves/all
Manager+ β–Ό

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
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"
GET /api/leaves/pending
Manager+ β–Ό

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
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"
PUT /api/leaves/{id}/status
Manager+ β–Ό

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
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" }'
RESPONSE β€” 200 OK
{
  "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"
  }
}
RESPONSE β€” 403 Cross-Department
{
  "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.

GET /api/tasks
Profile Required β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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" }
    }
  ]
}
POST /api/tasks
Manager+ β–Ό

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
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"
  }'
RESPONSE β€” 201 Created
{
  "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"
  }
}
PUT /api/tasks/{id}/status
Profile Required β–Ό

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
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 }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Task status updated successfully.",
  "data": { "id": 33, "status": "in_progress", "progress_percentage": 40 }
}
POST /api/tasks/{id}/comments
Profile Required β–Ό

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
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." }'
RESPONSE β€” 201 Created
{
  "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"
  }
}
POST /api/tasks/{id}/attachments
Profile Required β–Ό

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
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
  }'
GET /api/tasks/all
Manager+ β–Ό

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
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"
PUT /api/tasks/{id}
Manager+ β–Ό

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
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" }'
DELETE /api/tasks/{id}
Manager+ β–Ό

Delete a task. Only the task creator, assignee, or a manager/admin can delete.

cURL
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"
RESPONSE β€” 200 OK
{ "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.

GET /api/expenses
Profile Required β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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"
    }
  ]
}
POST /api/expenses
Profile Required β–Ό

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
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"
  }'
RESPONSE β€” 201 Created
{
  "success": true,
  "message": "Expense submitted successfully.",
  "data": {
    "id": 55,
    "title": "Team Lunch",
    "amount": 350.00,
    "category": "meals",
    "status": "pending",
    "expense_date": "2026-02-20"
  }
}
PUT /api/expenses/{id}
Profile Required β–Ό

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
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" }'
RESPONSE β€” 403 Already Processed
{
  "success": false,
  "message": "Cannot modify a processed expense.",
  "error_code": "EXPENSE_ALREADY_PROCESSED"
}
DELETE /api/expenses/{id}
Profile Required β–Ό

Delete a pending expense claim. Approved or rejected expenses cannot be deleted.

cURL
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"
RESPONSE β€” 200 OK
{ "success": true, "message": "Expense deleted successfully." }
GET /api/expenses/all
Manager+ β–Ό

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
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"
PUT /api/expenses/{id}/status
Manager+ β–Ό

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
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" }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Expense approved successfully.",
  "data": {
    "id": 55,
    "status": "approved",
    "approved_by_id": 5,
    "approved_at": "2026-02-22T15:00:00Z"
  }
}
GET /api/expenses/report
Manager+ β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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.

GET /api/expenses/all
Manager+ β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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" }
    }
  ]
}
GET /api/expenses/pending
Manager+ β–Ό

List all pending expense claims awaiting manager approval, ordered oldest-first.

cURL
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"
RESPONSE β€” 200 OK
{
  "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" }
    }
  ]
}
PUT /api/expenses/{id}/status
Manager+ β–Ό

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
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" }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Expense approved successfully.",
  "data": {
    "id": 55,
    "status": "approved",
    "approved_by_id": 5,
    "approved_at": "2026-02-22T15:00:00Z"
  }
}
GET /api/reports/expenses
Manager+ β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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.

GET /api/assets/my
Sanctum β–Ό

Retrieve all office assets currently assigned to the authenticated employee.

cURL
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"
RESPONSE β€” 200 OK
{
  "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"
    }
  ]
}
GET /api/assets
Manager+ β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Assets retrieved successfully.",
  "data": {
    "summary": {
      "total": 42,
      "available": 15,
      "assigned": 25,
      "maintenance": 2
    },
    "assets": [ ... ]
  }
}
POST /api/assets
Manager+ β–Ό

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
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"
  }'
RESPONSE β€” 201 Created
{
  "success": true,
  "message": "Asset created successfully.",
  "data": { "id": 14, "name": "MacBook Pro 16", "asset_code": "AST-00014", "status": "available" }
}
POST /api/assets/{id}/assign
Manager+ β–Ό

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
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 }'
RESPONSE β€” 200 OK
{
  "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" }
  }
}
RESPONSE β€” 400 Already Assigned
{
  "success": false,
  "message": "Asset is already assigned to another employee."
}
POST /api/assets/{id}/unassign
Manager+ β–Ό

Return an asset to the available pool. Clears the assigned_to_id and resets status to available.

cURL
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"
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Asset unassigned successfully.",
  "data": { "id": 14, "status": "available", "assigned_to_id": null }
}
PUT /api/assets/{id}
Manager+ β–Ό

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
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" }'
DELETE /api/assets/{id}
Manager+ β–Ό

Permanently delete an asset record from the inventory.

cURL
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"
RESPONSE β€” 200 OK
{ "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.

POST /api/assets
Admin Only β–Ό

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
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"
  }'
RESPONSE β€” 201 Created
{
  "success": true,
  "message": "Asset created successfully.",
  "data": { "id": 20, "name": "MacBook Pro 16\"", "asset_code": "AST-00020", "status": "available" }
}
PUT /api/assets/{id}
Admin Only β–Ό

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
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" }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Asset updated successfully.",
  "data": { "id": 20, "condition": "fair", "notes": "Screen has minor scratch" }
}
DELETE /api/assets/{id}
Admin Only β–Ό

Permanently delete an asset record from the inventory. Cannot delete an asset that is currently assigned to an employee.

cURL
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"
RESPONSE β€” 200 OK
{ "success": true, "message": "Asset deleted successfully." }
RESPONSE β€” 403 Forbidden
{ "success": false, "message": "Unauthorized. Admin access required." }
POST /api/assets/{id}/assign
Admin Only β–Ό

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
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 }'
RESPONSE β€” 200 OK
{
  "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" }
  }
}
POST /api/assets/{id}/unassign
Admin Only β–Ό

Return an asset to the available pool. Clears the assigned_to_id and resets status to available.

cURL
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"
RESPONSE β€” 200 OK
{
  "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).

GET /api/messages/inbox
Sanctum β–Ό

List all received messages for the authenticated user, excluding soft-deleted ones. Returns unread count alongside the message list.

cURL
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"
RESPONSE β€” 200 OK
{
  "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" }
      }
    ]
  }
}
GET /api/messages/sent
Sanctum β–Ό

List all messages sent by the authenticated user, excluding soft-deleted ones.

cURL
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"
RESPONSE β€” 200 OK
{
  "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" }
    }
  ]
}
POST /api/messages
Sanctum β–Ό

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
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."
  }'
RESPONSE β€” 201 Created
{
  "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" }
  }
}
GET /api/messages/{id}
Sanctum β–Ό

Retrieve a single message. If the authenticated user is the receiver and the message is unread, it is automatically marked as read.

cURL
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"
DELETE /api/messages/{id}
Sanctum β–Ό

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
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"
RESPONSE β€” 200 OK
{ "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.

Auto-generated: Notifications are created automatically by the API β€” you don't need a separate endpoint to create them. They are triggered by payroll status changes, task assignments/updates, leave approvals, expense decisions, and new messages.
GET /api/notifications
Sanctum β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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"
      }
    ]
  }
}
PUT /api/notifications/{id}/read
Sanctum β–Ό

Mark a single notification as read. Sets is_read = true and records the read_at timestamp.

cURL
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"
RESPONSE β€” 200 OK
{ "success": true, "message": "Notification marked as read." }
PUT /api/notifications/read-all
Sanctum β–Ό

Mark all unread notifications as read in a single request.

cURL
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"
RESPONSE β€” 200 OK
{ "success": true, "message": "All notifications marked as read." }
DELETE /api/notifications/{id}
Sanctum β–Ό

Permanently delete a single notification. Returns 404 if the notification belongs to a different user.

cURL
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"
RESPONSE β€” 200 OK
{ "success": true, "message": "Notification deleted successfully." }
DELETE /api/notifications/read
Sanctum β–Ό

Bulk delete all read notifications for the authenticated user. Useful for clearing notification history.

cURL
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"
RESPONSE β€” 200 OK
{ "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.

GET /api/dashboard/employee
Profile Required β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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
    }
  }
}
GET /api/dashboard/manager
Manager+ β–Ό

Returns a team overview: today's team presence/absence, pending leave requests from subordinates, and a team task summary.

cURL
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"
RESPONSE β€” 200 OK
{
  "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
    }
  }
}
GET /api/dashboard/admin
Admin Only β–Ό

Returns a company-wide snapshot: employee headcount, today's attendance rates, pending approvals (leaves, tasks, overdue tasks), and current month's payroll totals.

cURL
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"
RESPONSE β€” 200 OK
{
  "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
    }
  }
}
GET /api/dashboard/stats
Admin Only β–Ό

Compact key metrics: total employees, active count, department count, today's check-ins, pending leaves, and active task count.

cURL
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"
RESPONSE β€” 200 OK
{
  "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
  }
}
GET /api/dashboard/burnout-stats
Profile Required β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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.

⚠️ EmployeeObserver Deleting an employee automatically deactivates their user account (sets status to inactive) via the EmployeeObserver. This action is irreversible without direct database access.
GET /api/employees
Sanctum β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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" }
    }
  ]
}
GET /api/employees/{id}
Sanctum β–Ό

Retrieve full details for a single employee record.

cURL
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"
RESPONSE β€” 200 OK
{
  "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" }
  }
}
RESPONSE β€” 404 Not Found
{ "success": false, "message": "Employee not found." }
POST /api/employees
Admin Only β–Ό

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
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"
  }'
RESPONSE β€” 201 Created
{
  "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"
  }
}
RESPONSE β€” 422 Validation Error
{
  "success": false,
  "message": "Validation failed.",
  "errors": { "email": ["The email has already been taken."] }
}
PUT /api/employees/{id}
Admin Only β–Ό

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
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 }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Employee updated successfully.",
  "data": {
    "id": 7,
    "job_title": "Senior Software Engineer",
    "base_salary": 10000.00
  }
}
DELETE /api/employees/{id}
Admin Only β–Ό

Soft-delete an employee record. The associated user account is automatically deactivated by the EmployeeObserver.

cURL
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"
RESPONSE β€” 200 OK
{ "success": true, "message": "Employee deleted successfully." }
RESPONSE β€” 403 Forbidden
{ "success": false, "message": "Unauthorized. Admin access required." }
PUT /api/employees/{Employeecode}/profile
Manager+ β–Ό

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.

⚠️ Authorization Rule A Manager can only update employees where 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
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
  }'
RESPONSE β€” 200 OK
{
  "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" }
  }
}
RESPONSE β€” 403 Forbidden
{ "message": "You are not authorized to update employee profile." }
RESPONSE β€” 404 Not Found
{ "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.

πŸ’‘ Geofencing The 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.
GET /api/departments
Sanctum β–Ό

List all active departments in the organization.

cURL
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"
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Departments retrieved successfully.",
  "data": [
    {
      "id": 3,
      "name": "Engineering",
      "description": "Software development team",
      "is_active": true,
      "employees_count": 12
    }
  ]
}
GET /api/departments/{id}
Sanctum β–Ό

Get full details for a single department, including manager info and geofencing coordinates.

cURL
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"
RESPONSE β€” 200 OK
{
  "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
  }
}
RESPONSE β€” 404 Not Found
{ "success": false, "message": "Department not found." }
POST /api/departments
Manager+ β–Ό

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
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
  }'
RESPONSE β€” 201 Created
{
  "success": true,
  "message": "Department created successfully.",
  "data": {
    "id": 3,
    "name": "Engineering",
    "description": "Software development team",
    "is_active": true
  }
}
PUT /api/departments/{id}
Manager+ β–Ό

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
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" }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Department updated successfully.",
  "data": { "id": 3, "name": "Engineering", "manager_id": 8 }
}
PUT /api/departments/{id}/location
Manager+ β–Ό

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
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
  }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Department location updated successfully.",
  "data": {
    "id": 3,
    "name": "Engineering",
    "latitude": 24.7136,
    "longitude": 46.6753,
    "radius_meters": 300
  }
}
POST /api/departments/set-department
Manager+ β–Ό

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
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
  }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Department set for employee successfully.",
  "data": {
    "id": 12,
    "first_name": "Ahmed",
    "last_name": "Hassan",
    "department_id": 3,
    "manager_id": 5
  }
}
RESPONSE β€” 400 Bad Request (already has department)
{ "success": false, "message": "Employee has already a department.\nUse update endpoint instead." }
POST /api/departments/update-department
Manager+ β–Ό

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
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
  }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Department updated for employee successfully.",
  "data": {
    "id": 12,
    "first_name": "Ahmed",
    "last_name": "Hassan",
    "department_id": 5,
    "manager_id": 5
  }
}
RESPONSE β€” 403 Forbidden (not the employee's manager)
{ "success": false, "message": "You are not the manager of this employee." }
DELETE /api/departments/{id}
Manager+ β–Ό

Delete a department. Cannot delete a department that still has active employees assigned to it.

cURL
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"
RESPONSE β€” 200 OK
{ "success": true, "message": "Department deleted successfully." }
RESPONSE β€” 403 Forbidden
{ "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.

GET /api/payroll
Profile Required β–Ό

List all payroll records for the authenticated employee, ordered by year and month descending.

cURL
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"
RESPONSE β€” 200 OK
{
  "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"
    }
  ]
}
GET /api/payroll/all
Admin Only β–Ό

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
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"
POST /api/payroll/generate
Admin Only β–Ό

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).

Weekends (Fri/Sat) are excluded from working-day calculations. Holidays are not yet factored in.

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
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 }'
RESPONSE β€” 201 Created
{
  "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
      }
    ]
  }
}
PUT /api/payroll/{id}/status
Admin Only β–Ό

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
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"
  }'
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Payroll status updated successfully.",
  "data": {
    "id": 88,
    "status": "paid",
    "payment_date": "2026-02-28",
    "payment_method": "bank_transfer"
  }
}
GET /api/payroll/report
Admin Only β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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.

GET /api/reports/attendance
Manager+ β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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
  }
}
GET /api/reports/leave
Manager+ β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "success": true,
  "message": "Leave report retrieved.",
  "data": {
    "year": 2026,
    "total_requests": 87,
    "approved": 72,
    "rejected": 8,
    "pending": 5,
    "cancelled": 2,
    "total_days_taken": 285
  }
}
GET /api/reports/payroll
Admin Only β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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 Workflow
  1. Upload the file first β†’ receive a path in the response.
  2. Pass that path value to the relevant endpoint field, e.g.:
    • proof_image when checking in attendance
    • receipt_path when submitting an expense
    • attachment_path when adding a task attachment
POST /api/uploads
Sanctum β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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"
  }
}
POST /api/uploads/multiple
Sanctum β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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"
    }
  ]
}
POST /api/uploads/profile-image
Sanctum β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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"
  }
}
POST /api/uploads/receipt
Sanctum β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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"
  }
}
POST /api/uploads/task-attachment
Sanctum β–Ό

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
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"
RESPONSE β€” 200 OK
{
  "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"
  }
}
DELETE /api/uploads
Sanctum β–Ό

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
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" }'
RESPONSE β€” 200 OK
{ "success": true, "message": "File deleted successfully." }
RESPONSE β€” 404 Not Found
{ "success": false, "message": "File not found." }