Patrol System API Documentation

Overview

This document provides comprehensive API documentation for the patrol
system, covering three main resources:
- Patrol Rounds - Admin-managed patrol time slots
- Daily Patrol Summaries - Daily patrol session records
- Patrolling Logs - Individual location patrol records

Base URL: {APP_URL}/api/v1

All authenticated endpoints require Bearer token authentication.

  ---
Patrol Rounds API

1. List Patrol Rounds

GET /patrol-rounds

Retrieve a paginated list of patrol rounds with optional filtering.

Query Parameters:
- is_active (boolean) - Filter by active status
- search (string) - Search by name
- per_page (integer) - Items per page (default: 15)

Response:
{
"success": true,
"message": "Patrol rounds retrieved successfully",
"data": [
{
"id": 1,
"name": "Morning Round",
"start_time": "06:00",
"end_time": "10:00",
"duration": "04:00",
"is_active": true,
"description": "Morning patrol round",
"created_at": "2025-07-23T10:00:00.000000Z",
"updated_at": "2025-07-23T10:00:00.000000Z"                               
}
],
"meta": {
"current_page": 1,
"per_page": 15,
"total": 1,
"last_page": 1                                                              
}
}

2. Create Patrol Round

POST /patrol-rounds

Create a new patrol round (Admin only).

Request Body:
{
"name": "Evening Round",
"start_time": "18:00",
"end_time": "22:00",
"is_active": true,
"description": "Evening patrol covering parking areas"                        
}

Validation Rules:
- name: required, string, max 255 chars, unique
- start_time: required, HH:MM format
- end_time: required, HH:MM format, after start_time
- is_active: boolean (optional, defaults to true)
- description: nullable, string, max 1000 chars

Response: 201 Created                                                           
{
"success": true,
"message": "Patrol round created successfully",
"data": {
"id": 2,
"name": "Evening Round",
"start_time": "18:00",
"end_time": "22:00",
"duration": "04:00",
"is_active": true,
"description": "Evening patrol covering parking areas"                      
}
}

3. Get Patrol Round

GET /patrol-rounds/{id}

Retrieve a specific patrol round by ID.

Response:
{
"success": true,
"message": "Patrol round retrieved successfully",
"data": {
"id": 1,
"name": "Morning Round",
"start_time": "06:00",
"end_time": "10:00",
"duration": "04:00",
"is_active": true,
"description": "Morning patrol round"                                       
}
}

4. Update Patrol Round

PUT /patrol-rounds/{id}

Update an existing patrol round (Admin only).

Request Body:
{
"name": "Updated Morning Round",
"start_time": "05:30",
"end_time": "09:30",
"is_active": true,
"description": "Updated morning patrol description"                           
}

Validation Rules: Same as create, except name uniqueness excludes current       
record.

Response:
{
"success": true,
"message": "Patrol round updated successfully",
"data": {
"id": 1,
"name": "Updated Morning Round",
"start_time": "05:30",
"end_time": "09:30",
"duration": "04:00",
"is_active": true,
"description": "Updated morning patrol description"                         
}
}

5. Delete Patrol Round

DELETE /patrol-rounds/{id}

Delete a patrol round (Admin only). Cannot delete if it has associated
patrol summaries.

Response: 200 OK                                                                
{
"success": true,
"message": "Patrol round deleted successfully",
"data": null                                                                  
}

Error Response: 422 Unprocessable Entity                                        
{
"success": false,
"message": "Cannot delete patrol round that has associated patrol             
summaries"                                                                      
}

6. Get Active Patrol Rounds

GET /patrol-rounds/active

Retrieve all active patrol rounds, ordered by start time.

Response:
{
"success": true,
"message": "Active patrol rounds retrieved successfully",
"data": [
{
"id": 1,
"name": "Morning Round",
"start_time": "06:00",
"end_time": "10:00",
"duration": "04:00",
"is_active": true,
"description": "Morning patrol round"                                     
}
]
}

  ---
Daily Patrol Summaries API

1. List Daily Patrol Summaries

GET /daily-patrol-summaries

Retrieve paginated list of daily patrol summaries with advanced filtering.

Query Parameters:
- filter[guard_id] (integer) - Filter by guard user ID
- filter[patrol_round_id] (integer) - Filter by patrol round ID
- filter[patrol_date] (date) - Filter by specific date
- filter[status] (string) - Filter by status (started, completed,
  cancelled)
- filter[today] (boolean) - Filter for today's summaries
- filter[this_week] (boolean) - Filter for current week
- filter[this_month] (boolean) - Filter for current month
- include (string) - Include relationships: guardUser, patrolRound,
  patrollingLogs
- sort (string) - Sort by: patrol_date, actual_start_time,
  completion_percentage, created_at
- per_page (integer) - Items per page (default: 15)

Response:
{
"success": true,
"message": "Daily patrol summaries retrieved successfully",
"data": [
{
"id": 1,
"guard_id": 5,
"patrol_round_id": 1,
"patrol_date": "2025-07-23",
"total_locations": 10,
"completed_locations": 8,
"missed_locations": 2,
"expected_start_time": "06:00",
"expected_end_time": "10:00",
"actual_start_time": "2025-07-23T06:15:00.000000Z",
"actual_end_time": "2025-07-23T09:45:00.000000Z",
"status": "completed",
"notes": "All locations checked successfully",
"completion_percentage": 80.0,
"actual_duration": "03:30",
"expected_duration": "04:00",
"is_on_time": false,
"is_delayed": true,
"guard_user": {
"id": 5,
"name": "Rajesh Kumar",
"email": "rajesh.kumar@security.com"                                    
},
"patrol_round": {
"id": 1,
"name": "Morning Round",
"start_time": "06:00",
"end_time": "10:00"                                                     
}
}
],
"meta": {
"current_page": 1,
"per_page": 15,
"total": 1,
"last_page": 1                                                              
}
}

2. Create Daily Patrol Summary

POST /daily-patrol-summaries

Create a new daily patrol summary.

Request Body:
{
"guard_id": 5,
"patrol_round_id": 1,
"patrol_date": "2025-07-23",
"total_locations": 10,
"completed_locations": 0,
"missed_locations": 0,
"expected_start_time": "06:00",
"expected_end_time": "10:00",
"actual_start_time": "2025-07-23T06:00:00Z",
"status": "started"                                                           
}

Response: 201 Created                                                           
{
"success": true,
"message": "Daily patrol summary created successfully",
"data": {
"id": 2,
"guard_id": 5,
"patrol_round_id": 1,
"patrol_date": "2025-07-23",
"total_locations": 10,
"completed_locations": 0,
"missed_locations": 0,
"expected_start_time": "06:00",
"expected_end_time": "10:00",
"actual_start_time": "2025-07-23T06:00:00.000000Z",
"actual_end_time": null,
"status": "started",
"notes": null,
"completion_percentage": 0.0                                                
}
}

3. Get Daily Patrol Summary

GET /daily-patrol-summaries/{id}

Retrieve a specific daily patrol summary with relationships.

Response:
{
"success": true,
"message": "Daily patrol summary retrieved successfully",
"data": {
"id": 1,
"guard_id": 5,
"patrol_round_id": 1,
"patrol_date": "2025-07-23",
"total_locations": 10,
"completed_locations": 8,
"missed_locations": 2,
"expected_start_time": "06:00",
"expected_end_time": "10:00",
"actual_start_time": "2025-07-23T06:15:00.000000Z",
"actual_end_time": "2025-07-23T09:45:00.000000Z",
"status": "completed",
"notes": "All locations checked successfully",
"completion_percentage": 80.0,
"actual_duration": "03:30",
"expected_duration": "04:00",
"is_on_time": false,
"is_delayed": true,
"guard_user": {
"id": 5,
"name": "Rajesh Kumar",
"email": "rajesh.kumar@security.com"                                      
},
"patrol_round": {
"id": 1,
"name": "Morning Round",
"start_time": "06:00",
"end_time": "10:00"                                                       
},
"patrolling_logs": [
{
"id": 1,
"location_id": 1,
"patrol_time": "2025-07-23T06:20:00.000000Z",
"status": "checked",
"notes": "Area secure",
"location": {
"id": 1,
"name": "Main Gate",
"location_code": "LOC001"                                             
}
}
]
}
}

4. Update Daily Patrol Summary

PUT /daily-patrol-summaries/{id}

Update an existing daily patrol summary.

Request Body:
{
"completed_locations": 10,
"missed_locations": 0,
"actual_end_time": "2025-07-23T09:30:00Z",
"status": "completed",
"notes": "All locations patrolled successfully"                               
}

Response:
{
"success": true,
"message": "Daily patrol summary updated successfully",
"data": {
"id": 1,
"completed_locations": 10,
"missed_locations": 0,
"actual_end_time": "2025-07-23T09:30:00.000000Z",
"status": "completed",
"notes": "All locations patrolled successfully",
"completion_percentage": 100.0                                              
}
}

5. Delete Daily Patrol Summary

DELETE /daily-patrol-summaries/{id}

Delete a daily patrol summary. Cannot delete if it has associated patrol        
logs.

Response: 200 OK                                                                
{
"success": true,
"message": "Daily patrol summary deleted successfully",
"data": null                                                                  
}

Error Response: 422 Unprocessable Entity                                        
{
"success": false,
"message": "Cannot delete patrol summary that has associated patrol logs"     
}

  ---
Patrolling Logs API

1. List Patrolling Logs

GET /patrolling-logs

Retrieve paginated list of patrolling logs with filtering.

Query Parameters:
- filter[location_id] (integer) - Filter by location ID
- filter[guard_id] (integer) - Filter by guard user ID
- filter[patrol_date] (date) - Filter by patrol date
- filter[status] (string) - Filter by status
- include (string) - Include relationships: location, guardUser
- perPage (integer) - Items per page (default: 15)

Response:
{
"success": true,
"message": "Patrolling logs retrieved successfully",
"data": [
{
"id": 1,
"location_id": 1,
"guard_id": 5,
"daily_patrol_summary_id": 1,
"patrol_date": "2025-07-23",
"patrol_time": "2025-07-23T06:20:00.000000Z",
"status": "checked",
"notes": "Area secure, no issues found",
"issues_found": null,
"location": {
"id": 1,
"name": "Main Gate",
"location_code": "LOC001",
"type": "gate"                                                          
},
"guard_user": {
"id": 5,
"name": "Rajesh Kumar",
"email": "rajesh.kumar@security.com"                                    
}
}
],
"meta": {
"current_page": 1,
"per_page": 15,
"total": 1,
"last_page": 1                                                              
}
}

2. Create Patrolling Log

POST /patrolling-logs

Create a new patrolling log manually.

Request Body:
{
"location_id": 1,
"guard_id": 5,
"daily_patrol_summary_id": 1,
"patrol_date": "2025-07-23",
"patrol_time": "2025-07-23T06:20:00Z",
"status": "checked",
"notes": "Area secure",
"issues_found": null                                                          
}

Response: 201 Created                                                           
{
"success": true,
"message": "Patrolling log has been created successfully!",
"data": {
"id": 2,
"location_id": 1,
"guard_id": 5,
"daily_patrol_summary_id": 1,
"patrol_date": "2025-07-23",
"patrol_time": "2025-07-23T06:20:00.000000Z",
"status": "checked",
"notes": "Area secure",
"issues_found": null                                                        
}
}

3. Get Patrolling Log

GET /patrolling-logs/{id}

Retrieve a specific patrolling log with relationships.

Response:
{
"success": true,
"data": {
"id": 1,
"location_id": 1,
"guard_id": 5,
"daily_patrol_summary_id": 1,
"patrol_date": "2025-07-23",
"patrol_time": "2025-07-23T06:20:00.000000Z",
"status": "checked",
"notes": "Area secure, no issues found",
"issues_found": null,
"location": {
"id": 1,
"name": "Main Gate",
"location_code": "LOC001",
"type": "gate"                                                            
},
"guard_user": {
"id": 5,
"name": "Rajesh Kumar",
"email": "rajesh.kumar@security.com"                                      
}
}
}

4. Update Patrolling Log

PUT /patrolling-logs/{id}

Update an existing patrolling log.

Request Body:
{
"status": "issue_found",
"notes": "Minor maintenance required",
"issues_found": "Gate hinge requires lubrication"                             
}

Response:
{
"success": true,
"message": "Patrolling log has been updated successfully!",
"data": {
"id": 1,
"status": "issue_found",
"notes": "Minor maintenance required",
"issues_found": "Gate hinge requires lubrication"                           
}
}

5. Delete Patrolling Log

DELETE /patrolling-logs/{id}

Delete a patrolling log.

Response: 200 OK                                                                
{
"success": true,
"message": "Patrolling log has been deleted successfully!"                    
}

6. Scan Location (QR/Barcode)

POST /patrolling-logs/scan

Create a patrol log by scanning a location QR code or barcode during active     
patrol.

Request Body:
{
"location_code": "LOC001",
"daily_patrol_summary_id": 1,
"status": "checked",
"notes": "All clear",
"issues_found": null                                                          
}

Validation Rules:
- location_code: required, string (must exist and be active)
- daily_patrol_summary_id: required, must exist and belong to authenticated     
  guard
- status: required, enum (checked, issue_found, maintenance_required)
- notes: nullable, string
- issues_found: nullable, string

Response: 201 Created                                                           
{
"success": true,
"message": "Location patrolled successfully!",
"data": {
"id": 3,
"location_id": 1,
"guard_id": 5,
"daily_patrol_summary_id": 1,
"patrol_date": "2025-07-23",
"patrol_time": "2025-07-23T08:30:00.000000Z",
"status": "checked",
"notes": "All clear",
"issues_found": null,
"location": {
"id": 1,
"name": "Main Gate",
"location_code": "LOC001"                                                 
}
}
}

Error Responses:
- 404 Not Found: Location not found or inactive
- 404 Not Found: Active patrol round not found

7. Start Patrol Round

POST /patrolling-logs/start-patrol-round

Start a new patrol round for the authenticated guard.

Request Body:
{
"patrol_round_id": 1                                                          
}

Validation Rules:
- patrol_round_id: required, must exist in patrol_rounds table

Response: 200 OK                                                                
{
"success": true,
"message": "Patrol round started successfully!",
"data": {
"id": 2,
"guard_id": 5,
"patrol_round_id": 1,
"patrol_date": "2025-07-23",
"total_locations": 10,
"completed_locations": 0,
"missed_locations": 0,
"expected_start_time": "06:00",
"expected_end_time": "10:00",
"actual_start_time": "2025-07-23T06:00:00.000000Z",
"actual_end_time": null,
"status": "started",
"notes": null,
"patrol_round": {
"id": 1,
"name": "Morning Round",
"start_time": "06:00",
"end_time": "10:00"                                                       
}
}
}

Error Responses:
- 422 Unprocessable Entity: Already have active patrol round for this time      
  slot
- 422 Unprocessable Entity: Patrol round is not active

8. Complete Patrol Round

POST /patrolling-logs/complete-patrol-round

Complete an active patrol round and calculate final statistics.

Request Body:
{
"daily_patrol_summary_id": 1,
"notes": "All locations patrolled successfully"                               
}

Validation Rules:
- daily_patrol_summary_id: required, must exist and belong to authenticated     
  guard
- notes: nullable, string

Response: 200 OK                                                                
{
"success": true,
"message": "Patrol round completed successfully!",
"data": {
"id": 1,
"guard_id": 5,
"patrol_round_id": 1,
"patrol_date": "2025-07-23",
"total_locations": 10,
"completed_locations": 8,
"missed_locations": 2,
"expected_start_time": "06:00",
"expected_end_time": "10:00",
"actual_start_time": "2025-07-23T06:00:00.000000Z",
"actual_end_time": "2025-07-23T09:30:00.000000Z",
"status": "completed",
"notes": "All locations patrolled successfully",
"completion_percentage": 80.0,
"patrol_round": {
"id": 1,
"name": "Morning Round",
"start_time": "06:00",
"end_time": "10:00"                                                       
}
}
}

Error Response:
- 404 Not Found: No active patrol round found

  ---
Authentication & Authorization

Authentication

All API endpoints require Bearer token authentication:
Authorization: Bearer {your-token-here}

Roles & Permissions

- Admin: Full access to all endpoints
- Guard: Limited access to patrol operations and their own data
- Owner: Read-only access to patrol summaries

Guard-specific Restrictions

Guards can only:
- View their own patrol summaries and logs
- Start/complete their own patrol rounds
- Scan locations during their active patrol rounds

  ---
Error Responses

Standard Error Format

{
"success": false,
"message": "Error description",
"errors": {
"field_name": ["Field-specific error message"]
}
}

Common HTTP Status Codes

- 200 OK: Success
- 201 Created: Resource created successfully
- 400 Bad Request: Invalid request data
- 401 Unauthorized: Authentication required
- 403 Forbidden: Insufficient permissions
- 404 Not Found: Resource not found
- 422 Unprocessable Entity: Validation errors
- 500 Internal Server Error: Server error

  ---
Rate Limiting

API requests are rate-limited to prevent abuse:
- Authenticated users: 60 requests per minute
- Guest users: 10 requests per minute

Rate limit headers are included in responses:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1642694400
