Mobile API Usage Guide
This section shows how a mobile client uses the currently implemented API. Replace https://jit.sa with the API base URL for the environment being used.
1. Set The API Base URL
API_BASE_URL = https://jit.sa/api/v1All API requests should include:
Accept: application/jsonProtected endpoints also require:
Authorization: Bearer {access_token}Use HTTPS outside local development. Never log or store the access token in plain text.
2. Generate An Employee Token
Send the employee's login credentials to the public login endpoint:
POST /api/v1/auth/login
Content-Type: application/json
Accept: application/json{
"email": "employee@example.com",
"password": "employee-password",
"device_name": "iPhone 15"
}Example with cURL:
curl -X POST "https://jit.sa/api/v1/auth/login" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"email": "employee@example.com",
"password": "employee-password",
"device_name": "iPhone 15"
}'Successful response:
{
"data": {
"token": "1|sanctum-token-value",
"token_type": "Bearer",
"abilities": [
"employee:read",
"employee:write"
],
"employee": {
"id": 25,
"employee_id": "EMP-0025",
"full_name": "Ahmed Ali",
"email": "employee@example.com",
"status": "active",
"tenant": {
"id": 3,
"name": "Example Company",
"slug": "example-company"
}
}
},
"meta": [],
"links": [],
"message": null
}Store data.token securely. The mobile application must not send the employee ID or tenant ID during login or later requests.
3. Add The Token To Protected Requests
Create one shared authenticated HTTP client in the mobile application:
Authorization: Bearer 1|sanctum-token-value
Accept: application/jsonExample:
curl "https://jit.sa/api/v1/me" \
-H "Accept: application/json" \
-H "Authorization: Bearer 1|sanctum-token-value"If the token is missing, expired, or revoked, the API returns 401 Unauthorized. The app should clear the local token and send the employee back to login.
4. Retrieve Employee Details
Use either endpoint below:
GET /api/v1/me
GET /api/v1/me/profilecurl "https://jit.sa/api/v1/me/profile" \
-H "Accept: application/json" \
-H "Authorization: Bearer 1|sanctum-token-value"The response contains employee-safe information such as:
- Employee number and names
- Work email and phone
- Profile photo URL
- Employment status and hire date
- Tenant
- Branch
- Department
- Job title
- Group
- Shift
The response does not allow the mobile app to edit identity, tenant, status, manager, salary, or payroll configuration fields.
5. Retrieve The Employee Dashboard
GET /api/v1/me/dashboardcurl "https://jit.sa/api/v1/me/dashboard" \
-H "Accept: application/json" \
-H "Authorization: Bearer 1|sanctum-token-value"The dashboard response contains:
{
"data": {
"employee": {},
"today_attendance": null,
"leave_balances": [],
"pending_requests_count": 0,
"pending_approvals_count": 0,
"unread_notifications_count": 0,
"recent_payslip": null
},
"meta": [],
"links": [],
"message": null
}Use this endpoint for the first mobile screen instead of making many separate requests during app startup.
6. Update Employee Contact Information
Only the fields below are editable through the profile endpoint:
PATCH /api/v1/me/profile
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access_token}{
"phone": "+966500000000",
"emergency_contact_name": "Family Contact",
"emergency_contact_phone": "+966511111111"
}Do not send employee_id, tenant_id, full_name, email, status, or employment fields. They are not employee-editable API fields.
7. Change The Password
PATCH /api/v1/me/password
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access_token}{
"current_password": "old-password",
"password": "new-password",
"password_confirmation": "new-password"
}The current password, confirmation, and minimum password policy are validated by the server.
8. Retrieve Attendance History
GET /api/v1/me/attendance
GET /api/v1/me/attendance/summary
GET /api/v1/me/attendance/{attendanceId}Supported query parameters for history and summary:
from=2026-08-01
to=2026-08-31
status=present
per_page=25Example:
curl "https://jit.sa/api/v1/me/attendance?from=2026-08-01&to=2026-08-31&status=present" \
-H "Accept: application/json" \
-H "Authorization: Bearer 1|sanctum-token-value"The app should use the returned attendance ID when calling check-out.
9. Submit A Mobile Check-In
A check-in requires a unique Idempotency-Key request header:
POST /api/v1/me/attendance/check-in
Idempotency-Key: check-in-device-20260803-0001
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access_token}{
"client_time": "2026-08-03T08:02:11+03:00",
"gps_location": "24.7136,46.6753",
"notes": "Arrived at the office"
}Example:
curl -X POST "https://jit.sa/api/v1/me/attendance/check-in" \
-H "Accept: application/json" \
-H "Authorization: Bearer 1|sanctum-token-value" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: check-in-device-20260803-0001" \
-d '{
"client_time": "2026-08-03T08:02:11+03:00",
"gps_location": "24.7136,46.6753",
"notes": "Arrived at the office"
}'The server records the authoritative punch time. client_time is retained only as device metadata. If the same idempotency key is sent again, the existing attendance result is returned instead of creating a duplicate punch.
10. Submit A Mobile Check-Out
Use the attendance ID from the active attendance record:
POST /api/v1/me/attendance/{attendanceId}/check-out
Idempotency-Key: check-out-device-20260803-0001
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access_token}curl -X POST "https://jit.sa/api/v1/me/attendance/501/check-out" \
-H "Accept: application/json" \
-H "Authorization: Bearer 1|sanctum-token-value" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: check-out-device-20260803-0001" \
-d '{
"client_time": "2026-08-03T17:01:45+03:00",
"gps_location": "24.7136,46.6753",
"notes": "Leaving the office"
}'Possible attendance conflict codes include:
ATTENDANCE_ALREADY_STARTEDCHECK_IN_REQUIREDCHECK_OUT_BEFORE_CHECK_INATTENDANCE_NOT_ACTIVEIDEMPOTENCY_KEY_REUSED
These return HTTP 409 with the standard API error envelope.
11. Retrieve Leave Balances And History
Balances:
GET /api/v1/me/leave-balancesHistory:
GET /api/v1/me/leaves?status=approved&leave_type=annual&from=2026-01-01&to=2026-12-31
GET /api/v1/me/leaves/{leaveId}Leave records are read-only. To request a new leave, retrieve the appropriate dynamic request type and submit an employee request instead.
12. Retrieve Dynamic Request Types
GET /api/v1/request-types
GET /api/v1/request-types/{requestTypeId}The response includes:
- Request type ID
- Localized name and description
schema_version- Dynamic fields
- Field types
- Required flags
- Select options
- Conditional field information
- Attachment requirements
The mobile app should cache the schema using its schema_version, but it must send the current version when submitting the request.
13. Submit A Dynamic Employee Request
First retrieve a request type. Then submit normalized field keys from its schema:
POST /api/v1/me/requests
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access_token}{
"request_type_id": 12,
"schema_version": 3,
"subject": "Annual leave request",
"description": "Family vacation",
"form_data": {
"leave_type": "annual",
"date_from": "2026-08-10",
"date_to": "2026-08-12",
"notes": "Family vacation"
}
}The server supplies employee_id, tenant_id, status, submitted time, approval state, and side-effect state. Do not send those fields from the app.
If the schema has changed, the API returns 409 SCHEMA_VERSION_MISMATCH. The app should retrieve the request type again and rebuild the form before retrying.
14. Upload A Request Attachment
Only the request owner can upload an attachment, and only while the request is pending:
POST /api/v1/me/requests/{requestId}/attachments
Content-Type: multipart/form-data
Accept: application/json
Authorization: Bearer {access_token}Form field:
attachment: PDF, JPG, JPEG, PNG, DOC, or DOCX file, maximum 5 MB15. Review And Decide On Approvals
List pending approvals:
GET /api/v1/me/approvalsApprove:
POST /api/v1/me/approvals/{requestId}/approve
Content-Type: application/json{
"comment": "Approved."
}Reject:
POST /api/v1/me/approvals/{requestId}/reject
Content-Type: application/json{
"comment": "Please provide the required supporting document."
}The rejection comment is required. Approval requests are restricted to the current approval level and repeated mobile decisions are idempotent.
16. Read Notifications
List notifications:
GET /api/v1/notifications?unread=true&per_page=20Unread count:
GET /api/v1/notifications/unread-countMark one as read:
POST /api/v1/notifications/{notificationId}/readMark all as read:
POST /api/v1/notifications/read-allNotifications are scoped to the authenticated user and tenant. The mobile app should use the notification UUID returned by the list endpoint.
17. Register A Mobile Push Device
POST /api/v1/me/devices
Content-Type: application/json
Accept: application/json
Authorization: Bearer {access_token}{
"device_id": "ios-device-unique-id",
"device_name": "iPhone 15",
"platform": "ios",
"push_token": "provider-push-token",
"app_version": "1.0.0"
}The push token is encrypted at rest and is not returned in API responses. Registering the same device_id updates its current push token and last-seen time.
List registered mobile devices:
GET /api/v1/me/devicesRemove a device:
DELETE /api/v1/me/devices/{deviceId}18. Manage Bearer Sessions
List the authenticated user's Sanctum sessions:
GET /api/v1/auth/devicesRevoke one session:
DELETE /api/v1/auth/devices/{tokenId}The API only permits revoking tokens that belong to the authenticated user.
19. Handle API Errors
Validation errors use HTTP 422:
{
"message": "The given data was invalid.",
"errors": {
"email": ["The email field is required."]
},
"code": "VALIDATION_ERROR"
}Authentication errors use HTTP 401. Ownership and approval errors use HTTP 403 or 404. Business conflicts such as duplicate punches, stale schemas, overlapping work tasks, and invalid approval state use HTTP 409:
{
"message": "A check-in is required before checking out.",
"errors": [],
"code": "CHECK_IN_REQUIRED"
}The mobile client should use code for programmatic handling and message for a localized user-facing fallback.
20. Logout
POST /api/v1/auth/logout
Accept: application/json
Authorization: Bearer {access_token}After a successful logout, delete the locally stored access token and stop using the associated session. The mobile push-device registration may remain available for future login, but the revoked bearer token cannot be reused.
21. OpenAPI Documentation
The current API documentation is generated by Scramble:
Interactive documentation: /docs/api
OpenAPI JSON: /docs/api.jsonThe OpenAPI document includes the current implemented routes only. Planned endpoints such as payroll, private documents, password reset, offline synchronization, and push delivery will appear after their routes are implemented.