# Admin

**Only** Admin/Super Admin management routes — accounts, access control, finance operations, oversight. RBAC-gated (see [AUTH.md](AUTH.md)) — each sub-section's routes require the matching `{resource}.{action}` permission, shown per-endpoint below. Catalog, geo, branches, and content management (the *data* Admin also manages) live in `06-shared-general.md` instead, since Client/Company/Technician read those same resources through their own routes — Admin's management actions there are cross-linked from this file's relevant sections rather than duplicated. **Where relevant, each sub-section's endpoints note the resulting effect on Client/Technician/Company** — e.g. approving a company (§05) is what makes `company.auth.login` in `01-guest.md` start working; assigning a technician (§07) is what makes an order appear in `03-technician.md` §04's Assigned Orders list.

**101 endpoints in this section.** (Admin-side withdrawal-request review still works via `admin.withdraw-requests.*` but is intentionally left undocumented here as of 2026-08-26 — see `README.md`'s Generation & Verification changelog.)

## 01. Authentication (Session)

#### Logout

**What this does:** Invalidates the current admin JWT.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/auth/logout` |
| **Route name** | `admin.auth.logout` |
| **Guard** | JWT bearer (`auth:api`); account must be `active` |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `401 Unauthorized` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`
- `Authorization: Bearer {token}`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `device_id`
- **Description:** Device ID
- **Type:** `integer`
- **Required:** optional
- **Example:** `device-uuid-123`
- **Validation rules:** `nullable|string|max:255`
- `nullable` — may be null.
- `string` — must be text.
- `max:255` — must not exceed 255.

**Example Request Body:**
```json
{
    "device_id": "device-uuid-123"
}
```

**Actual Success Response(s):**

*{ 200 OK — logout success }*
```json
{
    "status": "success",
    "message": "Logged out successfully.",
    "data": null
}
```

**Actual Error Response(s):**

*{ 401 Unauthorized — 401 Unauthenticated - no token }*
```json
{
    "status": "fail",
    "message": "Unauthenticated, you have to login first",
    "data": null
}
```

**What happens next:** Log in again to obtain a new token.

---

## 02. Admin Profile

#### Update Profile

**What this does:** Updates the authenticated admin's own profile fields.

| | |
|---|---|
| **Method** | `PUT` |
| **Endpoint** | `{{base_url}}/api/v1/admin/profile` |
| **Route name** | `admin.profile.update` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `profile.update` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`
- `Authorization: Bearer {token}`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `name`
- **Description:** Name
- **Type:** `string`
- **Required:** optional
- **Example:** `Example Name`
- **Validation rules:** `sometimes|string|max:160`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:160` — must not exceed 160.
### `email`
- **Description:** Email
- **Type:** `string`
- **Required:** optional
- **Example:** `user@example.com`
- **Validation rules:** `sometimes|email|unique:users,email,1`
- `sometimes` — validated only when the field is present.
- `email` — must be a valid email address.
- `unique:users,email,1` — must be unique (users, email, 1).
### `phone`
- **Description:** Phone
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `sometimes|string|max:20|unique:users,phone,1`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:20` — must not exceed 20.
- `unique:users,phone,1` — must be unique (users, phone, 1).
### `image`
- **Description:** Image
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `nullable|string`
- `nullable` — may be null.
- `string` — must be text.
### `gender`
- **Description:** Gender
- **Type:** `string`
- **Required:** optional
- **Example:** `male`
- **Validation rules:** `sometimes|in:male,female`
- `sometimes` — validated only when the field is present.
- `in:male,female` — must be one of: male, female.
### `birth_date`
- **Description:** Birth Date
- **Type:** `string`
- **Required:** optional
- **Example:** `2026-08-19`
- **Validation rules:** `nullable|date`
- `nullable` — may be null.
- `date` — must be a valid date.

**Example Request Body:**
```json
{
    "name": "Updated Admin Name"
}
```

**Actual Success Response(s):**

*{ 200 OK — update name }*
```json
{
    "status": "success",
    "message": "Profile updated successfully",
    "data": {
        "id": 90,
        "name": "Updated Admin Name",
        "email": "profile.core@example.com",
        "phone": "1099990000",
        "user_type": "super_admin",
        "user_type_label": "Super Admin",
        "status": "active",
        "status_label": "Active",
        "avatar": null,
        "is_email_verified": true,
        "is_phone_verified": false,
        "last_login_at": null,
        "created_at": "2026-08-20T12:09:45.000000Z"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error - email already taken }*
```json
{
    "status": "fail",
    "message": "This email address is already registered.",
    "data": null
}
```

**What happens next:** Fetch `GET /admin/profile` to see the updated record.

---

#### Change Password Profile

**What this does:** Changes the account password after verifying `current_password`.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/profile/change-password` |
| **Route name** | `admin.profile.change-password` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `profile.change-password` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`
- `Authorization: Bearer {token}`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `current_password`
- **Description:** Current Password
- **Type:** `string`
- **Required:** required
- **Example:** `Password123!`
- **Validation rules:** `required|string`
- `required` — must be provided.
- `string` — must be text.
### `password`
- **Description:** New Password
- **Type:** `string`
- **Required:** required
- **Example:** `Password123!`
- **Validation rules:** `required|string|min:8|confirmed`
- `required` — must be provided.
- `string` — must be text.
- `min:8` — must be at least 8.
- `confirmed` — requires a matching *_confirmation field.

**Example Request Body:**
```json
{
    "current_password": "OldPass123",
    "password": "NewPass456",
    "password_confirmation": "NewPass456"
}
```

**Actual Success Response(s):**

*{ 200 OK — password changed }*
```json
{
    "status": "success",
    "message": "Password changed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error - wrong current password }*
```json
{
    "status": "fail",
    "message": "The current password is incorrect.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - password confirmation mismatch }*
```json
{
    "status": "fail",
    "message": "Password confirmation does not match.",
    "data": null
}
```

**What happens next:** The existing token remains valid; no re-login is required unless you also want a fresh token.

---

#### Show Profile Details

**What this does:** Returns the admin's own profile — base account fields plus role-specific profile data (and, for admin, `roles`/`permissions` when loaded).

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/profile` |
| **Route name** | `admin.profile.view` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `profile.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `401 Unauthorized` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`
- `Authorization: Bearer {token}`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — view own profile }*
```json
{
    "status": "success",
    "message": "Profile retrieved successfully",
    "data": {
        "id": 90,
        "name": "Core Admin",
        "email": "profile.core@example.com",
        "phone": "1099990000",
        "user_type": "super_admin",
        "user_type_label": "Super Admin",
        "status": "active",
        "status_label": "Active",
        "avatar": null,
        "is_email_verified": true,
        "is_phone_verified": false,
        "last_login_at": null,
        "created_at": "2026-08-20T12:09:45.000000Z",
        "roles": [],
        "permissions": []
    }
}
```

**Actual Error Response(s):**

*{ 401 Unauthorized — 401 Unauthenticated - no token }*
```json
{
    "status": "fail",
    "message": "Unauthenticated, you have to login first",
    "data": null
}
```

**What happens next:** Use `PUT` on the same endpoint to update editable fields.

---

## 03. Users / Clients

#### List All Users

**What this does:** Returns a paginated, filterable, searchable list of users.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/users?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[status]=active&filters[user_type]=individual&from=2024-01-01&to=2024-12-31` |
| **Route name** | `admin.users.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `users.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[status]` — Filter by status: active, pending, suspended, rejected (optional)
- `filters[user_type]` — Filter by user type: individual, company, technician (optional)
- `from` — Filter from date (optional)
- `to` — Filter to date (optional)

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Users retrieved",
    "data": {
        "data": [
            {
                "id": 2,
                "name": "Sheldon Wintheiser",
                "email": "gulgowski.zoey@example.net",
                "phone": "1814303906",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "individual",
                "user_type_label": "Individual",
                "status": "active",
                "status_label": "Active",
                "roles": [],
                "created_at": "2026-08-20 12:07:53"
            },
            {
                "id": 3,
                "name": "Rosemarie Kohler",
                "email": "mblick@example.org",
                "phone": "1249129369",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "individual",
                "user_type_label": "Individual",
                "status": "active",
                "status_label": "Active",
                "roles": [],
                "created_at": "2026-08-20 12:07:53"
            },
            {
                "id": 4,
                "name": "Caleb O'Connell Sr.",
                "email": "cnienow@example.com",
                "phone": "1813714451",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "individual",
                "user_type_label": "Individual",
                "status": "pending",
                "status_label": "Pending",
                "roles": [],
                "created_at": "2026-08-20 12:07:53"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/users?page=1",
            "last": "http://localhost/api/v1/admin/users?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/users?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/users",
            "per_page": 15,
            "to": 3,
            "total": 3
        }
    }
}
```

*{ 200 OK — filtered by status }*
```json
{
    "status": "success",
    "message": "Users retrieved",
    "data": {
        "data": [
            {
                "id": 4,
                "name": "Caleb O'Connell Sr.",
                "email": "cnienow@example.com",
                "phone": "1813714451",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "individual",
                "user_type_label": "Individual",
                "status": "pending",
                "status_label": "Pending",
                "roles": [],
                "created_at": "2026-08-20 12:07:53"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/users?page=1",
            "last": "http://localhost/api/v1/admin/users?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/users?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/users",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Users retrieved",
    "data": {
        "data": [
            {
                "id": 112,
                "name": "Kareem Monahan",
                "email": "oreilly.tamia@example.net",
                "phone": "1475871809",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "individual",
                "user_type_label": "Individual",
                "status": "active",
                "status_label": "Active",
                "roles": [],
                "created_at": "2026-08-20 12:09:24"
            },
            {
                "id": 113,
                "name": "Ms. Maybell King",
                "email": "friesen.elsa@example.net",
                "phone": "1945270988",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "individual",
                "user_type_label": "Individual",
                "status": "active",
                "status_label": "Active",
                "roles": [],
                "created_at": "2026-08-20 12:09:24"
            },
            {
                "id": 114,
                "name": "Miles McClure",
                "email": "andrew.schowalter@example.org",
                "phone": "1019628508",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "individual",
                "user_type_label": "Individual",
                "status": "pending",
                "status_label": "Pending",
                "roles": [],
                "created_at": "2026-08-20 12:09:24"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/users?page=1",
            "last": "http://localhost/api/v1/admin/users?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/users?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/users",
            "per_page": 15,
            "to": 3,
            "total": 3
        }
    }
}
```

*{ 200 OK — filtered by status }*
```json
{
    "status": "success",
    "message": "Users retrieved",
    "data": {
        "data": [
            {
                "id": 114,
                "name": "Miles McClure",
                "email": "andrew.schowalter@example.org",
                "phone": "1019628508",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "individual",
                "user_type_label": "Individual",
                "status": "pending",
                "status_label": "Pending",
                "roles": [],
                "created_at": "2026-08-20 12:09:24"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/users?page=1",
            "last": "http://localhost/api/v1/admin/users?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/users?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/users",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Users retrieved",
    "data": {
        "data": [
            {
                "id": 112,
                "name": "Shaylee Labadie",
                "email": "heath92@example.org",
                "phone": "1169843252",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "individual",
                "user_type_label": "Individual",
                "status": "active",
                "status_label": "Active",
                "roles": [],
                "created_at": "2026-08-20 12:09:46"
            },
            {
                "id": 113,
                "name": "Ms. River Koelpin",
                "email": "neal.bernhard@example.net",
                "phone": "1533949144",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "individual",
                "user_type_label": "Individual",
                "status": "active",
                "status_label": "Active",
                "roles": [],
                "created_at": "2026-08-20 12:09:46"
            },
            {
                "id": 114,
                "name": "America Lemke",
                "email": "adelbert.stanton@example.net",
                "phone": "1102903722",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "individual",
                "user_type_label": "Individual",
                "status": "pending",
                "status_label": "Pending",
                "roles": [],
                "created_at": "2026-08-20 12:09:46"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/users?page=1",
            "last": "http://localhost/api/v1/admin/users?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/users?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/users",
            "per_page": 15,
            "to": 3,
            "total": 3
        }
    }
}
```

*{ 200 OK — filtered by status }*
```json
{
    "status": "success",
    "message": "Users retrieved",
    "data": {
        "data": [
            {
                "id": 114,
                "name": "America Lemke",
                "email": "adelbert.stanton@example.net",
                "phone": "1102903722",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "individual",
                "user_type_label": "Individual",
                "status": "pending",
                "status_label": "Pending",
                "roles": [],
                "created_at": "2026-08-20 12:09:46"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/users?page=1",
            "last": "http://localhost/api/v1/admin/users?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/users?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/users",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### Show User Details

**What this does:** Returns full details for one user.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/users/:user` |
| **Route name** | `admin.users.show` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `users.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `user` — User ID — seeded example: `3`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 5,
        "name": "Test Individual",
        "email": "individual.store@example.com",
        "phone": "1055500001",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "individual",
        "user_type_label": "Individual",
        "status": "pending",
        "status_label": "Pending",
        "roles": [],
        "created_at": "2026-08-20 12:07:53",
        "locale": "ar",
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "suspension_reason": null,
        "profile": {
            "full_name": "Test Individual Full Name",
            "completed_orders_total": 0,
            "cancelled_orders_total": 0
        },
        "recent_orders": [],
        "recent_ratings": [],
        "assignment_log": [],
        "addresses": [],
        "wallet": null,
        "updated_at": "2026-08-20 12:07:53"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 115,
        "name": "Test Individual",
        "email": "individual.store@example.com",
        "phone": "1055500001",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "individual",
        "user_type_label": "Individual",
        "status": "pending",
        "status_label": "Pending",
        "roles": [],
        "created_at": "2026-08-20 12:09:24",
        "locale": "ar",
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "suspension_reason": null,
        "profile": {
            "full_name": "Test Individual Full Name",
            "completed_orders_total": 0,
            "cancelled_orders_total": 0
        },
        "recent_orders": [],
        "recent_ratings": [],
        "assignment_log": [],
        "addresses": [],
        "wallet": null,
        "updated_at": "2026-08-20 12:09:24"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 115,
        "name": "Test Individual",
        "email": "individual.store@example.com",
        "phone": "1055500001",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "individual",
        "user_type_label": "Individual",
        "status": "pending",
        "status_label": "Pending",
        "roles": [],
        "created_at": "2026-08-20 12:09:46",
        "locale": "ar",
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "suspension_reason": null,
        "profile": {
            "full_name": "Test Individual Full Name",
            "completed_orders_total": 0,
            "cancelled_orders_total": 0
        },
        "recent_orders": [],
        "recent_ratings": [],
        "assignment_log": [],
        "addresses": [],
        "wallet": null,
        "updated_at": "2026-08-20 12:09:46"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use `update` to modify it, or `destroy` to remove it.

---

#### Create New User

**What this does:** Creates a new user.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/users` |
| **Route name** | `admin.users.store` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `users.create` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `201 Created`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `user_type`
- **Description:** Account Type
- **Type:** `string`
- **Required:** required
- **Example:** `super_admin`
- **Validation rules:** `required|in:super_admin,admin,individual,company,technician`
- `required` — must be provided.
- `in:super_admin,admin,individual,company,technician` — must be one of: super_admin, admin, individual, company, technician.
### `name`
- **Description:** Name
- **Type:** `string`
- **Required:** required
- **Example:** `Example Name`
- **Validation rules:** `required|string|max:160`
- `required` — must be provided.
- `string` — must be text.
- `max:160` — must not exceed 160.
### `email`
- **Description:** Email
- **Type:** `string`
- **Required:** required
- **Example:** `user@example.com`
- **Validation rules:** `required|email|unique:users,email,NULL,id`
- `required` — must be provided.
- `email` — must be a valid email address.
- `unique:users,email,NULL,id` — must be unique (users, email, NULL, id).
### `phone`
- **Description:** Phone
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `nullable|string|max:20|unique:users,phone,NULL,id`
- `nullable` — may be null.
- `string` — must be text.
- `max:20` — must not exceed 20.
- `unique:users,phone,NULL,id` — must be unique (users, phone, NULL, id).
### `password`
- **Description:** Password
- **Type:** `string`
- **Required:** required
- **Example:** `Password123!`
- **Validation rules:** `required|nullable|string|min:8`
- `required` — must be provided.
- `nullable` — may be null.
- `string` — must be text.
- `min:8` — must be at least 8.
### `status`
- **Description:** Status
- **Type:** `string`
- **Required:** optional
- **Example:** `pending`
- **Validation rules:** `sometimes|in:pending,active,suspended,rejected`
- `sometimes` — validated only when the field is present.
- `in:pending,active,suspended,rejected` — must be one of: pending, active, suspended, rejected.
### `locale`
- **Description:** Locale
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `nullable|string|max:5`
- `nullable` — may be null.
- `string` — must be text.
- `max:5` — must not exceed 5.
### `full_name`
- **Description:** Full Name
- **Type:** `string`
- **Required:** conditional
- **Example:** `Example Name`
- **Validation rules:** `required_if:user_type,individual,technician|string|max:150`
- `required_if:user_type,individual,technician` — required when user_type, individual, technician.
- `string` — must be text.
- `max:150` — must not exceed 150.
### `legal_name`
- **Description:** Legal Company Name
- **Type:** `string`
- **Required:** conditional
- **Example:** `Example Name`
- **Validation rules:** `required_if:user_type,company|string|max:200`
- `required_if:user_type,company` — required when user_type, company.
- `string` — must be text.
- `max:200` — must not exceed 200.
### `tax_number`
- **Description:** VAT Number
- **Type:** `string`
- **Required:** optional
- **Example:** `300012345600003`
- **Validation rules:** `nullable|string|max:50`
- `nullable` — may be null.
- `string` — must be text.
- `max:50` — must not exceed 50.
### `commercial_registration_no`
- **Description:** Commercial Registration Number
- **Type:** `string`
- **Required:** optional
- **Example:** `1010101010`
- **Validation rules:** `nullable|string|max:50`
- `nullable` — may be null.
- `string` — must be text.
- `max:50` — must not exceed 50.
### `account_owner_phone`
- **Description:** Account Owner Phone
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `nullable|string|max:20`
- `nullable` — may be null.
- `string` — must be text.
- `max:20` — must not exceed 20.
### `category_id`
- **Description:** Service Category
- **Type:** `integer`
- **Required:** conditional
- **Example:** `2`
- **Validation rules:** `required_if:user_type,technician|integer|exists:categories,id`
- `required_if:user_type,technician` — required when user_type, technician.
- `integer` — must be a whole number.
- `exists:categories,id` — must reference an existing record (categories, id).
### `daily_order_capacity`
- **Description:** Daily Order Capacity
- **Type:** `integer`
- **Required:** conditional
- **Example:** `1`
- **Validation rules:** `required_if:user_type,technician|integer|min:1`
- `required_if:user_type,technician` — required when user_type, technician.
- `integer` — must be a whole number.
- `min:1` — must be at least 1.
### `employment_type`
- **Description:** Employment Type
- **Type:** `string`
- **Required:** conditional
- **Example:** `in_house`
- **Validation rules:** `required_if:user_type,technician|string|in:in_house,freelance`
- `required_if:user_type,technician` — required when user_type, technician.
- `string` — must be text.
- `in:in_house,freelance` — must be one of: in_house, freelance.
- **Gates wallet withdrawal eligibility, not just a label.** Only `freelance` technicians can withdraw (`Wallet::isFreelanceTechnician()`) — `in_house` technician wallets are locked at zero.
### `address`
- **Description:** Address
- **Type:** `string`
- **Required:** optional
- **Example:** `123 Main Street, Building A`
- **Validation rules:** `nullable|string|max:255`
- `nullable` — may be null.
- `string` — must be text.
- `max:255` — must not exceed 255.
### `country_id`
- **Description:** Country
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:countries,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:countries,id` — must reference an existing record (countries, id).
### `governorate_id`
- **Description:** City
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:governorates,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:governorates,id` — must reference an existing record (governorates, id).
### `region_id`
- **Description:** District
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:regions,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:regions,id` — must reference an existing record (regions, id).
### `years_experience`
- **Description:** Years experience
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|min:0`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `min:0` — must be at least .
### `coverage_areas`
- **Description:** Coverage Areas (Regions)
- **Type:** `array`
- **Required:** optional
- **Example:** `[1]`
- **Validation rules:** `nullable|array`
- `nullable` — may be null.
- `array` — must be an array.
### `coverage_areas.*`
- **Description:** Coverage areas item
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `integer|exists:regions,id`
- `integer` — must be a whole number.
- `exists:regions,id` — must reference an existing record (regions, id).

**Example Request Body:**
```json
{
    "user_type": "individual",
    "name": "Test Individual",
    "email": "individual.store@example.com",
    "phone": "1055500001",
    "password": "password123",
    "full_name": "Test Individual Full Name"
}
```

**Actual Success Response(s):**

*{ 201 Created — individual }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 5,
        "name": "Test Individual",
        "email": "individual.store@example.com",
        "phone": "1055500001",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "individual",
        "user_type_label": "Individual",
        "status": "pending",
        "status_label": "Pending",
        "roles": [],
        "created_at": "2026-08-20 12:07:53",
        "locale": "ar",
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "suspension_reason": null,
        "profile": {
            "full_name": "Test Individual Full Name",
            "completed_orders_total": 0,
            "cancelled_orders_total": 0
        },
        "recent_orders": [],
        "recent_ratings": [],
        "assignment_log": [],
        "addresses": [],
        "wallet": null,
        "updated_at": "2026-08-20 12:07:53"
    }
}
```

*{ 201 Created — technician }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 6,
        "name": "Test Technician",
        "email": "technician.store@example.com",
        "phone": "1055500002",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "technician",
        "user_type_label": "Technician",
        "status": "pending",
        "status_label": "Pending",
        "roles": [],
        "created_at": "2026-08-20 12:07:53",
        "locale": "ar",
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "suspension_reason": null,
        "profile": {
            "full_name": "Test Technician Full Name",
            "specialty": null,
            "daily_order_capacity": 5,
            "employment_type": "freelance",
            "address": null,
            "availability_status": "unavailable",
            "avg_rating": "0.0",
            "completed_orders_count": 0,
            "governorate": null
        },
        "recent_orders": [],
        "recent_ratings": [],
        "assignment_log": [],
        "addresses": [],
        "wallet": null,
        "updated_at": "2026-08-20 12:07:53"
    }
}
```

*{ 201 Created — individual }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 115,
        "name": "Test Individual",
        "email": "individual.store@example.com",
        "phone": "1055500001",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "individual",
        "user_type_label": "Individual",
        "status": "pending",
        "status_label": "Pending",
        "roles": [],
        "created_at": "2026-08-20 12:09:24",
        "locale": "ar",
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "suspension_reason": null,
        "profile": {
            "full_name": "Test Individual Full Name",
            "completed_orders_total": 0,
            "cancelled_orders_total": 0
        },
        "recent_orders": [],
        "recent_ratings": [],
        "assignment_log": [],
        "addresses": [],
        "wallet": null,
        "updated_at": "2026-08-20 12:09:24"
    }
}
```

*{ 201 Created — technician }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 116,
        "name": "Test Technician",
        "email": "technician.store@example.com",
        "phone": "1055500002",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "technician",
        "user_type_label": "Technician",
        "status": "pending",
        "status_label": "Pending",
        "roles": [],
        "created_at": "2026-08-20 12:09:25",
        "locale": "ar",
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "suspension_reason": null,
        "profile": {
            "full_name": "Test Technician Full Name",
            "specialty": null,
            "daily_order_capacity": 5,
            "employment_type": "freelance",
            "address": null,
            "availability_status": "unavailable",
            "avg_rating": "0.0",
            "completed_orders_count": 0,
            "governorate": null
        },
        "recent_orders": [],
        "recent_ratings": [],
        "assignment_log": [],
        "addresses": [],
        "wallet": null,
        "updated_at": "2026-08-20 12:09:25"
    }
}
```

*{ 201 Created — individual }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 115,
        "name": "Test Individual",
        "email": "individual.store@example.com",
        "phone": "1055500001",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "individual",
        "user_type_label": "Individual",
        "status": "pending",
        "status_label": "Pending",
        "roles": [],
        "created_at": "2026-08-20 12:09:46",
        "locale": "ar",
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "suspension_reason": null,
        "profile": {
            "full_name": "Test Individual Full Name",
            "completed_orders_total": 0,
            "cancelled_orders_total": 0
        },
        "recent_orders": [],
        "recent_ratings": [],
        "assignment_log": [],
        "addresses": [],
        "wallet": null,
        "updated_at": "2026-08-20 12:09:46"
    }
}
```

*{ 201 Created — technician }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 116,
        "name": "Test Technician",
        "email": "technician.store@example.com",
        "phone": "1055500002",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "technician",
        "user_type_label": "Technician",
        "status": "pending",
        "status_label": "Pending",
        "roles": [],
        "created_at": "2026-08-20 12:09:46",
        "locale": "ar",
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "suspension_reason": null,
        "profile": {
            "full_name": "Test Technician Full Name",
            "specialty": null,
            "daily_order_capacity": 5,
            "employment_type": "freelance",
            "address": null,
            "availability_status": "unavailable",
            "avg_rating": "0.0",
            "completed_orders_count": 0,
            "governorate": null
        },
        "recent_orders": [],
        "recent_ratings": [],
        "assignment_log": [],
        "addresses": [],
        "wallet": null,
        "updated_at": "2026-08-20 12:09:46"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "The selected account type is invalid.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "The selected account type is invalid.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "The selected account type is invalid.",
    "data": null
}
```

**What happens next:** Use the returned id with `show`/`update`/`destroy` for this user.

---

#### Update User

**What this does:** Updates an existing user.

| | |
|---|---|
| **Method** | `PUT` |
| **Endpoint** | `{{base_url}}/api/v1/admin/users/:user` |
| **Route name** | `admin.users.update` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `users.update` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `user` — User ID — seeded example: `3`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `user_type`
- **Description:** Account Type
- **Type:** `string`
- **Required:** optional
- **Example:** `super_admin`
- **Validation rules:** `sometimes|in:super_admin,admin,individual,company,technician`
- `sometimes` — validated only when the field is present.
- `in:super_admin,admin,individual,company,technician` — must be one of: super_admin, admin, individual, company, technician.
### `name`
- **Description:** Name
- **Type:** `string`
- **Required:** optional
- **Example:** `Example Name`
- **Validation rules:** `sometimes|string|max:160`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:160` — must not exceed 160.
### `email`
- **Description:** Email
- **Type:** `string`
- **Required:** optional
- **Example:** `user@example.com`
- **Validation rules:** `sometimes|email|unique:users,email,NULL,id`
- `sometimes` — validated only when the field is present.
- `email` — must be a valid email address.
- `unique:users,email,NULL,id` — must be unique (users, email, NULL, id).
### `phone`
- **Description:** Phone
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `nullable|string|max:20|unique:users,phone,NULL,id`
- `nullable` — may be null.
- `string` — must be text.
- `max:20` — must not exceed 20.
- `unique:users,phone,NULL,id` — must be unique (users, phone, NULL, id).
### `password`
- **Description:** Password
- **Type:** `string`
- **Required:** optional
- **Example:** `Password123!`
- **Validation rules:** `sometimes|nullable|string|min:8`
- `sometimes` — validated only when the field is present.
- `nullable` — may be null.
- `string` — must be text.
- `min:8` — must be at least 8.
### `status`
- **Description:** Status
- **Type:** `string`
- **Required:** optional
- **Example:** `pending`
- **Validation rules:** `sometimes|in:pending,active,suspended,rejected`
- `sometimes` — validated only when the field is present.
- `in:pending,active,suspended,rejected` — must be one of: pending, active, suspended, rejected.
### `locale`
- **Description:** Locale
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `nullable|string|max:5`
- `nullable` — may be null.
- `string` — must be text.
- `max:5` — must not exceed 5.
### `full_name`
- **Description:** Full Name
- **Type:** `string`
- **Required:** conditional
- **Example:** `Example Name`
- **Validation rules:** `required_if:user_type,individual,technician|string|max:150`
- `required_if:user_type,individual,technician` — required when user_type, individual, technician.
- `string` — must be text.
- `max:150` — must not exceed 150.
### `legal_name`
- **Description:** Legal Company Name
- **Type:** `string`
- **Required:** conditional
- **Example:** `Example Name`
- **Validation rules:** `required_if:user_type,company|string|max:200`
- `required_if:user_type,company` — required when user_type, company.
- `string` — must be text.
- `max:200` — must not exceed 200.
### `tax_number`
- **Description:** VAT Number
- **Type:** `string`
- **Required:** optional
- **Example:** `300012345600003`
- **Validation rules:** `nullable|string|max:50`
- `nullable` — may be null.
- `string` — must be text.
- `max:50` — must not exceed 50.
### `commercial_registration_no`
- **Description:** Commercial Registration Number
- **Type:** `string`
- **Required:** optional
- **Example:** `1010101010`
- **Validation rules:** `nullable|string|max:50`
- `nullable` — may be null.
- `string` — must be text.
- `max:50` — must not exceed 50.
### `account_owner_phone`
- **Description:** Account Owner Phone
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `nullable|string|max:20`
- `nullable` — may be null.
- `string` — must be text.
- `max:20` — must not exceed 20.
### `category_id`
- **Description:** Service Category
- **Type:** `integer`
- **Required:** conditional
- **Example:** `2`
- **Validation rules:** `required_if:user_type,technician|integer|exists:categories,id`
- `required_if:user_type,technician` — required when user_type, technician.
- `integer` — must be a whole number.
- `exists:categories,id` — must reference an existing record (categories, id).
### `daily_order_capacity`
- **Description:** Daily Order Capacity
- **Type:** `integer`
- **Required:** conditional
- **Example:** `1`
- **Validation rules:** `required_if:user_type,technician|integer|min:1`
- `required_if:user_type,technician` — required when user_type, technician.
- `integer` — must be a whole number.
- `min:1` — must be at least 1.
### `employment_type`
- **Description:** Employment Type
- **Type:** `string`
- **Required:** conditional
- **Example:** `in_house`
- **Validation rules:** `required_if:user_type,technician|string|in:in_house,freelance`
- `required_if:user_type,technician` — required when user_type, technician.
- `string` — must be text.
- `in:in_house,freelance` — must be one of: in_house, freelance.
- **Gates wallet withdrawal eligibility, not just a label.** Only `freelance` technicians can withdraw (`Wallet::isFreelanceTechnician()`) — `in_house` technician wallets are locked at zero.
### `address`
- **Description:** Address
- **Type:** `string`
- **Required:** optional
- **Example:** `123 Main Street, Building A`
- **Validation rules:** `nullable|string|max:255`
- `nullable` — may be null.
- `string` — must be text.
- `max:255` — must not exceed 255.
### `country_id`
- **Description:** Country
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:countries,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:countries,id` — must reference an existing record (countries, id).
### `governorate_id`
- **Description:** City
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:governorates,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:governorates,id` — must reference an existing record (governorates, id).
### `region_id`
- **Description:** District
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:regions,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:regions,id` — must reference an existing record (regions, id).
### `years_experience`
- **Description:** Years experience
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|min:0`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `min:0` — must be at least .
### `coverage_areas`
- **Description:** Coverage Areas (Regions)
- **Type:** `array`
- **Required:** optional
- **Example:** `[1]`
- **Validation rules:** `nullable|array`
- `nullable` — may be null.
- `array` — must be an array.
### `coverage_areas.*`
- **Description:** Coverage areas item
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `integer|exists:regions,id`
- `integer` — must be a whole number.
- `exists:regions,id` — must reference an existing record (regions, id).

**Example Request Body:**
```json
{
    "name": "Updated Individual Name"
}
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 5,
        "name": "Updated Individual Name",
        "email": "individual.store@example.com",
        "phone": "1055500001",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "individual",
        "user_type_label": "Individual",
        "status": "pending",
        "status_label": "Pending",
        "roles": [],
        "created_at": "2026-08-20 12:07:53",
        "locale": "ar",
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "suspension_reason": null,
        "profile": {
            "full_name": "Test Individual Full Name",
            "completed_orders_total": 0,
            "cancelled_orders_total": 0
        },
        "recent_orders": [],
        "recent_ratings": [],
        "assignment_log": [],
        "addresses": [],
        "wallet": null,
        "updated_at": "2026-08-20 12:07:53"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 115,
        "name": "Updated Individual Name",
        "email": "individual.store@example.com",
        "phone": "1055500001",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "individual",
        "user_type_label": "Individual",
        "status": "pending",
        "status_label": "Pending",
        "roles": [],
        "created_at": "2026-08-20 12:09:24",
        "locale": "ar",
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "suspension_reason": null,
        "profile": {
            "full_name": "Test Individual Full Name",
            "completed_orders_total": 0,
            "cancelled_orders_total": 0
        },
        "recent_orders": [],
        "recent_ratings": [],
        "assignment_log": [],
        "addresses": [],
        "wallet": null,
        "updated_at": "2026-08-20 12:09:25"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 115,
        "name": "Updated Individual Name",
        "email": "individual.store@example.com",
        "phone": "1055500001",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "individual",
        "user_type_label": "Individual",
        "status": "pending",
        "status_label": "Pending",
        "roles": [],
        "created_at": "2026-08-20 12:09:46",
        "locale": "ar",
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "suspension_reason": null,
        "profile": {
            "full_name": "Test Individual Full Name",
            "completed_orders_total": 0,
            "cancelled_orders_total": 0
        },
        "recent_orders": [],
        "recent_ratings": [],
        "assignment_log": [],
        "addresses": [],
        "wallet": null,
        "updated_at": "2026-08-20 12:09:46"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a valid email address.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a valid email address.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a valid email address.",
    "data": null
}
```

**What happens next:** Fetch `show` to confirm the change.

---

#### Activate User

**What this does:** Approves a `pending` user account (the generic endpoint used for individuals and, notably, technicians — there is no technician-specific activate route).

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/users/:id/activate` |
| **Route name** | `admin.users.activate` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `users.activate` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `18`

**Payload:**
No fields. Send an empty JSON object `{}`.

**Example Request Body:**
```json
[]
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "User activated successfully",
    "data": {
        "id": 4,
        "name": "Caleb O'Connell Sr.",
        "status": "active"
    }
}
```

*{ 200 OK — already active (idempotent) }*
```json
{
    "status": "success",
    "message": "User activated successfully",
    "data": {
        "id": 13,
        "name": "Brook Abbott",
        "status": "active"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "User activated successfully",
    "data": {
        "id": 114,
        "name": "Miles McClure",
        "status": "active"
    }
}
```

*{ 200 OK — already active (idempotent) }*
```json
{
    "status": "success",
    "message": "User activated successfully",
    "data": {
        "id": 123,
        "name": "Mariela McCullough",
        "status": "active"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "User activated successfully",
    "data": {
        "id": 114,
        "name": "America Lemke",
        "status": "active"
    }
}
```

*{ 200 OK — already active (idempotent) }*
```json
{
    "status": "success",
    "message": "User activated successfully",
    "data": {
        "id": 123,
        "name": "Prof. Tate Deckow Sr.",
        "status": "active"
    }
}
```

**What happens next:** **Effect on Technician (or Client):** their `/auth/login` (`02-technician.md` §01 or `01-guest-and-client.md` §01), which previously rejected with an account-status error, now succeeds.

---

#### Reject User

**What this does:** Rejects a `pending` user account, recording a reason.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/users/:id/reject` |
| **Route name** | `admin.users.reject` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `users.reject` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `6`

**Payload:**
Example payload is included in the request body. No FormRequest validation rules were detected.
### `reason`
- **Description:** Reason
- **Type:** `string`
- **Required:** optional
- **Example:** `Does not meet platform requirements.`
- **Validation rules:** `not specified`
- `not specified` — no validation rule was declared.

**Example Request Body:**
```json
{
    "reason": "Incomplete documentation"
}
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "User rejected successfully",
    "data": {
        "id": 7,
        "name": "Krista Smith",
        "status": "rejected"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "User rejected successfully",
    "data": {
        "id": 117,
        "name": "Wallace King",
        "status": "rejected"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "User rejected successfully",
    "data": {
        "id": 117,
        "name": "Dr. Kameron McCullough",
        "status": "rejected"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** The user cannot log in.

---

#### Toggle User Status

**What this does:** Flips a user's status between `active` and `suspended`.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/users/:id/toggle-active` |
| **Route name** | `admin.users.toggle` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `users.toggle` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `3`

**Payload:**
No fields. Send an empty JSON object `{}`.

**Example Request Body:**
```json
[]
```

**Actual Success Response(s):**

*{ 200 OK — active to suspended }*
```json
{
    "status": "success",
    "message": "User suspended successfully",
    "data": {
        "id": 8,
        "name": "Paxton Hill MD",
        "status": "suspended"
    }
}
```

*{ 200 OK — suspended to active }*
```json
{
    "status": "success",
    "message": "User activated successfully",
    "data": {
        "id": 8,
        "name": "Paxton Hill MD",
        "status": "active"
    }
}
```

*{ 200 OK — active to suspended }*
```json
{
    "status": "success",
    "message": "User suspended successfully",
    "data": {
        "id": 118,
        "name": "Prof. Antoinette Mueller",
        "status": "suspended"
    }
}
```

*{ 200 OK — suspended to active }*
```json
{
    "status": "success",
    "message": "User activated successfully",
    "data": {
        "id": 118,
        "name": "Prof. Antoinette Mueller",
        "status": "active"
    }
}
```

*{ 200 OK — active to suspended }*
```json
{
    "status": "success",
    "message": "User suspended successfully",
    "data": {
        "id": 118,
        "name": "Leanna Roob",
        "status": "suspended"
    }
}
```

*{ 200 OK — suspended to active }*
```json
{
    "status": "success",
    "message": "User activated successfully",
    "data": {
        "id": 118,
        "name": "Leanna Roob",
        "status": "active"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** A suspended user is immediately locked out of login.

---

#### Delete User

**What this does:** Permanently deletes a user.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/users/:user` |
| **Route name** | `admin.users.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `users.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `user` — User ID — seeded example: `3`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — already deleted }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — already deleted }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — already deleted }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** It no longer appears in `index`.

---

#### Delete Bulk

**What this does:** Deletes multiple users in one call by an array of ids.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/users/bulk` |
| **Route name** | `admin.users.bulk.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `users.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — unknown id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - empty ids }*
```json
{
    "status": "fail",
    "message": "Please select at least one item.",
    "data": null
}
```

*{ 404 Not Found — unknown id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - empty ids }*
```json
{
    "status": "fail",
    "message": "Please select at least one item.",
    "data": null
}
```

*{ 404 Not Found — unknown id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - empty ids }*
```json
{
    "status": "fail",
    "message": "Please select at least one item.",
    "data": null
}
```

**What happens next:** Re-fetch the index to confirm — deleted users no longer appear.

---

## 04. Technicians (Management)

#### List All Technicians

**What this does:** Returns a paginated, filterable, searchable list of technicians.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/technicians?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.technicians.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `technicians.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — 200 - OK }*
```json
{
    "status": "success",
    "message": "Technicians retrieved",
    "data": {
        "data": [
            {
                "id": 1,
                "user_id": 3,
                "name": "Ahmed Technician",
                "email": "ahmed.tech@example.test",
                "phone": "01099998888",
                "status": "active",
                "user_type": "technician",
                "full_name": "Ahmed Mohamed",
                "category_id": 1,
                "category_name": "Plumbing",
                "governorate": {
                    "id": 1,
                    "name": "Cairo"
                },
                "specialty": "Plumbing",
                "employment_type": "in_house",
                "availability_status": "available",
                "avg_rating": 0,
                "completed_orders_count": 0,
                "daily_order_capacity": 6,
                "created_at": "2026-08-20 12:09:42"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/technicians?page=1",
            "last": "http://localhost/api/v1/admin/technicians?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/technicians?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/technicians",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### Show Technician Details

**What this does:** Returns full details for one technician.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/technicians/:technician` |
| **Route name** | `admin.technicians.show` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `technicians.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `technician` — Technician ID — seeded example: `2`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — 200 - OK }*
```json
{
    "status": "success",
    "message": "Technician retrieved",
    "data": {
        "id": 1,
        "user_id": 3,
        "name": "Ahmed Technician",
        "email": "ahmed.tech@example.test",
        "phone": "01099998888",
        "status": "active",
        "user_type": "technician",
        "full_name": "Ahmed Mohamed",
        "category_id": 1,
        "category_name": "Plumbing",
        "governorate": {
            "id": 1,
            "name": "Cairo"
        },
        "specialty": "Plumbing",
        "employment_type": "in_house",
        "availability_status": "available",
        "avg_rating": 0,
        "completed_orders_count": 0,
        "daily_order_capacity": 6,
        "created_at": "2026-08-20 12:09:42",
        "id_number": "29901011234567",
        "address": "5 Nile Street",
        "country": {
            "id": 1,
            "name": null
        },
        "region": {
            "id": 1,
            "name": "Maadi"
        },
        "years_experience": 4,
        "coverage_areas": [
            {
                "id": 1,
                "name": "Maadi"
            }
        ],
        "personal_photo": null,
        "national_id_front": null,
        "national_id_back": null,
        "cv_file": null,
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null,
        "recent_orders": [],
        "recent_ratings": [],
        "wallet": null
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — 404 - Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use `update` to modify it, or `destroy` to remove it.

---

#### Create New Technician

**What this does:** Creates a new technician.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/technicians` |
| **Route name** | `admin.technicians.store` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `technicians.create` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `201 Created`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `name`
- **Description:** Name
- **Type:** `string`
- **Required:** required
- **Example:** `Example Name`
- **Validation rules:** `required|string|max:160`
- `required` — must be provided.
- `string` — must be text.
- `max:160` — must not exceed 160.
### `email`
- **Description:** Email
- **Type:** `string`
- **Required:** required
- **Example:** `user@example.com`
- **Validation rules:** `required|email|unique:users,email`
- `required` — must be provided.
- `email` — must be a valid email address.
- `unique:users,email` — must be unique (users, email).
### `phone`
- **Description:** Phone
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `nullable|string|max:20|unique:users,phone`
- `nullable` — may be null.
- `string` — must be text.
- `max:20` — must not exceed 20.
- `unique:users,phone` — must be unique (users, phone).
### `password`
- **Description:** Password
- **Type:** `string`
- **Required:** required
- **Example:** `Password123!`
- **Validation rules:** `required|string|min:8`
- `required` — must be provided.
- `string` — must be text.
- `min:8` — must be at least 8.
### `status`
- **Description:** Status
- **Type:** `string`
- **Required:** optional
- **Example:** `pending`
- **Validation rules:** `sometimes|in:pending,active,suspended,rejected`
- `sometimes` — validated only when the field is present.
- `in:pending,active,suspended,rejected` — must be one of: pending, active, suspended, rejected.
### `locale`
- **Description:** Locale
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `nullable|string|max:5`
- `nullable` — may be null.
- `string` — must be text.
- `max:5` — must not exceed 5.
### `full_name`
- **Description:** Full Name
- **Type:** `string`
- **Required:** required
- **Example:** `Example Name`
- **Validation rules:** `required|string|max:150`
- `required` — must be provided.
- `string` — must be text.
- `max:150` — must not exceed 150.
### `category_id`
- **Description:** Service Category
- **Type:** `integer`
- **Required:** required
- **Example:** `2`
- **Validation rules:** `required|integer|exists:categories,id`
- `required` — must be provided.
- `integer` — must be a whole number.
- `exists:categories,id` — must reference an existing record (categories, id).
### `daily_order_capacity`
- **Description:** Daily Order Capacity
- **Type:** `integer`
- **Required:** required
- **Example:** `1`
- **Validation rules:** `required|integer|min:1|max:50`
- `required` — must be provided.
- `integer` — must be a whole number.
- `min:1` — must be at least 1.
- `max:50` — must not exceed 50.
### `employment_type`
- **Description:** Employment Type
- **Type:** `string`
- **Required:** required
- **Example:** `in_house`
- **Validation rules:** `required|string|in:in_house,freelance`
- `required` — must be provided.
- `string` — must be text.
- `in:in_house,freelance` — must be one of: in_house, freelance.
- **Gates wallet withdrawal eligibility, not just a label.** Only `freelance` technicians can withdraw (`Wallet::isFreelanceTechnician()`) — `in_house` technician wallets are locked at zero.
### `address`
- **Description:** Address
- **Type:** `string`
- **Required:** optional
- **Example:** `123 Main Street, Building A`
- **Validation rules:** `nullable|string|max:255`
- `nullable` — may be null.
- `string` — must be text.
- `max:255` — must not exceed 255.
### `country_id`
- **Description:** Country
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:countries,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:countries,id` — must reference an existing record (countries, id).
### `governorate_id`
- **Description:** City
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:governorates,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:governorates,id` — must reference an existing record (governorates, id).
### `region_id`
- **Description:** District
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:regions,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:regions,id` — must reference an existing record (regions, id).
### `id_number`
- **Description:** ID Number
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `nullable|string|max:50`
- `nullable` — may be null.
- `string` — must be text.
- `max:50` — must not exceed 50.
### `years_experience`
- **Description:** Years of Experience
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|min:0|max:50`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `min:0` — must be at least .
- `max:50` — must not exceed 50.
### `coverage_areas`
- **Description:** Coverage Areas (Regions)
- **Type:** `array`
- **Required:** optional
- **Example:** `[1]`
- **Validation rules:** `nullable|array`
- `nullable` — may be null.
- `array` — must be an array.
### `coverage_areas.*`
- **Description:** Coverage areas item
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `integer|exists:regions,id`
- `integer` — must be a whole number.
- `exists:regions,id` — must reference an existing record (regions, id).
### `personal_photo`
- **Description:** Personal photo
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:media,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:media,id` — must reference an existing record (media, id).
### `national_id_front`
- **Description:** National id front
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:media,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:media,id` — must reference an existing record (media, id).
### `national_id_back`
- **Description:** National id back
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:media,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:media,id` — must reference an existing record (media, id).
### `cv_file`
- **Description:** Cv file
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:media,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:media,id` — must reference an existing record (media, id).

**Example Request Body:**
```json
{
    "name": "Ahmed Technician",
    "email": "ahmed.tech@example.test",
    "phone": "01099998888",
    "password": "password123",
    "status": "active",
    "full_name": "Ahmed Mohamed",
    "category_id": 2,
    "daily_order_capacity": 6,
    "employment_type": "in_house",
    "address": "5 Nile Street",
    "country_id": 1,
    "governorate_id": 1,
    "region_id": 1,
    "id_number": "29901011234567",
    "years_experience": 4,
    "coverage_areas": [
        1
    ]
}
```

**Actual Success Response(s):**

*{ 201 Created — 201 - OK }*
```json
{
    "status": "success",
    "message": "Technician created",
    "data": {
        "id": 1,
        "user_id": 3,
        "name": "Ahmed Technician",
        "email": "ahmed.tech@example.test",
        "phone": "01099998888",
        "status": "active",
        "user_type": "technician",
        "full_name": "Ahmed Mohamed",
        "category_id": 1,
        "category_name": "Plumbing",
        "governorate": {
            "id": 1,
            "name": "Cairo"
        },
        "specialty": "Plumbing",
        "employment_type": "in_house",
        "availability_status": "available",
        "avg_rating": 0,
        "completed_orders_count": 0,
        "daily_order_capacity": 6,
        "created_at": "2026-08-20 12:09:42",
        "id_number": "29901011234567",
        "address": "5 Nile Street",
        "country": {
            "id": 1,
            "name": null
        },
        "region": {
            "id": 1,
            "name": "Maadi"
        },
        "years_experience": 4,
        "coverage_areas": [
            {
                "id": 1,
                "name": "Maadi"
            }
        ],
        "personal_photo": null,
        "national_id_front": null,
        "national_id_back": null,
        "cv_file": null,
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 - Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a name.",
    "data": null
}
```

**What happens next:** Use the returned id with `show`/`update`/`destroy` for this technician.

---

#### Update Technician

**What this does:** Updates an existing technician.

| | |
|---|---|
| **Method** | `PUT` |
| **Endpoint** | `{{base_url}}/api/v1/admin/technicians/:technician` |
| **Route name** | `admin.technicians.update` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `technicians.update` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `technician` — Technician ID — seeded example: `2`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `name`
- **Description:** Name
- **Type:** `string`
- **Required:** optional
- **Example:** `Example Name`
- **Validation rules:** `sometimes|string|max:160`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:160` — must not exceed 160.
### `email`
- **Description:** Email
- **Type:** `string`
- **Required:** optional
- **Example:** `user@example.com`
- **Validation rules:** `sometimes|email|unique:users,email,NULL,id`
- `sometimes` — validated only when the field is present.
- `email` — must be a valid email address.
- `unique:users,email,NULL,id` — must be unique (users, email, NULL, id).
### `phone`
- **Description:** Phone
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `nullable|string|max:20|unique:users,phone,NULL,id`
- `nullable` — may be null.
- `string` — must be text.
- `max:20` — must not exceed 20.
- `unique:users,phone,NULL,id` — must be unique (users, phone, NULL, id).
### `password`
- **Description:** Password
- **Type:** `string`
- **Required:** optional
- **Example:** `Password123!`
- **Validation rules:** `sometimes|nullable|string|min:8`
- `sometimes` — validated only when the field is present.
- `nullable` — may be null.
- `string` — must be text.
- `min:8` — must be at least 8.
### `status`
- **Description:** Status
- **Type:** `string`
- **Required:** optional
- **Example:** `pending`
- **Validation rules:** `sometimes|in:pending,active,suspended,rejected`
- `sometimes` — validated only when the field is present.
- `in:pending,active,suspended,rejected` — must be one of: pending, active, suspended, rejected.
### `locale`
- **Description:** Locale
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `nullable|string|max:5`
- `nullable` — may be null.
- `string` — must be text.
- `max:5` — must not exceed 5.
### `full_name`
- **Description:** Full Name
- **Type:** `string`
- **Required:** optional
- **Example:** `Example Name`
- **Validation rules:** `sometimes|string|max:150`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:150` — must not exceed 150.
### `category_id`
- **Description:** Service Category
- **Type:** `integer`
- **Required:** optional
- **Example:** `2`
- **Validation rules:** `sometimes|integer|exists:categories,id`
- `sometimes` — validated only when the field is present.
- `integer` — must be a whole number.
- `exists:categories,id` — must reference an existing record (categories, id).
### `daily_order_capacity`
- **Description:** Daily Order Capacity
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `sometimes|integer|min:1|max:50`
- `sometimes` — validated only when the field is present.
- `integer` — must be a whole number.
- `min:1` — must be at least 1.
- `max:50` — must not exceed 50.
### `employment_type`
- **Description:** Employment Type
- **Type:** `string`
- **Required:** optional
- **Example:** `in_house`
- **Validation rules:** `sometimes|string|in:in_house,freelance`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `in:in_house,freelance` — must be one of: in_house, freelance.
- **Gates wallet withdrawal eligibility, not just a label.** Only `freelance` technicians can withdraw (`Wallet::isFreelanceTechnician()`) — `in_house` technician wallets are locked at zero. Changing an existing technician to `freelance` here unlocks their current balance for withdrawal going forward.
### `address`
- **Description:** Address
- **Type:** `string`
- **Required:** optional
- **Example:** `123 Main Street, Building A`
- **Validation rules:** `nullable|string|max:255`
- `nullable` — may be null.
- `string` — must be text.
- `max:255` — must not exceed 255.
### `country_id`
- **Description:** Country
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:countries,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:countries,id` — must reference an existing record (countries, id).
### `governorate_id`
- **Description:** City
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:governorates,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:governorates,id` — must reference an existing record (governorates, id).
### `region_id`
- **Description:** District
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:regions,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:regions,id` — must reference an existing record (regions, id).
### `id_number`
- **Description:** ID Number
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `nullable|string|max:50`
- `nullable` — may be null.
- `string` — must be text.
- `max:50` — must not exceed 50.
### `years_experience`
- **Description:** Years of Experience
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|min:0|max:50`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `min:0` — must be at least .
- `max:50` — must not exceed 50.
### `coverage_areas`
- **Description:** Coverage Areas (Regions)
- **Type:** `array`
- **Required:** optional
- **Example:** `[1]`
- **Validation rules:** `nullable|array`
- `nullable` — may be null.
- `array` — must be an array.
### `coverage_areas.*`
- **Description:** Coverage areas item
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `integer|exists:regions,id`
- `integer` — must be a whole number.
- `exists:regions,id` — must reference an existing record (regions, id).
### `personal_photo`
- **Description:** Personal photo
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:media,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:media,id` — must reference an existing record (media, id).
### `national_id_front`
- **Description:** National id front
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:media,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:media,id` — must reference an existing record (media, id).
### `national_id_back`
- **Description:** National id back
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:media,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:media,id` — must reference an existing record (media, id).
### `cv_file`
- **Description:** Cv file
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|integer|exists:media,id`
- `nullable` — may be null.
- `integer` — must be a whole number.
- `exists:media,id` — must reference an existing record (media, id).

**Example Request Body:**
```json
{
    "full_name": "Ahmed Mohamed Updated",
    "years_experience": 5
}
```

**Actual Success Response(s):**

*{ 200 OK — 200 - OK }*
```json
{
    "status": "success",
    "message": "Technician updated",
    "data": {
        "id": 1,
        "user_id": 3,
        "name": "Ahmed Technician",
        "email": "ahmed.tech@example.test",
        "phone": "01099998888",
        "status": "active",
        "user_type": "technician",
        "full_name": "Ahmed Mohamed Updated",
        "category_id": 1,
        "category_name": "Plumbing",
        "governorate": {
            "id": 1,
            "name": "Cairo"
        },
        "specialty": "Plumbing",
        "employment_type": "in_house",
        "availability_status": "available",
        "avg_rating": 0,
        "completed_orders_count": 0,
        "daily_order_capacity": 6,
        "created_at": "2026-08-20 12:09:42",
        "id_number": "29901011234567",
        "address": "5 Nile Street",
        "country": {
            "id": 1,
            "name": null
        },
        "region": {
            "id": 1,
            "name": "Maadi"
        },
        "years_experience": 5,
        "coverage_areas": [
            {
                "id": 1,
                "name": "Maadi"
            }
        ],
        "personal_photo": null,
        "national_id_front": null,
        "national_id_back": null,
        "cv_file": null,
        "email_verified_at": null,
        "phone_verified_at": null,
        "last_login_at": null
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — 404 - Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 - Validation Error }*
```json
{
    "status": "fail",
    "message": "This email address is already registered.",
    "data": null
}
```

**What happens next:** Fetch `show` to confirm the change.

---

#### Toggle Availability Technician

**What this does:** Admin override of a technician's `availability_status`, independent of the technician's own toggle.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/technicians/:id/toggle-availability` |
| **Route name** | `admin.technicians.toggle-availability` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `technicians.toggle-availability` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`

**Payload:**
No fields. Send an empty JSON object `{}`.

**Example Request Body:**
```json
[]
```

**Actual Success Response(s):**

*{ 200 OK — 200 - OK }*
```json
{
    "status": "success",
    "message": "Availability status updated",
    "data": {
        "availability_status": "unavailable"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — 404 - Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** **Effect on Technician:** their own `technician.profile.toggle-availability` (`02-technician.md` §03) reflects this same flag — whichever side last toggled it wins. Also affects whether this technician is offered new assignments (manual admin assignment or the auto-reassignment matcher).

---

#### Toggle Status Technician

**What this does:** Flips a technician's underlying user account status (active/suspended) from the technician-management screen.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/technicians/:id/toggle-status` |
| **Route name** | `admin.technicians.toggle-status` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `technicians.toggle-status` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`

**Payload:**
No fields. Send an empty JSON object `{}`.

**Example Request Body:**
```json
[]
```

**Actual Success Response(s):**

*{ 200 OK — 200 - OK }*
```json
{
    "status": "success",
    "message": "Technician suspended",
    "data": {
        "id": 3,
        "status": "suspended"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — 404 - Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Same effect as `admin.users.toggle` scoped to technicians — locks/unlocks login immediately.

---

#### Delete Technician

**What this does:** Permanently deletes a technician.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/technicians/:technician` |
| **Route name** | `admin.technicians.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `technicians.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `technician` — Technician ID — seeded example: `2`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — 200 - OK }*
```json
{
    "status": "success",
    "message": "Technician deleted",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — 404 - Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** It no longer appears in `index`.

---

#### Delete Bulk

**What this does:** Deletes multiple technicians in one call by an array of ids.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/technicians/bulk` |
| **Route name** | `admin.technicians.bulk.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `technicians.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — 200 - OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — 404 - Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 - Validation Error }*
```json
{
    "status": "fail",
    "message": "Please select at least one item.",
    "data": null
}
```

**What happens next:** Re-fetch the index to confirm — deleted technicians no longer appear.

---

## 05. Companies (Management)

#### List All Companies

**What this does:** Returns a paginated, filterable, searchable list of companies.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/companies?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.companies.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `companies.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Companies retrieved",
    "data": {
        "data": [
            {
                "id": 15,
                "legal_name": "Brandy Feil",
                "email": "matilde86@example.net",
                "account_owner_phone": "1650055823",
                "account_owner_phone_code": null,
                "tax_number": null,
                "commercial_registration_no": null,
                "status": "active",
                "commercial_register": {
                    "file_url": null,
                    "expiry_date": null,
                    "status": null,
                    "status_label": null
                },
                "created_at": "2026-08-20 12:07:53"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/companies?page=1",
            "last": "http://localhost/api/v1/admin/companies?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/companies?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/companies",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Companies retrieved",
    "data": {
        "data": [
            {
                "id": 125,
                "legal_name": "Bertram Collier",
                "email": "thirthe@example.com",
                "account_owner_phone": "1190501338",
                "account_owner_phone_code": null,
                "tax_number": null,
                "commercial_registration_no": null,
                "status": "active",
                "commercial_register": {
                    "file_url": null,
                    "expiry_date": null,
                    "status": null,
                    "status_label": null
                },
                "created_at": "2026-08-20 12:09:25"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/companies?page=1",
            "last": "http://localhost/api/v1/admin/companies?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/companies?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/companies",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Companies retrieved",
    "data": {
        "data": [
            {
                "id": 125,
                "legal_name": "Wilton Kautzer",
                "email": "lindgren.jarrett@example.net",
                "account_owner_phone": "1229677812",
                "tax_number": null,
                "commercial_registration_no": null,
                "status": "active",
                "created_at": "2026-08-20 12:09:46"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/companies?page=1",
            "last": "http://localhost/api/v1/admin/companies?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/companies?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/companies",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### Show Company Details

**What this does:** Returns full details for one company.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/companies/:company` |
| **Route name** | `admin.companies.show` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `companies.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `company` — Company ID — seeded example: `10`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 16,
        "legal_name": "Acme Maintenance LLC",
        "email": "acme.store@example.com",
        "account_owner_phone": "1066600001",
        "account_owner_phone_code": "20",
        "tax_number": "VAT-123456",
        "commercial_registration_no": "CR-987654",
        "status": "pending",
        "commercial_register": {
            "file_url": null,
            "expiry_date": "2027-08-24",
            "status": "pending_review",
            "status_label": "Under review"
        },
        "created_at": "2026-08-20 12:07:53"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use `update` to modify it, or `destroy` to remove it.

---

#### Create New Company

**What this does:** Creates a new company.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/companies` |
| **Route name** | `admin.companies.store` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `companies.create` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `201 Created`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `legal_name`
- **Description:** Legal Company Name
- **Type:** `string`
- **Required:** required
- **Example:** `Example Name`
- **Validation rules:** `required|string|max:200`
- `required` — must be provided.
- `string` — must be text.
- `max:200` — must not exceed 200.
### `email`
- **Description:** Official Email
- **Type:** `string`
- **Required:** required
- **Example:** `user@example.com`
- **Validation rules:** `required|email|unique:users,email,NULL,id`
- `required` — must be provided.
- `email` — must be a valid email address.
- `unique:users,email,NULL,id` — must be unique (users, email, NULL, id).
### `account_owner_phone`
- **Description:** Account Owner Phone
- **Type:** `string`
- **Required:** required
- **Example:** `1234567890`
- **Validation rules:** `required|string|max:20|unique:users,phone,NULL,id`
- `required` — must be provided.
- `string` — must be text.
- `max:20` — must not exceed 20.
- `unique:users,phone,NULL,id` — must be unique (users, phone, NULL, id).
### `account_owner_phone_code`
- **Description:** Account Owner Phone Code
- **Type:** `string`
- **Required:** optional
- **Example:** `20`
- **Validation rules:** `nullable|string|max:5`
- `nullable` — may be null.
- `string` — must be text.
- `max:5` — must not exceed 5.
### `password`
- **Description:** Password
- **Type:** `string`
- **Required:** required
- **Example:** `Password123!`
- **Validation rules:** `required|nullable|string|min:8`
- `required` — must be provided.
- `nullable` — may be null.
- `string` — must be text.
- `min:8` — must be at least 8.
### `status`
- **Description:** Status
- **Type:** `string`
- **Required:** optional
- **Example:** `pending`
- **Validation rules:** `sometimes|in:"pending","active","suspended","rejected"`
- `sometimes` — validated only when the field is present.
- `in:"pending","active","suspended","rejected"` — must be one of: "pending", "active", "suspended", "rejected".
### `tax_number`
- **Description:** VAT Number
- **Type:** `string`
- **Required:** optional
- **Example:** `300012345600003`
- **Validation rules:** `nullable|string|max:50`
- `nullable` — may be null.
- `string` — must be text.
- `max:50` — must not exceed 50.
### `commercial_registration_no`
- **Description:** Commercial Registration Number
- **Type:** `string`
- **Required:** optional
- **Example:** `1010101010`
- **Validation rules:** `nullable|string|max:50`
- `nullable` — may be null.
- `string` — must be text.
- `max:50` — must not exceed 50.
### `commercial_register_expiry_date`
- **Description:** Commercial Register Expiry Date
- **Type:** `string` (date)
- **Required:** optional
- **Example:** `2027-08-24`
- **Validation rules:** `nullable|date`
- `nullable` — may be null.
- `date` — must be a valid date.
- Submitting `commercial_registration_no` **and** this field together (re)starts commercial-register review — resets `commercial_register.status` to `pending_review` even if a prior submission was already approved/rejected, since the underlying document may have changed. The register document itself is uploaded separately (media upload), not through this field.

**Example Request Body:**
```json
{
    "legal_name": "Acme Maintenance LLC",
    "email": "acme.store@example.com",
    "account_owner_phone": "1066600001",
    "account_owner_phone_code": "20",
    "password": "password123",
    "tax_number": "VAT-123456",
    "commercial_registration_no": "CR-987654",
    "commercial_register_expiry_date": "2027-08-24"
}
```

**Actual Success Response(s):**

*{ 201 Created — Created }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 16,
        "legal_name": "Acme Maintenance LLC",
        "email": "acme.store@example.com",
        "account_owner_phone": "1066600001",
        "account_owner_phone_code": "20",
        "tax_number": "VAT-123456",
        "commercial_registration_no": "CR-987654",
        "status": "pending",
        "commercial_register": {
            "file_url": null,
            "expiry_date": "2027-08-24",
            "status": "pending_review",
            "status_label": "Under review"
        },
        "created_at": "2026-08-20 12:07:53"
    }
}
```
`commercial_register.status` is one of `pending_review`, `rejected`, `valid`, `expired`, or `null` (nothing submitted yet) — see `CompanyProfile::commercialRegisterStatus()`. It is **not** the same as the top-level `status` (the user account's `pending`/`active`/`suspended`/`rejected` state) — a company can be `active` with an `expired` commercial register, or `pending` with a `valid` one.

*{ 201 Created — Created }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 126,
        "legal_name": "Acme Maintenance LLC",
        "email": "acme.store@example.com",
        "account_owner_phone": "1066600001",
        "account_owner_phone_code": null,
        "tax_number": "VAT-123456",
        "commercial_registration_no": "CR-987654",
        "status": "pending",
        "commercial_register": {
            "file_url": null,
            "expiry_date": null,
            "status": null,
            "status_label": null
        },
        "created_at": "2026-08-20 12:09:25"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "The Legal Company Name field is required.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "The Legal Company Name field is required.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "The Legal Company Name field is required.",
    "data": null
}
```

**What happens next:** Use the returned id with `show`/`update`/`destroy` for this company.

---

#### Update Company

**What this does:** Updates an existing company.

| | |
|---|---|
| **Method** | `PUT` |
| **Endpoint** | `{{base_url}}/api/v1/admin/companies/:company` |
| **Route name** | `admin.companies.update` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `companies.update` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `company` — Company ID — seeded example: `10`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `legal_name`
- **Description:** Legal Company Name
- **Type:** `string`
- **Required:** optional
- **Example:** `Example Name`
- **Validation rules:** `sometimes|string|max:200`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:200` — must not exceed 200.
### `email`
- **Description:** Official Email
- **Type:** `string`
- **Required:** optional
- **Example:** `user@example.com`
- **Validation rules:** `sometimes|email|unique:users,email,NULL,id`
- `sometimes` — validated only when the field is present.
- `email` — must be a valid email address.
- `unique:users,email,NULL,id` — must be unique (users, email, NULL, id).
### `account_owner_phone`
- **Description:** Account Owner Phone
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `sometimes|string|max:20|unique:users,phone,NULL,id`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:20` — must not exceed 20.
- `unique:users,phone,NULL,id` — must be unique (users, phone, NULL, id).
### `account_owner_phone_code`
- **Description:** Account Owner Phone Code
- **Type:** `string`
- **Required:** optional
- **Example:** `20`
- **Validation rules:** `nullable|string|max:5`
- `nullable` — may be null.
- `string` — must be text.
- `max:5` — must not exceed 5.
### `password`
- **Description:** Password
- **Type:** `string`
- **Required:** optional
- **Example:** `Password123!`
- **Validation rules:** `sometimes|nullable|string|min:8`
- `sometimes` — validated only when the field is present.
- `nullable` — may be null.
- `string` — must be text.
- `min:8` — must be at least 8.
### `status`
- **Description:** Status
- **Type:** `string`
- **Required:** optional
- **Example:** `pending`
- **Validation rules:** `sometimes|in:"pending","active","suspended","rejected"`
- `sometimes` — validated only when the field is present.
- `in:"pending","active","suspended","rejected"` — must be one of: "pending", "active", "suspended", "rejected".
### `tax_number`
- **Description:** VAT Number
- **Type:** `string`
- **Required:** optional
- **Example:** `300012345600003`
- **Validation rules:** `nullable|string|max:50`
- `nullable` — may be null.
- `string` — must be text.
- `max:50` — must not exceed 50.
### `commercial_registration_no`
- **Description:** Commercial Registration Number
- **Type:** `string`
- **Required:** optional
- **Example:** `1010101010`
- **Validation rules:** `nullable|string|max:50`
- `nullable` — may be null.
- `string` — must be text.
- `max:50` — must not exceed 50.
### `commercial_register_expiry_date`
- **Description:** Commercial Register Expiry Date
- **Type:** `string` (date)
- **Required:** optional
- **Example:** `2027-08-24`
- **Validation rules:** `nullable|date`
- `nullable` — may be null.
- `date` — must be a valid date.
- Submitting `commercial_registration_no` **and** this field together (re)starts commercial-register review — see the same note under Create New Company above.

**Example Request Body:**
```json
{
    "legal_name": "Acme Maintenance LLC (Updated)"
}
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 16,
        "legal_name": "Acme Maintenance LLC (Updated)",
        "email": "acme.store@example.com",
        "account_owner_phone": "1066600001",
        "account_owner_phone_code": "20",
        "tax_number": "VAT-123456",
        "commercial_registration_no": "CR-987654",
        "status": "pending",
        "commercial_register": {
            "file_url": null,
            "expiry_date": "2027-08-24",
            "status": "pending_review",
            "status_label": "Under review"
        },
        "created_at": "2026-08-20 12:07:53"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a valid email address.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a valid email address.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a valid email address.",
    "data": null
}
```

**What happens next:** Fetch `show` to confirm the change.

---

#### Activate Company

**What this does:** Approves a `pending` company account — sets `status: active`, clearing any suspension reason.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/companies/:id/activate` |
| **Route name** | `admin.companies.activate` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `companies.activate` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `6`

**Payload:**
No fields. Send an empty JSON object `{}`.

**Example Request Body:**
```json
[]
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Company activated successfully",
    "data": {
        "id": 17,
        "name": "Victoria Schamberger PhD",
        "status": "active"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Company activated successfully",
    "data": {
        "id": 127,
        "name": "Mr. Merl Goodwin",
        "status": "active"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Company activated successfully",
    "data": {
        "id": 127,
        "name": "Catherine White",
        "status": "active"
    }
}
```

**What happens next:** **Effect on Company:** `company.auth.login` (`03-company.md` §01), which previously 422'd with `company_account_pending`, now succeeds and returns a usable token.

---

#### Approve Commercial register

**What this does:** Approves a company's uploaded commercial-registration document (only valid while `commercial_register_status: pending_review`).

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/companies/:id/commercial-register/approve` |
| **Route name** | `admin.companies.commercial-register.approve` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `companies.approve` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `6`

**Payload:**
No fields. Send an empty JSON object `{}`.

**Example Request Body:**
```json
[]
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Commercial register approved successfully.",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Commercial register approved successfully.",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Commercial register approved successfully.",
    "data": null
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Not Pending }*
```json
{
    "status": "fail",
    "message": "This commercial register is not pending review.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Not Pending }*
```json
{
    "status": "fail",
    "message": "This commercial register is not pending review.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Not Pending }*
```json
{
    "status": "fail",
    "message": "This commercial register is not pending review.",
    "data": null
}
```

**What happens next:** This is independent of the account-activation step above — both may be needed before the company is fully onboarded, depending on business policy.

---

#### Reject Commercial register

**What this does:** Rejects a company's uploaded commercial-registration document.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/companies/:id/commercial-register/reject` |
| **Route name** | `admin.companies.commercial-register.reject` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `companies.reject` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `6`

**Payload:**
Example payload is included in the request body. No FormRequest validation rules were detected.
### `reason`
- **Description:** Reason
- **Type:** `string`
- **Required:** optional
- **Example:** `Does not meet platform requirements.`
- **Validation rules:** `not specified`
- `not specified` — no validation rule was declared.

**Example Request Body:**
```json
{
    "reason": "Does not meet platform requirements."
}
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Commercial register rejected successfully.",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Commercial register rejected successfully.",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Commercial register rejected successfully.",
    "data": null
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 No Profile / Not Pending }*
```json
{
    "status": "fail",
    "message": "This commercial register is not pending review.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 No Profile / Not Pending }*
```json
{
    "status": "fail",
    "message": "This commercial register is not pending review.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 No Profile / Not Pending }*
```json
{
    "status": "fail",
    "message": "This commercial register is not pending review.",
    "data": null
}
```

**What happens next:** The company should re-upload a corrected document and the review can be attempted again.

---

#### Reject Company

**What this does:** Rejects a `pending` company account, recording a reason.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/companies/:id/reject` |
| **Route name** | `admin.companies.reject` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `companies.reject` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `6`

**Payload:**
Example payload is included in the request body. No FormRequest validation rules were detected.
### `reason`
- **Description:** Reason
- **Type:** `string`
- **Required:** optional
- **Example:** `Does not meet platform requirements.`
- **Validation rules:** `not specified`
- `not specified` — no validation rule was declared.

**Example Request Body:**
```json
{
    "reason": "Invalid tax number"
}
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Company rejected successfully",
    "data": {
        "id": 18,
        "name": "Prof. Wyatt Stanton DDS",
        "status": "rejected"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Company rejected successfully",
    "data": {
        "id": 128,
        "name": "Jewell Funk",
        "status": "rejected"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Company rejected successfully",
    "data": {
        "id": 128,
        "name": "Prof. Clotilde Gutkowski DDS",
        "status": "rejected"
    }
}
```

**What happens next:** The company cannot log in; they would need a new registration (or manual admin intervention) to proceed.

---

#### Toggle Company Status

**What this does:** Flips a company's status between `active` and `suspended`.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/companies/:id/toggle-active` |
| **Route name** | `admin.companies.toggle` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `companies.toggle` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `10`

**Payload:**
No fields. Send an empty JSON object `{}`.

**Example Request Body:**
```json
[]
```

**Actual Success Response(s):**

*{ 200 OK — active to suspended }*
```json
{
    "status": "success",
    "message": "Company suspended successfully",
    "data": {
        "id": 19,
        "name": "Miss Alison Lueilwitz",
        "status": "suspended"
    }
}
```

*{ 200 OK — active to suspended }*
```json
{
    "status": "success",
    "message": "Company suspended successfully",
    "data": {
        "id": 129,
        "name": "Jarrell Bradtke Jr.",
        "status": "suspended"
    }
}
```

*{ 200 OK — active to suspended }*
```json
{
    "status": "success",
    "message": "Company suspended successfully",
    "data": {
        "id": 129,
        "name": "Mrs. Jadyn Watsica",
        "status": "suspended"
    }
}
```

**What happens next:** A suspended company is immediately locked out of `POST /company/auth/login`.

---

#### Delete Company

**What this does:** Permanently deletes a company.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/companies/:company` |
| **Route name** | `admin.companies.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `companies.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `company` — Company ID — seeded example: `10`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**What happens next:** It no longer appears in `index`.

---

#### Delete Bulk

**What this does:** Deletes multiple companies in one call by an array of ids.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/companies/bulk` |
| **Route name** | `admin.companies.bulk.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `companies.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — unknown id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — unknown id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — unknown id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Re-fetch the index to confirm — deleted companies no longer appear.

---

## 06. Orders / Requests

#### List All Orders

**What this does:** Returns a paginated, filterable, searchable list of orders.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/orders?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.orders.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `orders.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — (orders found) }*
```json
{
    "status": "success",
    "message": "تم استرجاع الطلبات بنجاح.",
    "data": {
        "data": [
            {
                "id": 1,
                "uuid": "ab984891-fe8c-4676-902c-0d5aa3225134",
                "order_number": "ORD-260820-TEQC",
                "customer": {
                    "id": 2,
                    "name": "Mr. Cristopher Hahn"
                },
                "technician": {
                    "id": null,
                    "name": null
                },
                "order_source": "individual",
                "booking_type": "instant",
                "scheduled_date": "2026-08-26",
                "status": "pending",
                "total_amount": "180.58",
                "paid_amount": "180.58",
                "is_auto": false,
                "needs_attention": false,
                "created_at": "2026-08-20T10:12:59+00:00"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/orders?page=1",
            "last": "http://localhost/api/v1/admin/orders?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/orders?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/orders",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### Show Order Details

**What this does:** Returns full details for one order.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/orders/:order` |
| **Route name** | `admin.orders.show` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `orders.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `order` — Order UUID (orders.uuid) — NOT the numeric orders.id. Copy the `uuid` field from a List/Show response. — chained from an earlier request in this flow ({{order_id}})

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "تم استرجاع الطلب بنجاح.",
    "data": {
        "id": 1,
        "uuid": "ab984891-fe8c-4676-902c-0d5aa3225134",
        "order_number": "ORD-260820-TEQC",
        "customer": {
            "id": 2,
            "name": "Mr. Cristopher Hahn",
            "email": "reed70@example.net",
            "phone": "1418821609"
        },
        "technician": {
            "id": null,
            "name": null
        },
        "assigned_by": {
            "id": null,
            "name": null
        },
        "branch": {
            "id": null,
            "name": null
        },
        "contract_id": null,
        "address": {
            "id": 1,
            "title": "Home"
        },
        "order_source": "individual",
        "booking_type": "instant",
        "scheduled_date": "2026-08-26",
        "status": "pending",
        "subtotal_amount": "157.03",
        "vat_amount": "23.55",
        "fees_amount": "0.00",
        "total_amount": "180.58",
        "paid_amount": "180.58",
        "is_auto": false,
        "needs_attention": false,
        "internal_notes": [],
        "items": [
            {
                "id": 1,
                "category_id": null,
                "service_name": "cum ipsum repudiandae",
                "pricing_type": "fixed",
                "unit_price": "232.49",
                "quantity": 2,
                "line_total": "464.98",
                "is_quoted": false,
                "notes": null,
                "request_description": null,
                "request_media_url": null
            }
        ],
        "payments": [],
        "attachments": [],
        "status_history": [
            {
                "id": 1,
                "from_status": null,
                "to_status": "pending",
                "changed_by": "Adriana Schmidt",
                "notes": null,
                "created_at": "2026-08-20T10:12:59+00:00"
            }
        ],
        "rating": null,
        "created_at": "2026-08-20T10:12:59+00:00",
        "updated_at": "2026-08-20T10:12:59+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — (unknown UUID) }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use `update` to modify it, or `destroy` to remove it.

---

#### Cancel Order

**What this does:** Admin cancellation — the widest allowance of any actor (any status except `finish`/`confirmed`/`cancelled`). If `paid_amount > 0` on an eligible individual order, refunds to the customer's wallet automatically (or records a blocked-refund audit row if ineligible, e.g. a company job order).

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/orders/:id/cancel` |
| **Route name** | `admin.orders.cancel` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `orders.cancel` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Order UUID (orders.uuid) — NOT the numeric orders.id. Copy the `uuid` field from a List/Show response. — chained from an earlier request in this flow ({{order_id}})

**Payload:**
Send as `application/json`. Allowed for any order not yet in `finish`, `confirmed`, or `cancelled`. If the order has a `paid_amount` > 0, cancelling also credits that amount back to the customer's wallet (never a gateway refund) — see RefundService.

**Field documentation:**
### `reason`
- **Description:** Cancellation Reason
- **Type:** `string`
- **Required:** required
- **Example:** `Manual adjustment by admin.`
- **Validation rules:** `required|string|max:500`
- `required` — must be provided.
- `string` — must be text.
- `max:500` — must not exceed 500.

**Example Request Body:**
```json
{
    "reason": "Customer requested cancellation due to change of plans"
}
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "تم إلغاء الطلب بنجاح.",
    "data": {
        "id": 5,
        "uuid": "56bb8eb6-1f51-40fc-95e8-f3033e39d765",
        "order_number": "ORD-260820-KBXU",
        "customer": {
            "id": 2,
            "name": "Mr. Cristopher Hahn",
            "email": "reed70@example.net",
            "phone": "1418821609"
        },
        "technician": {
            "id": null,
            "name": null
        },
        "assigned_by": {
            "id": null,
            "name": null
        },
        "branch": {
            "id": null,
            "name": null
        },
        "contract_id": null,
        "address": {
            "id": 1,
            "title": "Home"
        },
        "order_source": "job_order",
        "booking_type": "scheduled",
        "scheduled_date": "2026-08-27",
        "status": "cancelled",
        "subtotal_amount": "308.34",
        "vat_amount": "46.25",
        "fees_amount": "0.00",
        "total_amount": "354.59",
        "paid_amount": "0.00",
        "is_auto": false,
        "needs_attention": false,
        "internal_notes": [],
        "items": [],
        "payments": [],
        "attachments": [],
        "status_history": [
            {
                "id": 11,
                "from_status": "pending",
                "to_status": "cancelled",
                "changed_by": "Adriana Schmidt",
                "notes": "Customer requested cancellation due to change of plans",
                "created_at": "2026-08-20T10:12:59+00:00"
            },
            {
                "id": 10,
                "from_status": "pending",
                "to_status": "cancelled",
                "changed_by": "Adriana Schmidt",
                "notes": null,
                "created_at": "2026-08-20T10:12:59+00:00"
            },
            {
                "id": 9,
                "from_status": null,
                "to_status": "pending",
                "changed_by": "Adriana Schmidt",
                "notes": null,
                "created_at": "2026-08-20T10:12:59+00:00"
            }
        ],
        "rating": null,
        "created_at": "2026-08-20T10:12:59+00:00",
        "updated_at": "2026-08-20T10:12:59+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — Example Response — 422 Invalid State (already cancelled/finished) }*
```json
{
    "status": "fail",
    "message": "لم يعد بالإمكان إلغاء هذا الطلب.",
    "data": null
}
```

*{ 422 Unprocessable Entity — Example Response — 422 Validation Error (missing reason) }*
```json
{
    "status": "fail",
    "message": "حقل Cancellation Reason مطلوب.",
    "data": null
}
```

**What happens next:** Order is terminal. Check `GET /admin/wallets/{customer_wallet_id}/transactions` to confirm the refund landed, if applicable.

---

#### Reschedule Order

**What this does:** Changes the order's `scheduled_date`. Allowed for the same "before the technician has actually started" window as customer self-cancel — any status in `pending`, `waiting_price`, `priced`, `accepted`, `on_the_way`. Notifies the customer and the assigned technician (if any). Does **not** change `status` and does **not** add a `status_history` entry — the optional `reason` is only recorded as an internal activity-log entry, not returned in the response.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/orders/:id/reschedule` |
| **Route name** | `admin.orders.reschedule` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `orders.reschedule` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Order UUID (orders.uuid) — NOT the numeric orders.id. Copy the `uuid` field from a List/Show response.

**Payload:**
Send as `application/json`. Rejected with `422` if the order is no longer in a reschedulable status (e.g. already `on_the_way`'s technician has started, `finish`, `confirmed`, `cancelled`).

**Field documentation:**
### `scheduled_date`
- **Description:** Scheduled Date
- **Type:** `string` (date)
- **Required:** required
- **Example:** `2026-09-01`
- **Validation rules:** `required|date|after_or_equal:today`
- `required` — must be provided.
- `date` — must be a valid date.
- `after_or_equal:today` — must be today or later.
### `reason`
- **Description:** Reschedule Reason
- **Type:** `string`
- **Required:** optional
- **Example:** `Customer requested a later time slot.`
- **Validation rules:** `nullable|string|max:500`
- `nullable` — may be null.
- `string` — must be text.
- `max:500` — must not exceed 500.

**Example Request Body:**
```json
{
    "scheduled_date": "2026-09-01",
    "reason": "Customer requested a later time slot"
}
```

**Example Success Response:**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Order rescheduled successfully.",
    "data": {
        "id": 5,
        "uuid": "56bb8eb6-1f51-40fc-95e8-f3033e39d765",
        "order_number": "ORD-260820-KBXU",
        "status": "pending",
        "scheduled_date": "2026-09-01",
        "status_history": []
    }
}
```
*(Full response is the same `OrderDetailsResource` shape shown under "Cancel Order" — customer/technician/assigned_by/branch/address/amounts/items/payments/attachments — trimmed here to the fields this action actually changes.)*

**Example Error Response:**

*{ 422 Unprocessable Entity — Example Response — 422 Invalid State (order already started/terminal) }*
```json
{
    "status": "fail",
    "message": "This order can no longer be rescheduled.",
    "data": null
}
```

**What happens next:** Customer and assigned technician (if any) are notified of the new date.

---

#### Quote Order

**What this does:** Sets per-item prices on a `waiting_price` custom-request order — computes `subtotal_amount`/`total_amount` (plus optional `vat_amount`/`fees_amount`) and moves it to `priced`.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/orders/:id/quote` |
| **Route name** | `admin.orders.quote` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `orders.quote` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Order UUID (orders.uuid) — NOT the numeric orders.id. Copy the `uuid` field from a List/Show response. — ⚠️ **no real record exists in the seeded database** (confirmed empty — see [SEED_DATA.md](SEED_DATA.md)); placeholder `b51ed17d-b8d9-4aeb-90f3-c7e3d8eeea25` will 404/422 until you create one

**Payload:**
Send as `application/json`. Only valid when the order's status is `waiting_price` (custom-price requests) — quoting an order in any other status returns a 422. `items[].id` must be an `order_items.id` belonging to THIS order (fetch it from Show Order Details first, NOT the order's own id/uuid). `vat_amount`/`fees_amount` default to the order's existing values when omitted.

**Field documentation:**
### `items`
- **Description:** Items
- **Type:** `array`
- **Required:** required
- **Example:** `[{"id":1,"unit_price":10}]`
- **Validation rules:** `required|array|min:1`
- `required` — must be provided.
- `array` — must be an array.
- `min:1` — must be at least 1.
### `items.*.id`
- **Description:** Order Item
- **Type:** `integer`
- **Required:** required
- **Example:** `1`
- **Validation rules:** `required|integer|exists:order_items,id`
- `required` — must be provided.
- `integer` — must be a whole number.
- `exists:order_items,id` — must reference an existing record (order_items, id).
### `items.*.unit_price`
- **Description:** Unit Price
- **Type:** `number`
- **Required:** required
- **Example:** `10`
- **Validation rules:** `required|numeric|min:0`
- `required` — must be provided.
- `numeric` — must be numeric.
- `min:0` — must be at least .
### `vat_amount`
- **Description:** VAT Amount
- **Type:** `number`
- **Required:** optional
- **Example:** `10`
- **Validation rules:** `nullable|numeric|min:0`
- `nullable` — may be null.
- `numeric` — must be numeric.
- `min:0` — must be at least .
### `fees_amount`
- **Description:** Fees Amount
- **Type:** `number`
- **Required:** optional
- **Example:** `10`
- **Validation rules:** `nullable|numeric|min:0`
- `nullable` — may be null.
- `numeric` — must be numeric.
- `min:0` — must be at least .

**Example Request Body:**
```json
{
    "items": [
        {
            "id": 2,
            "unit_price": 150.5
        }
    ],
    "vat_amount": 45.15,
    "fees_amount": 10
}
```

**Actual Success Response(s):**

*{ 200 OK — (waiting_price → priced) }*
```json
{
    "status": "success",
    "message": "تم تسعير الطلب بنجاح.",
    "data": {
        "id": 2,
        "uuid": "b51ed17d-b8d9-4aeb-90f3-c7e3d8eeea25",
        "order_number": "ORD-260820-EHSJ",
        "customer": {
            "id": 2,
            "name": "Mr. Cristopher Hahn",
            "email": "reed70@example.net",
            "phone": "1418821609"
        },
        "technician": {
            "id": null,
            "name": null
        },
        "assigned_by": {
            "id": null,
            "name": null
        },
        "branch": {
            "id": null,
            "name": null
        },
        "contract_id": null,
        "address": {
            "id": 1,
            "title": "Home"
        },
        "order_source": "individual",
        "booking_type": "instant",
        "scheduled_date": null,
        "status": "priced",
        "subtotal_amount": "301.00",
        "vat_amount": "45.15",
        "fees_amount": "10.00",
        "total_amount": "356.15",
        "paid_amount": "418.95",
        "is_auto": false,
        "needs_attention": false,
        "internal_notes": [],
        "items": [
            {
                "id": 2,
                "category_id": null,
                "service_name": "pariatur dicta illum",
                "pricing_type": "fixed",
                "unit_price": "150.50",
                "quantity": 2,
                "line_total": "301.00",
                "is_quoted": true,
                "notes": null,
                "request_description": null,
                "request_media_url": null
            }
        ],
        "payments": [],
        "attachments": [],
        "status_history": [
            {
                "id": 4,
                "from_status": "waiting_price",
                "to_status": "priced",
                "changed_by": "Adriana Schmidt",
                "notes": "تم تسعير الطلب بنجاح.",
                "created_at": "2026-08-20T10:12:59+00:00"
            },
            {
                "id": 3,
                "from_status": "waiting_price",
                "to_status": "priced",
                "changed_by": "Adriana Schmidt",
                "notes": null,
                "created_at": "2026-08-20T10:12:59+00:00"
            },
            {
                "id": 2,
                "from_status": null,
                "to_status": "waiting_price",
                "changed_by": "Adriana Schmidt",
                "notes": null,
                "created_at": "2026-08-20T10:12:59+00:00"
            }
        ],
        "rating": null,
        "created_at": "2026-08-20T10:12:59+00:00",
        "updated_at": "2026-08-20T10:12:59+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — Example Response — 422 Invalid State (order not waiting_price) }*
```json
{
    "status": "fail",
    "message": "يمكن تسعير الطلبات التي تنتظر التسعير فقط.",
    "data": null
}
```

*{ 422 Unprocessable Entity — Example Response — 422 Validation Error (missing items) }*
```json
{
    "status": "fail",
    "message": "حقل Items مطلوب.",
    "data": null
}
```

**What happens next:** The customer must accept or reject the price — see `client.orders.accept-price` / `.reject-price` (or the company equivalents) in this section.

---

#### Status Order

**What this does:** Generic "advance one step" endpoint for the standard forward flow (`pending→accepted→on_the_way→start→finish→confirmed`) — rejects any transition that skips a step or that has a dedicated actor-specific endpoint instead (`waiting_price→priced`, `priced→pending/cancelled`, `finish→confirmed`).

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/orders/:id/status` |
| **Route name** | `admin.orders.status` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `orders.status` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Order UUID (orders.uuid) — NOT the numeric orders.id. Copy the `uuid` field from a List/Show response. — chained from an earlier request in this flow ({{order_id}})

**Payload:**
Send as `application/json`. Advances the order exactly ONE step forward in the fixed lifecycle `pending → accepted → on_the_way → start → finish → confirmed` — skipping a step, moving backward, or targeting `waiting_price`/`priced`/`cancelled` (those are reached through quote/cancel instead) all return a 422. `notes` is optional and stored on the status-history row.

**Field documentation:**
### `status`
- **Description:** Status
- **Type:** `string`
- **Required:** required
- **Example:** `pending`
- **Validation rules:** `required|string|in:"pending","waiting_price","priced","accepted","on_the_way","start","finish","confirmed","cancelled"`
- `required` — must be provided.
- `string` — must be text.
- `in:"pending","waiting_price","priced","accepted","on_the_way","start","finish","confirmed","cancelled"` — must be one of: "pending", "waiting_price", "priced", "accepted", "on_the_way", "start", "finish", "confirmed", "cancelled".
### `notes`
- **Description:** Notes
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `nullable|string|max:500`
- `nullable` — may be null.
- `string` — must be text.
- `max:500` — must not exceed 500.

**Example Request Body:**
```json
{
    "status": "accepted",
    "notes": "Technician confirmed availability"
}
```

**Actual Success Response(s):**

*{ 200 OK — (pending → accepted) }*
```json
{
    "status": "success",
    "message": "تم تحديث الطلب بنجاح.",
    "data": {
        "id": 4,
        "uuid": "bf29cbf3-93c6-4a65-a2d6-20993b2b1d98",
        "order_number": "ORD-260820-MXEV",
        "customer": {
            "id": 2,
            "name": "Mr. Cristopher Hahn",
            "email": "reed70@example.net",
            "phone": "1418821609"
        },
        "technician": {
            "id": null,
            "name": null
        },
        "assigned_by": {
            "id": null,
            "name": null
        },
        "branch": {
            "id": null,
            "name": null
        },
        "contract_id": null,
        "address": {
            "id": 1,
            "title": "Home"
        },
        "order_source": "individual",
        "booking_type": "instant",
        "scheduled_date": "2026-09-01",
        "status": "accepted",
        "subtotal_amount": "183.32",
        "vat_amount": "27.50",
        "fees_amount": "0.00",
        "total_amount": "210.82",
        "paid_amount": "210.82",
        "is_auto": false,
        "needs_attention": false,
        "internal_notes": [],
        "items": [],
        "payments": [],
        "attachments": [],
        "status_history": [
            {
                "id": 8,
                "from_status": "pending",
                "to_status": "accepted",
                "changed_by": "Adriana Schmidt",
                "notes": "Technician confirmed availability",
                "created_at": "2026-08-20T10:12:59+00:00"
            },
            {
                "id": 7,
                "from_status": "pending",
                "to_status": "accepted",
                "changed_by": "Adriana Schmidt",
                "notes": null,
                "created_at": "2026-08-20T10:12:59+00:00"
            },
            {
                "id": 6,
                "from_status": null,
                "to_status": "pending",
                "changed_by": "Adriana Schmidt",
                "notes": null,
                "created_at": "2026-08-20T10:12:59+00:00"
            }
        ],
        "rating": null,
        "created_at": "2026-08-20T10:12:59+00:00",
        "updated_at": "2026-08-20T10:12:59+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — Example Response — 422 Invalid Transition (skipped a step) }*
```json
{
    "status": "fail",
    "message": "لا يمكن تغيير الحالة من الحالة الحالية للطلب.",
    "data": null
}
```

*{ 422 Unprocessable Entity — Example Response — 422 Validation Error (unknown status value) }*
```json
{
    "status": "fail",
    "message": "الحالة المحددة غير صالحة.",
    "data": null
}
```

**What happens next:** Prefer the technician/customer lifecycle-specific endpoints where one exists; use this as an admin override/escape hatch.

---

## 06b. Visits

> Named `admin.orders.visits` (not `admin.visits.index`) on purpose — the route is registered via `Route::apiResource('visits', VisitController::class)->only(['index'])->names(['index' => 'admin.orders.visits'])`, so it resolves to the `orders.visits` RBAC permission and stays grouped with the rest of the order permission set rather than standing alone. `VisitPermissionSeeder` grants `orders.visits` to every role that already holds `orders.index`, so access tracks the Orders section above automatically. Only `index` is registered — there is no show/store/update/destroy for this resource.

#### List All Visits

**What this does:** Returns a paginated, filterable list of **contract-scheduled visits** — the same `orders` table as §06 Orders / Requests, restricted to rows with a non-null `contract_id` (i.e. recurring visits materialized from an active company contract, not ad-hoc one-off requests). Eager-loads `customer`, `technician.user`, `contract`, and `branch`. Rows flagged `needs_attention` (technician rejected/unreachable/timed out) sort first, then newest-first (`VisitService::index`).

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/visits?page=1` |
| **Route name** | `admin.orders.visits` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `orders.visits` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `401 Unauthorized` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`
- `Authorization: Bearer {token}`

**Payload:**
No request body. Use the documented query parameters.

**Query parameters:**
- `status` — Filter to one exact order status (optional)
- `order_source` — Filter by order source (optional)
- `customer_id` — Filter to one customer id (optional)
- `technician_id` — Filter to one technician profile id (optional)
- `needs_attention` — `1`/`true` to show only orders needing attention (optional)
- `search` — Matches `order_number`, or the customer's `name`/`email` (optional)
- `from` / `to` — Filter by `scheduled_date` range, inclusive (`Y-m-d`) (optional)
- `per_page` — Items per page, 1–100, default 15 (optional)

**Example Response** *(not captured from a live run — no server was available when this endpoint was added; shape follows `VisitResource` and the standard Laravel paginator envelope used throughout this file)*:

*{ 200 OK — visits found }*
```json
{
    "status": "success",
    "message": "تم استرجاع الطلبات بنجاح.",
    "data": {
        "data": [
            {
                "id": 42,
                "uuid": "7c1e6a2d-3b4f-4a11-9c7e-1f2a3b4c5d6e",
                "order_number": "ORD-260824-VXQK",
                "contract": {
                    "id": 1,
                    "contract_number": "CNT-2026-0001",
                    "company": {
                        "id": 10,
                        "name": "Gulf Maintenance Co."
                    },
                    "start_date": "2026-01-01",
                    "end_date": "2026-12-31",
                    "billing_cycle": "monthly",
                    "visits_allowed": 12,
                    "visits_consumed": 3,
                    "remaining_visits": 9,
                    "total_amount": "12000.00",
                    "currency": "SAR",
                    "status": "active",
                    "status_label": "Active",
                    "auto_renew": true,
                    "signed_at": "2026-01-01T09:00:00+00:00",
                    "approved_at": "2026-01-01T10:00:00+00:00",
                    "created_at": "2026-01-01T08:30:00+00:00"
                },
                "branch": {
                    "id": 1,
                    "company_id": 10,
                    "company_name": "Gulf Maintenance Co.",
                    "company": null,
                    "name": "Riyadh Main Branch",
                    "phone": "+966500000000",
                    "address_text": "King Fahd Road, Riyadh",
                    "latitude": "24.713600",
                    "longitude": "46.675300",
                    "working_hours": null,
                    "is_active": true,
                    "created_at": "2026-01-01"
                },
                "customer": {
                    "id": 10,
                    "name": "Gulf Maintenance Co."
                },
                "technician": {
                    "id": 2,
                    "name": "Fahad Al-Otaibi"
                },
                "order_source": "job_order",
                "booking_type": "contract",
                "scheduled_date": "2026-08-25",
                "status": "accepted",
                "paid_amount": "0.00",
                "total_amount": "1000.00",
                "is_auto": true,
                "needs_attention": false,
                "created_at": "2026-08-24T07:12:00+00:00"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/visits?page=1",
            "last": "http://localhost/api/v1/admin/visits?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

**Actual Error Response(s):**

*{ 401 Unauthorized — 401 Unauthenticated }*
```json
{
    "status": "fail",
    "message": "Unauthenticated, you have to login first",
    "data": null
}
```

**What happens next:** Drill into a specific visit's full order record via `GET /admin/orders/:id` (§06 Orders / Requests above) — this endpoint is read-only and has no dedicated show/update/destroy actions.

---

## 07. Assignments

#### Assign Technician Order

**What this does:** Assigns (or reassigns) a technician to an order not yet `finish`/`confirmed`/`cancelled`. Arms a response-timeout job (default 15 min, `AppConfig`-driven) — if the technician never responds, they're auto-unassigned and the next available match is tried automatically.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/orders/:id/assign-technician` |
| **Route name** | `admin.orders.assign-technician` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `orders.assign-technician` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Order UUID (orders.uuid) — NOT the numeric orders.id. Copy the `uuid` field from a List/Show response. — chained from an earlier request in this flow ({{order_id}})

**Payload:**
Send as `application/json`. `technician_id` is the technician's **profile id** (`technicians.id`, from Admin → Technicians list), NOT the technician's `users.id`. Allowed for any order not yet in `finish`, `confirmed`, or `cancelled`.

**Field documentation:**
### `technician_id`
- **Description:** Technician
- **Type:** `integer`
- **Required:** required
- **Example:** `1`
- **Validation rules:** `required|integer|exists:technicians,id`
- `required` — must be provided.
- `integer` — must be a whole number.
- `exists:technicians,id` — must reference an existing record (technicians, id).

**Example Request Body:**
```json
{
    "technician_id": 1
}
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "تم تعيين الفني بنجاح.",
    "data": {
        "id": 3,
        "uuid": "973de10c-65ab-4fc5-92ce-ef31e17d501c",
        "order_number": "ORD-260820-XKPI",
        "customer": {
            "id": 2,
            "name": "Mr. Cristopher Hahn",
            "email": "reed70@example.net",
            "phone": "1418821609"
        },
        "technician": {
            "id": 1,
            "name": "Amber Rogahn PhD"
        },
        "assigned_by": {
            "id": 1,
            "name": "Adriana Schmidt"
        },
        "branch": {
            "id": null,
            "name": null
        },
        "contract_id": null,
        "address": {
            "id": 1,
            "title": "Home"
        },
        "order_source": "job_order",
        "booking_type": "instant",
        "scheduled_date": null,
        "status": "pending",
        "subtotal_amount": "275.10",
        "vat_amount": "41.27",
        "fees_amount": "0.00",
        "total_amount": "316.37",
        "paid_amount": "316.37",
        "is_auto": false,
        "needs_attention": false,
        "internal_notes": [],
        "items": [],
        "payments": [],
        "attachments": [],
        "status_history": [
            {
                "id": 5,
                "from_status": null,
                "to_status": "pending",
                "changed_by": "Adriana Schmidt",
                "notes": null,
                "created_at": "2026-08-20T10:12:59+00:00"
            }
        ],
        "rating": null,
        "created_at": "2026-08-20T10:12:59+00:00",
        "updated_at": "2026-08-20T10:12:59+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — Example Response — 422 Validation Error (unknown technician_id) }*
```json
{
    "status": "fail",
    "message": "Technician المحدد غير صالح.",
    "data": null
}
```

**What happens next:** **Effect on Technician:** the order now appears in their `technician.orders.index` (`02-technician.md` §04 Assigned Orders & Jobs), and they must accept or reject it (§05) within the timeout window.

---

## 08. Contracts

#### List All Contracts

**What this does:** Returns a paginated, filterable, searchable list of contracts.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contracts?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.contracts.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contracts.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `401 Unauthorized` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Contracts retrieved successfully.",
    "data": {
        "data": [
            {
                "id": 1,
                "contract_number": "CTR-2026-000001",
                "company": {
                    "id": 19,
                    "name": "Bennie Strosin"
                },
                "start_date": "2026-08-20",
                "end_date": "2026-09-20",
                "billing_cycle": "monthly",
                "visits_allowed": 10,
                "visits_consumed": 0,
                "remaining_visits": 10,
                "total_amount": "1000.00",
                "currency": "SAR",
                "status": "pending_signature",
                "status_label": "Pending Signature",
                "auto_renew": false,
                "signed_at": null,
                "approved_at": null,
                "created_at": "2026-08-20T12:09:43+00:00"
            },
            {
                "id": 2,
                "contract_number": "CTR-2026-000002",
                "company": {
                    "id": 19,
                    "name": "Bennie Strosin"
                },
                "start_date": "2026-08-20",
                "end_date": "2026-09-20",
                "billing_cycle": "monthly",
                "visits_allowed": 10,
                "visits_consumed": 0,
                "remaining_visits": 10,
                "total_amount": "1000.00",
                "currency": "SAR",
                "status": "active",
                "status_label": "Active",
                "auto_renew": false,
                "signed_at": null,
                "approved_at": null,
                "created_at": "2026-08-20T12:09:43+00:00"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/contracts?page=1",
            "last": "http://localhost/api/v1/admin/contracts?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/contracts?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/contracts",
            "per_page": 15,
            "to": 2,
            "total": 2
        }
    }
}
```

*{ 200 OK — filtered by status=active }*
```json
{
    "status": "success",
    "message": "Contracts retrieved successfully.",
    "data": {
        "data": [
            {
                "id": 2,
                "contract_number": "CTR-2026-000002",
                "company": {
                    "id": 19,
                    "name": "Bennie Strosin"
                },
                "start_date": "2026-08-20",
                "end_date": "2026-09-20",
                "billing_cycle": "monthly",
                "visits_allowed": 10,
                "visits_consumed": 0,
                "remaining_visits": 10,
                "total_amount": "1000.00",
                "currency": "SAR",
                "status": "active",
                "status_label": "Active",
                "auto_renew": false,
                "signed_at": null,
                "approved_at": null,
                "created_at": "2026-08-20T12:09:43+00:00"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/contracts?page=1",
            "last": "http://localhost/api/v1/admin/contracts?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/contracts?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/contracts",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

**Actual Error Response(s):**

*{ 401 Unauthorized — 401 Unauthenticated }*
```json
{
    "status": "fail",
    "message": "Unauthenticated, you have to login first",
    "data": null
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### Show Contract Details

**What this does:** Returns full details for one contract.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contracts/:contract` |
| **Route name** | `admin.contracts.show` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contracts.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `contract` — Contract ID — seeded example: `1`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Contract retrieved successfully.",
    "data": {
        "id": 4,
        "contract_number": "CTR-2026-000001",
        "company": {
            "id": 24,
            "name": "Bryce Hoeger",
            "email": "westley.keeling@example.net"
        },
        "created_by": {
            "id": 24,
            "name": "Bryce Hoeger"
        },
        "approved_by": {
            "id": null,
            "name": null
        },
        "signed_by": {
            "id": null,
            "name": null
        },
        "start_date": "2026-08-20",
        "end_date": "2026-09-20",
        "billing_cycle": "monthly",
        "visits_allowed": 10,
        "visits_consumed": 0,
        "remaining_visits": 10,
        "total_amount": "1000.00",
        "currency": "SAR",
        "status": "pending_signature",
        "status_label": "Pending Signature",
        "auto_renew": false,
        "pdf_path": null,
        "signed_pdf_path": null,
        "signed_at": null,
        "approved_at": null,
        "terminated_at": null,
        "terminated_reason": null,
        "notes": null,
        "branches": [],
        "services": [],
        "signatures": [],
        "renewal_requests": [],
        "created_at": "2026-08-20T12:09:44+00:00",
        "updated_at": "2026-08-20T12:09:44+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use `update` to modify it, or `destroy` to remove it.

---

#### Create New Contract

**What this does:** Creates a new contract.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contracts` |
| **Route name** | `admin.contracts.store` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contracts.create` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `201 Created`, `401 Unauthorized`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `company_id`
- **Description:** Company id
- **Type:** `integer`
- **Required:** required
- **Example:** `10`
- **Validation rules:** `required|exists:users,id`
- `required` — must be provided.
- `exists:users,id` — must reference an existing record (users, id).
### `service_ids`
- **Description:** Service ids
- **Type:** `array`
- **Required:** optional
- **Example:** `[2]`
- **Validation rules:** `sometimes|array|min:1`
- `sometimes` — validated only when the field is present.
- `array` — must be an array.
- `min:1` — must be at least 1.
### `service_ids.*`
- **Description:** Service ids item
- **Type:** `integer`
- **Required:** optional
- **Example:** `2`
- **Validation rules:** `exists:categories,id`
- `exists:categories,id` — must reference an existing record (categories, id).
### `branch_ids`
- **Description:** Branch ids
- **Type:** `array`
- **Required:** optional
- **Example:** `[1]`
- **Validation rules:** `sometimes|array|min:1`
- `sometimes` — validated only when the field is present.
- `array` — must be an array.
- `min:1` — must be at least 1.
### `branch_ids.*`
- **Description:** Branch ids item
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `exists:branches,id`
- `exists:branches,id` — must reference an existing record (branches, id).
### `start_date`
- **Description:** Start date
- **Type:** `string`
- **Required:** required
- **Example:** `2026-08-21`
- **Validation rules:** `required|date|after_or_equal:today`
- `required` — must be provided.
- `date` — must be a valid date.
- `after_or_equal:today` — custom validation rule.
### `end_date`
- **Description:** End date
- **Type:** `string`
- **Required:** required
- **Example:** `2026-08-21`
- **Validation rules:** `required|date|after:start_date`
- `required` — must be provided.
- `date` — must be a valid date.
- `after:start_date` — custom validation rule.
### `billing_cycle`
- **Description:** Billing cycle
- **Type:** `string`
- **Required:** required
- **Example:** `monthly`
- **Validation rules:** `required|in:monthly,quarterly,annual`
- `required` — must be provided.
- `in:monthly,quarterly,annual` — must be one of: monthly, quarterly, annual.
### `visits_allowed`
- **Description:** Visits allowed
- **Type:** `integer`
- **Required:** required
- **Example:** `1`
- **Validation rules:** `required|integer|min:1`
- `required` — must be provided.
- `integer` — must be a whole number.
- `min:1` — must be at least 1.
### `total_amount`
- **Description:** Total amount
- **Type:** `number`
- **Required:** required
- **Example:** `10`
- **Validation rules:** `required|numeric|min:0`
- `required` — must be provided.
- `numeric` — must be numeric.
- `min:0` — must be at least .
### `currency`
- **Description:** Currency
- **Type:** `string`
- **Required:** optional
- **Example:** `EGP`
- **Validation rules:** `sometimes|string|size:3`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `size:3` — custom validation rule.
### `notes`
- **Description:** Notes
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `nullable|string|max:1000`
- `nullable` — may be null.
- `string` — must be text.
- `max:1000` — must not exceed 1000.

**Example Request Body:**
```json
{
    "company_id": 10,
    "start_date": "2026-08-21",
    "end_date": "2027-08-20",
    "billing_cycle": "monthly",
    "visits_allowed": 12,
    "total_amount": 960,
    "currency": "SAR",
    "branch_ids": [
        1
    ],
    "service_ids": [
        2
    ],
    "notes": "Annual maintenance contract"
}
```

**Actual Success Response(s):**

*{ 201 Created — 201 - contract created (status=draft) }*
```json
{
    "status": "success",
    "message": "Contract created successfully.",
    "data": {
        "id": 3,
        "contract_number": "CTR-2026-000001",
        "company": {
            "id": 21,
            "name": "Mr. Hugh Jast",
            "email": "michele03@example.org"
        },
        "created_by": {
            "id": 20,
            "name": "Danielle Moore"
        },
        "approved_by": {
            "id": null,
            "name": null
        },
        "signed_by": {
            "id": null,
            "name": null
        },
        "start_date": "2026-08-21",
        "end_date": "2027-08-20",
        "billing_cycle": "monthly",
        "visits_allowed": 12,
        "visits_consumed": 0,
        "remaining_visits": 12,
        "total_amount": "960.00",
        "currency": "SAR",
        "status": "draft",
        "status_label": "Draft",
        "auto_renew": null,
        "pdf_path": null,
        "signed_pdf_path": null,
        "signed_at": null,
        "approved_at": null,
        "terminated_at": null,
        "terminated_reason": null,
        "notes": "Annual maintenance contract",
        "branches": [
            {
                "id": 5,
                "name": "Main Branch"
            }
        ],
        "services": [
            {
                "id": 13,
                "name": "AC Repair"
            }
        ],
        "signatures": [],
        "renewal_requests": [],
        "created_at": "2026-08-20T12:09:44+00:00",
        "updated_at": "2026-08-20T12:09:44+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 - validation error (missing required fields, bad billing_cycle) }*
```json
{
    "status": "fail",
    "message": "The company id field is required. (and 5 more errors)",
    "data": null
}
```

*{ 401 Unauthorized — 401 - unauthenticated }*
```json
{
    "status": "fail",
    "message": "Unauthenticated, you have to login first",
    "data": null
}
```

**What happens next:** Use the returned id with `show`/`update`/`destroy` for this contract.

---

#### Update Contract

**What this does:** Updates an existing contract.

| | |
|---|---|
| **Method** | `PUT` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contracts/:contract` |
| **Route name** | `admin.contracts.update` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contracts.update` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `contract` — Contract ID — seeded example: `1`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `company_id`
- **Description:** Company id
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `sometimes|exists:users,id`
- `sometimes` — validated only when the field is present.
- `exists:users,id` — must reference an existing record (users, id).
### `service_ids`
- **Description:** Service ids
- **Type:** `array`
- **Required:** optional
- **Example:** `[2]`
- **Validation rules:** `sometimes|array|min:1`
- `sometimes` — validated only when the field is present.
- `array` — must be an array.
- `min:1` — must be at least 1.
### `service_ids.*`
- **Description:** Service ids item
- **Type:** `integer`
- **Required:** optional
- **Example:** `2`
- **Validation rules:** `exists:categories,id`
- `exists:categories,id` — must reference an existing record (categories, id).
### `branch_ids`
- **Description:** Branch ids
- **Type:** `array`
- **Required:** optional
- **Example:** `[1]`
- **Validation rules:** `sometimes|array|min:1`
- `sometimes` — validated only when the field is present.
- `array` — must be an array.
- `min:1` — must be at least 1.
### `branch_ids.*`
- **Description:** Branch ids item
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `exists:branches,id`
- `exists:branches,id` — must reference an existing record (branches, id).
### `start_date`
- **Description:** Start date
- **Type:** `string`
- **Required:** optional
- **Example:** `2026-08-21`
- **Validation rules:** `sometimes|date|after_or_equal:today`
- `sometimes` — validated only when the field is present.
- `date` — must be a valid date.
- `after_or_equal:today` — custom validation rule.
### `end_date`
- **Description:** End date
- **Type:** `string`
- **Required:** optional
- **Example:** `2026-08-21`
- **Validation rules:** `sometimes|date|after:start_date`
- `sometimes` — validated only when the field is present.
- `date` — must be a valid date.
- `after:start_date` — custom validation rule.
### `billing_cycle`
- **Description:** Billing cycle
- **Type:** `string`
- **Required:** optional
- **Example:** `monthly`
- **Validation rules:** `sometimes|in:monthly,quarterly,annual`
- `sometimes` — validated only when the field is present.
- `in:monthly,quarterly,annual` — must be one of: monthly, quarterly, annual.
### `visits_allowed`
- **Description:** Visits allowed
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `sometimes|integer|min:1`
- `sometimes` — validated only when the field is present.
- `integer` — must be a whole number.
- `min:1` — must be at least 1.
### `total_amount`
- **Description:** Total amount
- **Type:** `number`
- **Required:** optional
- **Example:** `10`
- **Validation rules:** `sometimes|numeric|min:0`
- `sometimes` — validated only when the field is present.
- `numeric` — must be numeric.
- `min:0` — must be at least .
### `currency`
- **Description:** Currency
- **Type:** `string`
- **Required:** optional
- **Example:** `EGP`
- **Validation rules:** `sometimes|string|size:3`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `size:3` — custom validation rule.
### `notes`
- **Description:** Notes
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `nullable|string|max:1000`
- `nullable` — may be null.
- `string` — must be text.
- `max:1000` — must not exceed 1000.

**Example Request Body:**
```json
{
    "total_amount": 1200,
    "notes": "Updated notes"
}
```

**Actual Success Response(s):**

*{ 200 OK — draft contract updated }*
```json
{
    "status": "success",
    "message": "Contract updated successfully.",
    "data": {
        "id": 5,
        "contract_number": "CTR-2026-000001",
        "company": {
            "id": 26,
            "name": "Mariane Blick",
            "email": "wsimonis@example.com"
        },
        "created_by": {
            "id": 26,
            "name": "Mariane Blick"
        },
        "approved_by": {
            "id": null,
            "name": null
        },
        "signed_by": {
            "id": null,
            "name": null
        },
        "start_date": "2026-08-20",
        "end_date": "2026-09-20",
        "billing_cycle": "monthly",
        "visits_allowed": 10,
        "visits_consumed": 0,
        "remaining_visits": 10,
        "total_amount": "1200.00",
        "currency": "SAR",
        "status": "draft",
        "status_label": "Draft",
        "auto_renew": false,
        "pdf_path": null,
        "signed_pdf_path": null,
        "signed_at": null,
        "approved_at": null,
        "terminated_at": null,
        "terminated_reason": null,
        "notes": "Updated notes",
        "branches": [],
        "services": [],
        "signatures": [],
        "renewal_requests": [],
        "created_at": "2026-08-20T12:09:44+00:00",
        "updated_at": "2026-08-20T12:09:44+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 - active contract can no longer be edited (canBeEdited() only allows draft/pending_signature) }*
```json
{
    "status": "fail",
    "message": "Contract can no longer be edited.",
    "data": null
}
```

*{ 404 Not Found — 404 - not found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Fetch `show` to confirm the change.

---

#### Approve Contract

**What this does:** Approves a `pending_approval` contract — moves it to `active` and materializes its full visit quota as real `Order` rows (one unscheduled, zero-priced `contract_visit` order per visit slot on each contracted branch/service pair — see `ContractService::generateVisitOrders()`), rather than a separate ledger balance.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contracts/:id/approve` |
| **Route name** | `admin.contracts.approve` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contracts.approve` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`

**Payload:**
No fields. Send an empty JSON object `{}`.

**Example Request Body:**
```json
[]
```

**Actual Success Response(s):**

*{ 200 OK — pending_approval to active }*
```json
{
    "status": "success",
    "message": "Contract approved successfully.",
    "data": {
        "id": 14,
        "contract_number": "CTR-2026-000001",
        "company": {
            "id": 43,
            "name": "Araceli Miller V",
            "email": "okeefe.keegan@example.org"
        },
        "created_by": {
            "id": 43,
            "name": "Araceli Miller V"
        },
        "approved_by": {
            "id": 42,
            "name": "Joelle Beahan"
        },
        "signed_by": {
            "id": null,
            "name": null
        },
        "start_date": "2026-08-20",
        "end_date": "2026-09-20",
        "billing_cycle": "monthly",
        "visits_allowed": 10,
        "visits_consumed": 0,
        "remaining_visits": 10,
        "total_amount": "1000.00",
        "currency": "SAR",
        "status": "active",
        "status_label": "Active",
        "auto_renew": false,
        "pdf_path": null,
        "signed_pdf_path": null,
        "signed_at": null,
        "approved_at": "2026-08-20T12:09:44+00:00",
        "terminated_at": null,
        "terminated_reason": null,
        "notes": null,
        "branches": [],
        "services": [],
        "signatures": [],
        "renewal_requests": [],
        "created_at": "2026-08-20T12:09:44+00:00",
        "updated_at": "2026-08-20T12:09:44+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 - already active, not pending_approval }*
```json
{
    "status": "fail",
    "message": "Contract is not pending approval.",
    "data": null
}
```

*{ 404 Not Found — 404 - not found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** **Effect on Company:** `03-company.md` §04 Contracts now shows `status: active`, and §06 Orders & Jobs can be created against it. The generated visit-orders flow through the normal order status machine like any other order.

---

#### Reject Contract

**What this does:** Rejects a contract still at `pending_signature`/`pending_approval`, recording a reason.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contracts/:id/reject` |
| **Route name** | `admin.contracts.reject` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contracts.reject` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`

**Payload:**
Example payload is included in the request body. No FormRequest validation rules were detected.
### `reason`
- **Description:** Reason
- **Type:** `string`
- **Required:** optional
- **Example:** `Does not meet platform requirements.`
- **Validation rules:** `not specified`
- `not specified` — no validation rule was declared.

**Example Request Body:**
```json
{
    "reason": "Missing required signatures on branch documentation"
}
```

**Actual Success Response(s):**

*{ 200 OK — pending_approval to rejected }*
```json
{
    "status": "success",
    "message": "Contract rejected successfully.",
    "data": {
        "id": 16,
        "contract_number": "CTR-2026-000001",
        "company": {
            "id": 48,
            "name": "Angelo Rosenbaum",
            "email": "alana63@example.org"
        },
        "created_by": {
            "id": 48,
            "name": "Angelo Rosenbaum"
        },
        "approved_by": {
            "id": null,
            "name": null
        },
        "signed_by": {
            "id": null,
            "name": null
        },
        "start_date": "2026-08-20",
        "end_date": "2026-09-20",
        "billing_cycle": "monthly",
        "visits_allowed": 10,
        "visits_consumed": 0,
        "remaining_visits": 10,
        "total_amount": "1000.00",
        "currency": "SAR",
        "status": "rejected",
        "status_label": "Rejected",
        "auto_renew": false,
        "pdf_path": null,
        "signed_pdf_path": null,
        "signed_at": null,
        "approved_at": null,
        "terminated_at": null,
        "terminated_reason": "Missing required signatures on branch documentation",
        "notes": null,
        "branches": [],
        "services": [],
        "signatures": [],
        "renewal_requests": [],
        "created_at": "2026-08-20T12:09:44+00:00",
        "updated_at": "2026-08-20T12:09:44+00:00"
    }
}
```

*{ 200 OK — pending_signature to rejected }*
```json
{
    "status": "success",
    "message": "Contract rejected successfully.",
    "data": {
        "id": 17,
        "contract_number": "CTR-2026-000001",
        "company": {
            "id": 50,
            "name": "Prof. Albertha Gottlieb III",
            "email": "alisa.renner@example.com"
        },
        "created_by": {
            "id": 50,
            "name": "Prof. Albertha Gottlieb III"
        },
        "approved_by": {
            "id": null,
            "name": null
        },
        "signed_by": {
            "id": null,
            "name": null
        },
        "start_date": "2026-08-20",
        "end_date": "2026-09-20",
        "billing_cycle": "monthly",
        "visits_allowed": 10,
        "visits_consumed": 0,
        "remaining_visits": 10,
        "total_amount": "1000.00",
        "currency": "SAR",
        "status": "rejected",
        "status_label": "Rejected",
        "auto_renew": false,
        "pdf_path": null,
        "signed_pdf_path": null,
        "signed_at": null,
        "approved_at": null,
        "terminated_at": null,
        "terminated_reason": "Company withdrew the request",
        "notes": null,
        "branches": [],
        "services": [],
        "signatures": [],
        "renewal_requests": [],
        "created_at": "2026-08-20T12:09:44+00:00",
        "updated_at": "2026-08-20T12:09:44+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 - active contract cannot be rejected }*
```json
{
    "status": "fail",
    "message": "Contract cannot be rejected in its current state.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 - validation error (reason required, inline $request->validate()) }*
```json
{
    "status": "fail",
    "message": "The reason field is required.",
    "data": null
}
```

*{ 404 Not Found — 404 - not found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** The company must submit a new contract if it wants to try again — there is no re-submit-same-contract flow.

---

#### Renewal Contract

**What this does:** Approves or rejects (`:action` path segment) a company's pending renewal request. Approval creates a **new** `Contract` row (copying billing terms and the per-branch/service visit-quota breakdown) with its own freshly-generated visit-orders, and expires the old one; rejection just marks the renewal request rejected and leaves the original contract as-is.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contracts/:id/renewal/:action` |
| **Route name** | `admin.contracts.renewal` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contracts.renewal` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`
- `action` — Action ID — seeded example: `approve`

**Payload:**
Example payload is included in the request body. No FormRequest validation rules were detected.
### `key`
- **Description:** Key
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `not specified`
- `not specified` — no validation rule was declared.

**Example Request Body:**
```json
{
    "key": "value"
}
```

**Actual Success Response(s):**

*{ 200 OK — BUG (see report): a new active contract IS created in the DB and the old one IS expired, but the response body echoes the OLD (now-expired) contract's data, not the new contract — ContractService::renewalAction() builds $newContract inside the DB::transaction() closure but returns ContractDetailsResource::make($contract) on the stale outer variable }*
```json
{
    "status": "success",
    "message": "Renewal approved successfully.",
    "data": {
        "id": 23,
        "contract_number": "CTR-2026-000001",
        "company": {
            "id": 64,
            "name": "Lila McGlynn",
            "email": "nicolas.audie@example.com"
        },
        "created_by": {
            "id": 64,
            "name": "Lila McGlynn"
        },
        "approved_by": {
            "id": null,
            "name": null
        },
        "signed_by": {
            "id": null,
            "name": null
        },
        "start_date": "2026-08-20",
        "end_date": "2026-08-25",
        "billing_cycle": "monthly",
        "visits_allowed": 10,
        "visits_consumed": 0,
        "remaining_visits": 10,
        "total_amount": "1000.00",
        "currency": "SAR",
        "status": "expired",
        "status_label": "Expired",
        "auto_renew": false,
        "pdf_path": null,
        "signed_pdf_path": null,
        "signed_at": null,
        "approved_at": null,
        "terminated_at": null,
        "terminated_reason": null,
        "notes": null,
        "branches": [],
        "services": [],
        "signatures": [],
        "renewal_requests": [
            {
                "id": 1,
                "status": "approved",
                "note": "Please renew for another year",
                "new_contract_id": 24,
                "requested_by": "Lila McGlynn",
                "handled_by": "Javier Kuvalis",
                "created_at": "2026-08-20T12:09:44+00:00"
            }
        ],
        "created_at": "2026-08-20T12:09:44+00:00",
        "updated_at": "2026-08-20T12:09:44+00:00"
    }
}
```

*{ 200 OK — renewal rejected, contract status unchanged }*
```json
{
    "status": "success",
    "message": "Renewal rejected successfully.",
    "data": {
        "id": 25,
        "contract_number": "CTR-2026-000001",
        "company": {
            "id": 66,
            "name": "Jeromy Jaskolski",
            "email": "johns.tomasa@example.org"
        },
        "created_by": {
            "id": 66,
            "name": "Jeromy Jaskolski"
        },
        "approved_by": {
            "id": null,
            "name": null
        },
        "signed_by": {
            "id": null,
            "name": null
        },
        "start_date": "2026-08-20",
        "end_date": "2026-09-20",
        "billing_cycle": "monthly",
        "visits_allowed": 10,
        "visits_consumed": 0,
        "remaining_visits": 10,
        "total_amount": "1000.00",
        "currency": "SAR",
        "status": "pending_renewal",
        "status_label": "Pending Renewal",
        "auto_renew": false,
        "pdf_path": null,
        "signed_pdf_path": null,
        "signed_at": null,
        "approved_at": null,
        "terminated_at": null,
        "terminated_reason": null,
        "notes": null,
        "branches": [],
        "services": [],
        "signatures": [],
        "renewal_requests": [
            {
                "id": 2,
                "status": "rejected",
                "note": null,
                "new_contract_id": null,
                "requested_by": "Jeromy Jaskolski",
                "handled_by": "Carolyne Greenfelder",
                "created_at": "2026-08-20T12:09:44+00:00"
            }
        ],
        "created_at": "2026-08-20T12:09:44+00:00",
        "updated_at": "2026-08-20T12:09:44+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 - invalid action segment (not 'approve'/'reject') }*
```json
{
    "message": "Invalid action"
}
```

*{ 422 Unprocessable Entity — 422 - contract is not pending_renewal }*
```json
{
    "status": "fail",
    "message": "Contract is not pending renewal.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 - no pending renewal request row found despite status=pending_renewal }*
```json
{
    "status": "fail",
    "message": "No pending renewal request found.",
    "data": null
}
```

*{ 404 Not Found — 404 - contract not found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** On approval, switch to referencing the new contract's id for further calls — the old one is now `expired`.

---

#### Terminate Contract

**What this does:** Ends an `active` contract early, recording a reason.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contracts/:id/terminate` |
| **Route name** | `admin.contracts.terminate` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contracts.terminate` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `reason`
- **Description:** Reason
- **Type:** `string`
- **Required:** required
- **Example:** `Manual adjustment by admin.`
- **Validation rules:** `required|string|max:500`
- `required` — must be provided.
- `string` — must be text.
- `max:500` — must not exceed 500.

**Example Request Body:**
```json
{
    "reason": "Company requested early termination due to relocation"
}
```

**Actual Success Response(s):**

*{ 200 OK — active to terminated }*
```json
{
    "status": "success",
    "message": "Contract terminated successfully.",
    "data": {
        "id": 20,
        "contract_number": "CTR-2026-000001",
        "company": {
            "id": 57,
            "name": "Prof. Diana Abernathy",
            "email": "collins.madonna@example.com"
        },
        "created_by": {
            "id": 57,
            "name": "Prof. Diana Abernathy"
        },
        "approved_by": {
            "id": null,
            "name": null
        },
        "signed_by": {
            "id": null,
            "name": null
        },
        "start_date": "2026-08-20",
        "end_date": "2026-09-20",
        "billing_cycle": "monthly",
        "visits_allowed": 10,
        "visits_consumed": 0,
        "remaining_visits": 10,
        "total_amount": "1000.00",
        "currency": "SAR",
        "status": "terminated",
        "status_label": "Terminated",
        "auto_renew": false,
        "pdf_path": null,
        "signed_pdf_path": null,
        "signed_at": null,
        "approved_at": null,
        "terminated_at": "2026-08-20T12:09:44+00:00",
        "terminated_reason": "Company requested early termination due to relocation",
        "notes": null,
        "branches": [],
        "services": [],
        "signatures": [],
        "renewal_requests": [],
        "created_at": "2026-08-20T12:09:44+00:00",
        "updated_at": "2026-08-20T12:09:44+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 - draft contract cannot be terminated (only active can) }*
```json
{
    "status": "fail",
    "message": "Contract cannot be terminated in its current state.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 - validation error (reason required, via TerminateContractRequest) }*
```json
{
    "status": "fail",
    "message": "The reason field is required.",
    "data": null
}
```

*{ 404 Not Found — 404 - not found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** No further job orders can be placed against it; existing in-flight orders are unaffected.

---

#### Delete Contract

**What this does:** Permanently deletes a contract.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contracts/:contract` |
| **Route name** | `admin.contracts.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contracts.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `contract` — Contract ID — seeded example: `1`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — draft contract deleted }*
```json
{
    "status": "success",
    "message": "Contract deleted successfully.",
    "data": null
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 - active contract cannot be deleted }*
```json
{
    "status": "fail",
    "message": "Contract cannot be deleted in its current state.",
    "data": null
}
```

*{ 404 Not Found — 404 - not found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** It no longer appears in `index`.

---

#### Delete Bulk

**What this does:** Deletes multiple contracts in one call by an array of ids.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contracts/bulk` |
| **Route name** | `admin.contracts.bulk.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contracts.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — both deletable contracts deleted }*
```json
{
    "status": "success",
    "message": "Contract deleted successfully.",
    "data": null
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 - all-or-nothing: one active contract in the batch rejects the whole request }*
```json
{
    "status": "fail",
    "message": "Contract cannot be deleted in its current state.",
    "data": null
}
```

*{ 404 Not Found — 404 - one of the requested ids does not exist }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 - validation error (empty ids array) }*
```json
{
    "status": "fail",
    "message": "Please select at least one item.",
    "data": null
}
```

**What happens next:** Re-fetch the index to confirm — deleted contracts no longer appear.

---

## 09. Wallets

#### List All Wallets

**What this does:** Returns a paginated, filterable, searchable list of wallets.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/wallets?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.wallets.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `wallets.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `401 Unauthorized` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — list wallets }*
```json
{
    "status": "success",
    "message": "Wallets retrieved successfully",
    "data": {
        "data": [
            {
                "id": 1,
                "user": {
                    "id": 2,
                    "name": "Sara Al-Fahad",
                    "email": "cristopher.ullrich@example.net",
                    "user_type": "individual"
                },
                "balance": "350.75",
                "currency": "SAR",
                "created_at": "2026-08-20 12:10:23"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/wallets?page=1",
            "last": "http://localhost/api/v1/admin/wallets?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/wallets?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/wallets",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

*{ 200 OK — filtered by min_balance }*
```json
{
    "status": "success",
    "message": "Wallets retrieved successfully",
    "data": {
        "data": [
            {
                "id": 1,
                "user": {
                    "id": 2,
                    "name": "Sara Al-Fahad",
                    "email": "cristopher.ullrich@example.net",
                    "user_type": "individual"
                },
                "balance": "350.75",
                "currency": "SAR",
                "created_at": "2026-08-20 12:10:23"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/wallets?page=1",
            "last": "http://localhost/api/v1/admin/wallets?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/wallets?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/wallets",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

**Actual Error Response(s):**

*{ 401 Unauthorized — 401 Unauthenticated }*
```json
{
    "status": "fail",
    "message": "Unauthenticated, you have to login first",
    "data": null
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### Show Wallet Details

**What this does:** Returns full details for one wallet.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/wallets/:id` |
| **Route name** | `admin.wallets.show` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `wallets.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — ⚠️ **no real record exists in the seeded database** (confirmed empty — see [SEED_DATA.md](SEED_DATA.md)); placeholder `1` will 404/422 until you create one

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — wallet with transactions }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 1,
        "user": {
            "id": 2,
            "name": "Sara Al-Fahad",
            "email": "cristopher.ullrich@example.net",
            "user_type": "individual"
        },
        "balance": "350.75",
        "currency": "SAR",
        "created_at": "2026-08-20 12:10:23",
        "transactions": [
            {
                "id": 1,
                "type": "refund_credit",
                "type_label": "Refund from cancelled order",
                "amount": "100.00",
                "balance_after": "350.75",
                "status": "completed",
                "notes": "Refund from cancelled order",
                "related_order_id": null,
                "related_withdraw_request_id": null,
                "created_by": "Crystel Eichmann",
                "created_at": "2026-08-20 12:10:23"
            },
            {
                "id": 2,
                "type": "order_debit",
                "type_label": "Wallet-funded booking",
                "amount": "50.00",
                "balance_after": "300.75",
                "status": "completed",
                "notes": "Wallet balance applied to order",
                "related_order_id": null,
                "related_withdraw_request_id": null,
                "created_by": "Sara Al-Fahad",
                "created_at": "2026-08-20 12:10:23"
            }
        ],
        "updated_at": "2026-08-20 12:10:23"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use `update` to modify it, or `destroy` to remove it.

---

#### Block Refund Wallet

**What this does:** Admin-triggered equivalent of the automatic refund-block path — records a `$0` failed `reversal` transaction with a reason, for cases needing manual intervention instead of the automatic order-cancel refund.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/wallets/:id/block-refund` |
| **Route name** | `admin.wallets.block-refund` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `wallets.block-refund` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — ⚠️ **no real record exists in the seeded database** (confirmed empty — see [SEED_DATA.md](SEED_DATA.md)); placeholder `1` will 404/422 until you create one

**Payload:**
Send as `application/json`.

**Field documentation:**
### `order_id`
- **Description:** Order
- **Type:** `integer`
- **Required:** required
- **Example:** `1`
- **Validation rules:** `required|integer|exists:orders,id`
- `required` — must be provided.
- `integer` — must be a whole number.
- `exists:orders,id` — must reference an existing record (orders, id).
### `reason`
- **Description:** Reason
- **Type:** `string`
- **Required:** required
- **Example:** `Manual adjustment by admin.`
- **Validation rules:** `required|string|max:500`
- `required` — must be provided.
- `string` — must be text.
- `max:500` — must not exceed 500.

**Example Request Body:**
```json
{
    "order_id": 1,
    "reason": "Manual adjustment by admin."
}
```

**Actual Error Response(s):**

*{ 404 Not Found — BUG - realistic order_id (integer id) never matches, always 404s (see bug report) }*
```json
{
    "status": "fail",
    "message": "Refund blocked — order not eligible",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - order_id does not exist }*
```json
{
    "status": "fail",
    "message": "The selected order does not exist.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - missing reason }*
```json
{
    "status": "fail",
    "message": "The Reason field is required.",
    "data": null
}
```

*{ 404 Not Found — wallet not found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use for order/wallet combinations the automatic `RefundService` rejected (e.g. company job orders, which are never auto-refunded to a wallet).

---

#### Credit Wallet

**What this does:** Manually credits a wallet by `amount`, recording a `reason` (`manual_credit` transaction type).

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/wallets/:id/credit` |
| **Route name** | `admin.wallets.credit` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `wallets.credit` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — ⚠️ **no real record exists in the seeded database** (confirmed empty — see [SEED_DATA.md](SEED_DATA.md)); placeholder `1` will 404/422 until you create one

**Payload:**
Send as `application/json`.

**Field documentation:**
### `amount`
- **Description:** Amount
- **Type:** `number`
- **Required:** required
- **Example:** `10`
- **Validation rules:** `required|numeric|min:0.01|max:999999.99`
- `required` — must be provided.
- `numeric` — must be numeric.
- `min:0.01` — must be at least 0.01.
- `max:999999.99` — must not exceed 999999.99.
### `reason`
- **Description:** Reason
- **Type:** `string`
- **Required:** optional
- **Example:** `Manual adjustment by admin.`
- **Validation rules:** `sometimes|nullable|string|max:500`
- `sometimes` — validated only when the field is present.
- `nullable` — may be null.
- `string` — must be text.
- `max:500` — must not exceed 500.

**Example Request Body:**
```json
{
    "amount": 75.5,
    "reason": "Goodwill credit for delayed service"
}
```

**Actual Success Response(s):**

*{ 200 OK — credited }*
```json
{
    "status": "success",
    "message": "Wallet credited successfully",
    "data": {
        "id": 1,
        "user_id": 2,
        "balance": "426.25",
        "currency": "SAR"
    }
}
```

*{ 200 OK — ATTEMPT - credit a locked wallet (see bug report re: is_locked not checked) }*
```json
{
    "status": "success",
    "message": "Wallet credited successfully",
    "data": {
        "id": 4,
        "user_id": 6,
        "balance": "200.00",
        "currency": "SAR"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error - negative amount }*
```json
{
    "status": "fail",
    "message": "Amount must be at least 0.01.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - zero amount }*
```json
{
    "status": "fail",
    "message": "Amount must be at least 0.01.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - missing amount }*
```json
{
    "status": "fail",
    "message": "Please enter the amount.",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — ATTEMPT - credit by user_id when no wallet row exists (see bug report) }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Reflected immediately in `GET /admin/wallets/{id}` and the owner's own wallet-balance endpoint.

---

#### Lock Wallet

**What this does:** Locks a wallet — blocks both order payment (`validateWalletUsage`) and withdrawal (`validateWithdrawal`) with a 422 `wallet_locked` until unlocked.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/wallets/:id/lock` |
| **Route name** | `admin.wallets.lock` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `wallets.lock` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — ⚠️ **no real record exists in the seeded database** (confirmed empty — see [SEED_DATA.md](SEED_DATA.md)); placeholder `4` will 404/422 until you create one

**Payload:**
No fields. Send an empty JSON object `{}`.

**Example Request Body:**
```json
[]
```

**Actual Success Response(s):**

*{ 200 OK — locked }*
```json
{
    "status": "success",
    "message": "Your wallet is currently locked. Please contact support.",
    "data": {
        "id": 4,
        "user_id": 6,
        "balance": "150.00",
        "currency": "SAR",
        "is_locked": true,
        "created_at": "2026-08-20T12:10:23.000000Z",
        "updated_at": "2026-08-20T12:10:23.000000Z"
    }
}
```

*{ 200 OK — lock an already-locked wallet (no guard, idempotent) }*
```json
{
    "status": "success",
    "message": "Your wallet is currently locked. Please contact support.",
    "data": {
        "id": 4,
        "user_id": 6,
        "balance": "150.00",
        "currency": "SAR",
        "is_locked": true,
        "created_at": "2026-08-20T12:10:23.000000Z",
        "updated_at": "2026-08-20T12:10:23.000000Z"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Call `admin.wallets.unlock` to restore normal use.

---

#### Transactions Wallet

**What this does:** Returns the full transaction ledger for one specific wallet (admin view — any user's wallet, not just the caller's own).

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/wallets/:id/transactions` |
| **Route name** | `admin.wallets.transactions` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `wallets.transactions` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — ⚠️ **no real record exists in the seeded database** (confirmed empty — see [SEED_DATA.md](SEED_DATA.md)); placeholder `1` will 404/422 until you create one

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — list transactions }*
```json
{
    "status": "success",
    "message": "Transactions retrieved successfully",
    "data": {
        "data": [
            {
                "id": 1,
                "type": "refund_credit",
                "type_label": "Refund from cancelled order",
                "amount": "100.00",
                "balance_after": "350.75",
                "status": "completed",
                "notes": "Refund from cancelled order",
                "related_order_id": null,
                "related_withdraw_request_id": null,
                "created_by": "Crystel Eichmann",
                "created_at": "2026-08-20 12:10:23"
            },
            {
                "id": 2,
                "type": "order_debit",
                "type_label": "Wallet-funded booking",
                "amount": "50.00",
                "balance_after": "300.75",
                "status": "completed",
                "notes": "Wallet balance applied to order",
                "related_order_id": null,
                "related_withdraw_request_id": null,
                "created_by": "Sara Al-Fahad",
                "created_at": "2026-08-20 12:10:23"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/wallets/1/transactions?page=1",
            "last": "http://localhost/api/v1/admin/wallets/1/transactions?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/wallets/1/transactions?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/wallets/1/transactions",
            "per_page": 20,
            "to": 2,
            "total": 2
        }
    }
}
```

*{ 200 OK — filtered by type=order_debit }*
```json
{
    "status": "success",
    "message": "Transactions retrieved successfully",
    "data": {
        "data": [
            {
                "id": 2,
                "type": "order_debit",
                "type_label": "Wallet-funded booking",
                "amount": "50.00",
                "balance_after": "300.75",
                "status": "completed",
                "notes": "Wallet balance applied to order",
                "related_order_id": null,
                "related_withdraw_request_id": null,
                "created_by": "Sara Al-Fahad",
                "created_at": "2026-08-20 12:10:23"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/wallets/1/transactions?page=1",
            "last": "http://localhost/api/v1/admin/wallets/1/transactions?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/wallets/1/transactions?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/wallets/1/transactions",
            "per_page": 20,
            "to": 1,
            "total": 1
        }
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error - invalid type }*
```json
{
    "status": "fail",
    "message": "The selected type is invalid.",
    "data": null
}
```

**What happens next:** Cross-reference `related_order_id`/`related_withdraw_request_id` with the Requests/Jobs and Statuses sections.

---

#### Unlock Wallet

**What this does:** Reverses `admin.wallets.lock` — the wallet can be used for payment/withdrawal again.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/wallets/:id/unlock` |
| **Route name** | `admin.wallets.unlock` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `wallets.unlock` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — ⚠️ **no real record exists in the seeded database** (confirmed empty — see [SEED_DATA.md](SEED_DATA.md)); placeholder `4` will 404/422 until you create one

**Payload:**
No fields. Send an empty JSON object `{}`.

**Example Request Body:**
```json
[]
```

**Actual Success Response(s):**

*{ 200 OK — unlocked }*
```json
{
    "status": "success",
    "message": "Wallet has been unlocked successfully.",
    "data": {
        "id": 4,
        "user_id": 6,
        "balance": "150.00",
        "currency": "SAR",
        "is_locked": false,
        "created_at": "2026-08-20T12:10:23.000000Z",
        "updated_at": "2026-08-20T12:10:23.000000Z"
    }
}
```

*{ 200 OK — unlock an already-unlocked wallet (idempotent) }*
```json
{
    "status": "success",
    "message": "Wallet has been unlocked successfully.",
    "data": {
        "id": 4,
        "user_id": 6,
        "balance": "150.00",
        "currency": "SAR",
        "is_locked": false,
        "created_at": "2026-08-20T12:10:23.000000Z",
        "updated_at": "2026-08-20T12:10:23.000000Z"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Confirm with `GET /admin/wallets/{id}`.

---

#### Zero Out Wallet

**What this does:** Forces a wallet's balance to zero, recording a reason.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/wallets/:id/zero-out` |
| **Route name** | `admin.wallets.zero-out` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `wallets.zero-out` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — ⚠️ **no real record exists in the seeded database** (confirmed empty — see [SEED_DATA.md](SEED_DATA.md)); placeholder `2` will 404/422 until you create one

**Payload:**
Send as `application/json`.

**Field documentation:**
### `reason`
- **Description:** Reason
- **Type:** `string`
- **Required:** required
- **Example:** `Manual adjustment by admin.`
- **Validation rules:** `required|string|max:500`
- `required` — must be provided.
- `string` — must be text.
- `max:500` — must not exceed 500.

**Example Request Body:**
```json
{
    "reason": "Fraudulent balance under investigation"
}
```

**Actual Success Response(s):**

*{ 200 OK — zeroed }*
```json
{
    "status": "success",
    "message": "Wallet balance reset to zero successfully",
    "data": {
        "id": 2,
        "user_id": 4,
        "balance": "0.00",
        "currency": "SAR"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error - already zero }*
```json
{
    "status": "fail",
    "message": "Wallet balance is already zero",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - missing reason }*
```json
{
    "status": "fail",
    "message": "The Reason field is required.",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Any subsequent order-payment or withdrawal attempt against this wallet will fail insufficient-balance checks until it's credited again.

---

## 10. Invoices

#### List All Invoices

**What this does:** Returns a paginated, filterable, searchable list of invoices.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/invoices?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.invoices.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `invoices.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `401 Unauthorized` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Invoices retrieved successfully.",
    "data": {
        "data": [
            {
                "id": 1,
                "invoice_number": "INV-2026-000001",
                "contract_number": "CTR-2026-000001",
                "company": {
                    "id": 75,
                    "name": "Amber White"
                },
                "sequence_no": 1,
                "total_invoices": null,
                "amount_due": "500.00",
                "currency": "SAR",
                "status": "issued",
                "issue_date": "2026-08-20",
                "due_date": "2026-09-04"
            },
            {
                "id": 2,
                "invoice_number": "INV-2026-000002",
                "contract_number": "CTR-2026-000001",
                "company": {
                    "id": 75,
                    "name": "Amber White"
                },
                "sequence_no": 2,
                "total_invoices": null,
                "amount_due": "500.00",
                "currency": "SAR",
                "status": "paid",
                "issue_date": "2026-08-20",
                "due_date": "2026-09-04"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/invoices?page=1",
            "last": "http://localhost/api/v1/admin/invoices?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/invoices?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/invoices",
            "per_page": 15,
            "to": 2,
            "total": 2
        }
    }
}
```

*{ 200 OK — filtered by status=paid }*
```json
{
    "status": "success",
    "message": "Invoices retrieved successfully.",
    "data": {
        "data": [
            {
                "id": 2,
                "invoice_number": "INV-2026-000002",
                "contract_number": "CTR-2026-000001",
                "company": {
                    "id": 75,
                    "name": "Amber White"
                },
                "sequence_no": 2,
                "total_invoices": null,
                "amount_due": "500.00",
                "currency": "SAR",
                "status": "paid",
                "issue_date": "2026-08-20",
                "due_date": "2026-09-04"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/invoices?page=1",
            "last": "http://localhost/api/v1/admin/invoices?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/invoices?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/invoices",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

**Actual Error Response(s):**

*{ 401 Unauthorized — 401 Unauthenticated }*
```json
{
    "status": "fail",
    "message": "Unauthenticated, you have to login first",
    "data": null
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### Show Invoice Details

**What this does:** Returns full details for one invoice.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/invoices/:invoice` |
| **Route name** | `admin.invoices.show` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `invoices.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `invoice` — Invoice ID — ⚠️ **no real record exists in the seeded database** (confirmed empty — see [SEED_DATA.md](SEED_DATA.md)); placeholder `3` will 404/422 until you create one

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Invoice retrieved successfully.",
    "data": {
        "id": 3,
        "invoice_number": "INV-2026-000001",
        "contract": {
            "id": 30,
            "contract_number": "CTR-2026-000001",
            "total_amount": "1000.00",
            "total_invoices_count": null
        },
        "company": {
            "id": 77,
            "name": "Britney Willms"
        },
        "sequence_no": 1,
        "period_start": "2026-08-01",
        "period_end": "2026-08-31",
        "amount_due": "500.00",
        "amount_paid": "0.00",
        "currency": "SAR",
        "status": "issued",
        "issue_date": "2026-08-20",
        "due_date": "2026-09-04",
        "pdf_path": null,
        "line_items": [
            {
                "id": 1,
                "description": "Monthly installment",
                "amount": "500.00"
            }
        ],
        "created_at": "2026-08-20T12:09:45+00:00"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use `update` to modify it, or `destroy` to remove it.

---

#### Cancel Invoice

**What this does:** Cancels a system-generated invoice.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/invoices/:id/cancel` |
| **Route name** | `admin.invoices.cancel` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `invoices.cancel` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — ⚠️ **no real record exists in the seeded database** (confirmed empty — see [SEED_DATA.md](SEED_DATA.md)); placeholder `1` will 404/422 until you create one

**Payload:**
Example payload is included in the request body. No FormRequest validation rules were detected.
### `key`
- **Description:** Key
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `not specified`
- `not specified` — no validation rule was declared.

**Example Request Body:**
```json
{
    "key": "value"
}
```

**Actual Success Response(s):**

*{ 200 OK — issued invoice cancelled }*
```json
{
    "status": "success",
    "message": "Invoice cancelled successfully.",
    "data": null
}
```

*{ 200 OK — overdue invoice cancelled }*
```json
{
    "status": "success",
    "message": "Invoice cancelled successfully.",
    "data": null
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 - paid invoice cannot be cancelled (money already changed hands) }*
```json
{
    "status": "fail",
    "message": "Invoice cannot be cancelled in its current state.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 - already cancelled invoice cannot be cancelled again }*
```json
{
    "status": "fail",
    "message": "Invoice cannot be cancelled in its current state.",
    "data": null
}
```

*{ 404 Not Found — 404 - not found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** The invoice no longer counts toward the company's outstanding balance.

---

## 11. Notifications (Admin Send)

#### List All Notifications

**What this does:** Returns a paginated, filterable, searchable list of notifications.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/notifications?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.notifications.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `notifications.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`
- `Authorization: Bearer {token}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — list notifications }*
```json
{
    "status": "success",
    "message": "Notifications retrieved successfully",
    "data": {
        "current_page": 1,
        "data": [
            {
                "id": "4da51c94-964f-454b-bef2-d01caa25e3b2",
                "admin_notification_id": null,
                "notifiable_type": "App\\Models\\User",
                "notifiable_id": 87,
                "type": "App\\Notifications\\GeneralNotification",
                "data": {
                    "notification_type": "general",
                    "notify_id": "broadcast",
                    "message": "The platform will be down for maintenance tonight.",
                    "payload": {
                        "title": "Platform Maintenance",
                        "channels": null,
                        "meta": {
                            "notification_type": "general"
                        }
                    }
                },
                "read_at": null,
                "created_at": "2026-08-20T12:09:45.000000Z",
                "updated_at": "2026-08-20T12:09:45.000000Z"
            },
            {
                "id": "74069fb7-bcc4-469e-9cb2-3099759d6c60",
                "admin_notification_id": null,
                "notifiable_type": "App\\Models\\User",
                "notifiable_id": 94,
                "type": "App\\Notifications\\GeneralNotification",
                "data": {
                    "notification_type": "general",
                    "notify_id": "broadcast",
                    "message": "Please update your profile information.",
                    "payload": {
                        "title": "Account Update",
                        "channels": null,
                        "meta": {
                            "notification_type": "general"
                        }
                    }
                },
                "read_at": null,
                "created_at": "2026-08-20T12:09:45.000000Z",
                "updated_at": "2026-08-20T12:09:45.000000Z"
            },
            {
                "id": "776af4d9-1319-4911-8690-348b874e2587",
                "admin_notification_id": null,
                "notifiable_type": "App\\Models\\User",
                "notifiable_id": 92,
                "type": "App\\Notifications\\GeneralNotification",
                "data": {
                    "notification_type": "general",
                    "notify_id": "broadcast",
                    "message": "The platform will be down for maintenance tonight.",
                    "payload": {
                        "title": "Platform Maintenance",
                        "channels": null,
                        "meta": {
                            "notification_type": "general"
                        }
                    }
                },
                "read_at": null,
                "created_at": "2026-08-20T12:09:45.000000Z",
                "updated_at": "2026-08-20T12:09:45.000000Z"
            },
            {
                "id": "787a25ec-0aee-45f6-adf1-173689ee94b0",
                "admin_notification_id": null,
                "notifiable_type": "App\\Models\\User",
                "notifiable_id": 89,
                "type": "App\\Notifications\\GeneralNotification",
                "data": {
                    "notification_type": "general",
                    "notify_id": "broadcast",
                    "message": "The platform will be down for maintenance tonight.",
                    "payload": {
                        "title": "Platform Maintenance",
                        "channels": null,
                        "meta": {
                            "notification_type": "general"
                        }
                    }
                },
                "read_at": null,
                "created_at": "2026-08-20T12:09:45.000000Z",
                "updated_at": "2026-08-20T12:09:45.000000Z"
            },
            {
                "id": "7f6c50da-93d5-457a-8d6c-e4cbe2060489",
                "admin_notification_id": null,
                "notifiable_type": "App\\Models\\User",
                "notifiable_id": 94,
                "type": "App\\Notifications\\GeneralNotification",
                "data": {
                    "notification_type": "general",
                    "notify_id": "broadcast",
                    "message": "The platform will be down for maintenance tonight.",
                    "payload": {
                        "title": "Platform Maintenance",
                        "channels": null,
                        "meta": {
                            "notification_type": "general"
                        }
                    }
                },
                "read_at": null,
                "created_at": "2026-08-20T12:09:45.000000Z",
                "updated_at": "2026-08-20T12:09:45.000000Z"
            },
            {
                "id": "a146e7fb-5abf-4937-98fb-a165004856ce",
                "admin_notification_id": null,
                "notifiable_type": "App\\Models\\User",
                "notifiable_id": 88,
                "type": "App\\Notifications\\GeneralNotification",
                "data": {
                    "notification_type": "general",
                    "notify_id": "broadcast",
                    "message": "The platform will be down for maintenance tonight.",
                    "payload": {
                        "title": "Platform Maintenance",
                        "channels": null,
                        "meta": {
                            "notification_type": "general"
                        }
                    }
                },
                "read_at": null,
                "created_at": "2026-08-20T12:09:45.000000Z",
                "updated_at": "2026-08-20T12:09:45.000000Z"
            },
            {
                "id": "a5e3be08-4757-4690-94db-a55247fd326c",
                "admin_notification_id": null,
                "notifiable_type": "App\\Models\\User",
                "notifiable_id": 93,
                "type": "App\\Notifications\\GeneralNotification",
                "data": {
                    "notification_type": "general",
                    "notify_id": "broadcast",
                    "message": "Please update your profile information.",
                    "payload": {
                        "title": "Account Update",
                        "channels": null,
                        "meta": {
                            "notification_type": "general"
                        }
                    }
                },
                "read_at": null,
                "created_at": "2026-08-20T12:09:45.000000Z",
                "updated_at": "2026-08-20T12:09:45.000000Z"
            },
            {
                "id": "c631e616-9ecb-41ba-a83e-c2a4947f2aae",
                "admin_notification_id": null,
                "notifiable_type": "App\\Models\\User",
                "notifiable_id": 90,
                "type": "App\\Notifications\\GeneralNotification",
                "data": {
                    "notification_type": "general",
                    "notify_id": "broadcast",
                    "message": "The platform will be down for maintenance tonight.",
                    "payload": {
                        "title": "Platform Maintenance",
                        "channels": null,
                        "meta": {
                            "notification_type": "general"
                        }
                    }
                },
                "read_at": null,
                "created_at": "2026-08-20T12:09:45.000000Z",
                "updated_at": "2026-08-20T12:09:45.000000Z"
            },
            {
                "id": "c6ec7f0d-933c-4fdb-8431-245015e9509e",
                "admin_notification_id": null,
                "notifiable_type": "App\\Models\\User",
                "notifiable_id": 93,
                "type": "App\\Notifications\\GeneralNotification",
                "data": {
                    "notification_type": "general",
                    "notify_id": "broadcast",
                    "message": "The platform will be down for maintenance tonight.",
                    "payload": {
                        "title": "Platform Maintenance",
                        "channels": null,
                        "meta": {
                            "notification_type": "general"
                        }
                    }
                },
                "read_at": null,
                "created_at": "2026-08-20T12:09:45.000000Z",
                "updated_at": "2026-08-20T12:09:45.000000Z"
            },
            {
                "id": "f61b07bc-0384-486a-95a2-0a8d21f55251",
                "admin_notification_id": null,
                "notifiable_type": "App\\Models\\User",
                "notifiable_id": 91,
                "type": "App\\Notifications\\GeneralNotification",
                "data": {
                    "notification_type": "general",
                    "notify_id": "broadcast",
                    "message": "The platform will be down for maintenance tonight.",
                    "payload": {
                        "title": "Platform Maintenance",
                        "channels": null,
                        "meta": {
                            "notification_type": "general"
                        }
                    }
                },
                "read_at": null,
                "created_at": "2026-08-20T12:09:45.000000Z",
                "updated_at": "2026-08-20T12:09:45.000000Z"
            }
        ],
        "first_page_url": "http://localhost/api/v1/admin/notifications?page=1",
        "from": 1,
        "last_page": 1,
        "last_page_url": "http://localhost/api/v1/admin/notifications?page=1",
        "links": [
            {
                "url": null,
                "label": "&laquo; Previous",
                "page": null,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/notifications?page=1",
                "label": "1",
                "page": 1,
                "active": true
            },
            {
                "url": null,
                "label": "Next &raquo;",
                "page": null,
                "active": false
            }
        ],
        "next_page_url": null,
        "path": "http://localhost/api/v1/admin/notifications",
        "per_page": 15,
        "prev_page_url": null,
        "to": 10,
        "total": 10
    }
}
```

*{ 200 OK — list notifications with per_page }*
```json
{
    "status": "success",
    "message": "Notifications retrieved successfully",
    "data": {
        "current_page": 1,
        "data": [
            {
                "id": "4da51c94-964f-454b-bef2-d01caa25e3b2",
                "admin_notification_id": null,
                "notifiable_type": "App\\Models\\User",
                "notifiable_id": 87,
                "type": "App\\Notifications\\GeneralNotification",
                "data": {
                    "notification_type": "general",
                    "notify_id": "broadcast",
                    "message": "The platform will be down for maintenance tonight.",
                    "payload": {
                        "title": "Platform Maintenance",
                        "channels": null,
                        "meta": {
                            "notification_type": "general"
                        }
                    }
                },
                "read_at": null,
                "created_at": "2026-08-20T12:09:45.000000Z",
                "updated_at": "2026-08-20T12:09:45.000000Z"
            }
        ],
        "first_page_url": "http://localhost/api/v1/admin/notifications?page=1",
        "from": 1,
        "last_page": 10,
        "last_page_url": "http://localhost/api/v1/admin/notifications?page=10",
        "links": [
            {
                "url": null,
                "label": "&laquo; Previous",
                "page": null,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/notifications?page=1",
                "label": "1",
                "page": 1,
                "active": true
            },
            {
                "url": "http://localhost/api/v1/admin/notifications?page=2",
                "label": "2",
                "page": 2,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/notifications?page=3",
                "label": "3",
                "page": 3,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/notifications?page=4",
                "label": "4",
                "page": 4,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/notifications?page=5",
                "label": "5",
                "page": 5,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/notifications?page=6",
                "label": "6",
                "page": 6,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/notifications?page=7",
                "label": "7",
                "page": 7,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/notifications?page=8",
                "label": "8",
                "page": 8,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/notifications?page=9",
                "label": "9",
                "page": 9,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/notifications?page=10",
                "label": "10",
                "page": 10,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/notifications?page=2",
                "label": "Next &raquo;",
                "page": 2,
                "active": false
            }
        ],
        "next_page_url": "http://localhost/api/v1/admin/notifications?page=2",
        "path": "http://localhost/api/v1/admin/notifications",
        "per_page": 1,
        "prev_page_url": null,
        "to": 1,
        "total": 10
    }
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### Create New Notification

**What this does:** Sends a notification either to every user (`target: broadcast`) or to a specific list (`target: targeted`, `user_ids`).

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/notifications/send` |
| **Route name** | `admin.notifications.create` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `notifications.create` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`
- `Authorization: Bearer {token}`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `title`
- **Description:** Title
- **Type:** `string`
- **Required:** required
- **Example:** `Example Title`
- **Validation rules:** `required|string|max:200`
- `required` — must be provided.
- `string` — must be text.
- `max:200` — must not exceed 200.
### `body`
- **Description:** Message Body
- **Type:** `string`
- **Required:** required
- **Example:** `Example message body text.`
- **Validation rules:** `required|string|max:1000`
- `required` — must be provided.
- `string` — must be text.
- `max:1000` — must not exceed 1000.
### `target`
- **Description:** Target
- **Type:** `string`
- **Required:** required
- **Example:** `broadcast`
- **Validation rules:** `required|in:broadcast,targeted`
- `required` — must be provided.
- `in:broadcast,targeted` — must be one of: broadcast, targeted.
### `user_ids`
- **Description:** User IDs
- **Type:** `array`
- **Required:** conditional
- **Example:** `[1]`
- **Validation rules:** `required_if:target,targeted|array`
- `required_if:target,targeted` — required when target, targeted.
- `array` — must be an array.
### `user_ids.*`
- **Description:** User ids item
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `integer|exists:users,id`
- `integer` — must be a whole number.
- `exists:users,id` — must reference an existing record (users, id).

**Example Request Body:**
```json
{
    "title": "Platform Maintenance",
    "body": "The platform will be down for maintenance tonight.",
    "target": "broadcast"
}
```

**Actual Success Response(s):**

*{ 200 OK — broadcast notification }*
```json
{
    "status": "success",
    "message": "Notification sent successfully",
    "data": {
        "recipients_count": 8
    }
}
```

*{ 200 OK — targeted notification }*
```json
{
    "status": "success",
    "message": "Notification sent successfully",
    "data": {
        "recipients_count": 2
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error - targeted without user_ids }*
```json
{
    "status": "fail",
    "message": "The User IDs field is required when Target is targeted.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - invalid target enum value }*
```json
{
    "status": "fail",
    "message": "Invalid notification target.",
    "data": null
}
```

**What happens next:** Recipients see it via their own `GET /notifications` (or role-specific notification list).

---

#### Bulk Delete Notifications

**What this does:** Deletes multiple sent notifications in one call by an array of ids. Unlike every other `*/bulk` endpoint in this file, `notifications.id` (`DatabaseNotification`) is a **UUID**, not an auto-increment integer, so this route has its own `BulkDeleteNotificationRequest` instead of reusing the shared `BulkDeleteRequest`. All-or-nothing: if any id in the array doesn't exist, the whole batch is rejected with `404` and nothing is deleted (`NotificationCommandService::bulkDestroy`, wrapped in a `DB::transaction`).

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/notifications/bulk` |
| **Route name** | `admin.notifications.bulk.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active` (no RBAC permission gate on this route — same as `notifications.create`/`notifications.index` in this section) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`
- `Authorization: Bearer {token}`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `ids`
- **Description:** IDs
- **Type:** `array`
- **Required:** required
- **Example:** `["b7e2c2b0-1a4b-4b3e-8e9f-2c1a1a2b3c4d"]`
- **Validation rules:** `required|array|min:1|max:100`
- `required` — must be provided.
- `array` — must be an array.
- `min:1` — at least one id.
- `max:100` — at most 100 ids per call.
### `ids.*`
- **Description:** ID
- **Type:** `string`
- **Required:** required
- **Example:** `b7e2c2b0-1a4b-4b3e-8e9f-2c1a1a2b3c4d`
- **Validation rules:** `required|string|uuid|distinct`
- `required` — must be provided.
- `string` — must be text.
- `uuid` — must be a valid UUID (not an integer id, unlike other bulk-delete endpoints).
- `distinct` — no duplicate ids within the array.

**Example Request Body:**
```json
{
    "ids": [
        "b7e2c2b0-1a4b-4b3e-8e9f-2c1a1a2b3c4d",
        "d3f1a9c8-5e6f-4a1b-9c2d-7f8e9a0b1c2d"
    ]
}
```

**Example Response** *(not captured from a live run — no server was available when this endpoint was added; shape follows the `json(null, ...)` helper used by every other bulk-delete endpoint in this file)*:

*{ 200 OK — all ids existed }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 404 Not Found — one or more ids didn't exist (whole batch rejected) }*
```json
{
    "status": "fail",
    "message": "Some selected items were not found",
    "data": null
}
```

*{ 422 Unprocessable Entity — empty/invalid ids array }*
```json
{
    "status": "fail",
    "message": "The ids field is required.",
    "data": null
}
```

**What happens next:** The deleted notifications no longer appear in `GET /admin/notifications` (§12 List All Notifications above) or in the recipients' own notification lists.

---

## 12. Conversations & Contact Messages (Oversight)

#### List All Contact messages

**What this does:** Returns a paginated, filterable, searchable list of contact messages.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contact-messages?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_read]=0` |
| **Route name** | `admin.contact-messages.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contact-messages.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_read]` — Filter by read status: 0 or 1 (optional)

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "contact_messages": [
            {
                "id": 1,
                "name": "John Doe",
                "email": "john@example.com",
                "phone": "1000000001",
                "subject": "Question about pricing",
                "is_read": false,
                "replied_at": null,
                "created_at": "2026-08-20 14:19:15"
            },
            {
                "id": 2,
                "name": "Jane Roe",
                "email": "jane@example.com",
                "phone": "1000000002",
                "subject": "Complaint",
                "is_read": false,
                "replied_at": null,
                "created_at": "2026-08-20 14:19:15"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/contact-messages?page=1",
            "last": "http://localhost/api/v1/admin/contact-messages?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/contact-messages?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/contact-messages",
            "per_page": 15,
            "to": 2,
            "total": 2
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "contact_messages": [
            {
                "id": 1,
                "name": "John Doe",
                "email": "john@example.com",
                "phone": "1000000001",
                "subject": "Question about pricing",
                "is_read": false,
                "replied_at": null,
                "created_at": "2026-08-20 14:20:13"
            },
            {
                "id": 2,
                "name": "Jane Roe",
                "email": "jane@example.com",
                "phone": "1000000002",
                "subject": "Complaint",
                "is_read": false,
                "replied_at": null,
                "created_at": "2026-08-20 14:20:13"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/contact-messages?page=1",
            "last": "http://localhost/api/v1/admin/contact-messages?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/contact-messages?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/contact-messages",
            "per_page": 15,
            "to": 2,
            "total": 2
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "contact_messages": [
            {
                "id": 1,
                "name": "John Doe",
                "email": "john@example.com",
                "phone": "1000000001",
                "subject": "Question about pricing",
                "is_read": false,
                "replied_at": null,
                "created_at": "2026-08-20 14:24:24"
            },
            {
                "id": 2,
                "name": "Jane Roe",
                "email": "jane@example.com",
                "phone": "1000000002",
                "subject": "Complaint",
                "is_read": false,
                "replied_at": null,
                "created_at": "2026-08-20 14:24:24"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/contact-messages?page=1",
            "last": "http://localhost/api/v1/admin/contact-messages?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/contact-messages?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/contact-messages",
            "per_page": 15,
            "to": 2,
            "total": 2
        }
    }
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### List All Conversations

**What this does:** Returns a paginated, filterable, searchable list of conversations.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/conversations?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.conversations.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `conversations.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "conversations": [
            {
                "id": 1,
                "customer": {
                    "id": 3,
                    "name": "Davin Gibson",
                    "email": "rbednar@example.org"
                },
                "subject": "Need help with my order",
                "status": "Open",
                "last_message": "Hello, when will my technician arrive?",
                "created_at": "2026-08-20 14:19:16",
                "closed_at": null
            },
            {
                "id": 2,
                "customer": {
                    "id": 3,
                    "name": "Davin Gibson",
                    "email": "rbednar@example.org"
                },
                "subject": "Billing question",
                "status": "Open",
                "last_message": null,
                "created_at": "2026-08-20 14:19:16",
                "closed_at": null
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/conversations?page=1",
            "last": "http://localhost/api/v1/admin/conversations?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/conversations?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/conversations",
            "per_page": 15,
            "to": 2,
            "total": 2
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "conversations": [
            {
                "id": 1,
                "customer": {
                    "id": 105,
                    "name": "Ibrahim Price Jr.",
                    "email": "arvilla37@example.org"
                },
                "subject": "Need help with my order",
                "status": "Open",
                "last_message": "Hello, when will my technician arrive?",
                "created_at": "2026-08-20 14:20:13",
                "closed_at": null
            },
            {
                "id": 2,
                "customer": {
                    "id": 105,
                    "name": "Ibrahim Price Jr.",
                    "email": "arvilla37@example.org"
                },
                "subject": "Billing question",
                "status": "Open",
                "last_message": null,
                "created_at": "2026-08-20 14:20:13",
                "closed_at": null
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/conversations?page=1",
            "last": "http://localhost/api/v1/admin/conversations?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/conversations?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/conversations",
            "per_page": 15,
            "to": 2,
            "total": 2
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "conversations": [
            {
                "id": 1,
                "customer": {
                    "id": 105,
                    "name": "Clyde Walker I",
                    "email": "ykris@example.net"
                },
                "subject": "Need help with my order",
                "status": "Open",
                "last_message": "Hello, when will my technician arrive?",
                "created_at": "2026-08-20 14:24:24",
                "closed_at": null
            },
            {
                "id": 2,
                "customer": {
                    "id": 105,
                    "name": "Clyde Walker I",
                    "email": "ykris@example.net"
                },
                "subject": "Billing question",
                "status": "Open",
                "last_message": null,
                "created_at": "2026-08-20 14:24:24",
                "closed_at": null
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/conversations?page=1",
            "last": "http://localhost/api/v1/admin/conversations?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/conversations?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/conversations",
            "per_page": 15,
            "to": 2,
            "total": 2
        }
    }
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### Show Contact message Details

**What this does:** Returns full details for one contact message.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contact-messages/:id` |
| **Route name** | `admin.contact-messages.show` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contact-messages.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — marks as read }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 1,
        "name": "John Doe",
        "email": "john@example.com",
        "phone": "1000000001",
        "subject": "Question about pricing",
        "is_read": true,
        "replied_at": null,
        "created_at": "2026-08-20 14:19:15",
        "message": "How much does a standard maintenance visit cost?",
        "reply": null,
        "replied_by": null,
        "updated_at": "2026-08-20 14:19:15"
    }
}
```

*{ 200 OK — marks as read }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 1,
        "name": "John Doe",
        "email": "john@example.com",
        "phone": "1000000001",
        "subject": "Question about pricing",
        "is_read": true,
        "replied_at": null,
        "created_at": "2026-08-20 14:20:13",
        "message": "How much does a standard maintenance visit cost?",
        "reply": null,
        "replied_by": null,
        "updated_at": "2026-08-20 14:20:13"
    }
}
```

*{ 200 OK — marks as read }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 1,
        "name": "John Doe",
        "email": "john@example.com",
        "phone": "1000000001",
        "subject": "Question about pricing",
        "is_read": true,
        "replied_at": null,
        "created_at": "2026-08-20 14:24:24",
        "message": "How much does a standard maintenance visit cost?",
        "reply": null,
        "replied_by": null,
        "updated_at": "2026-08-20 14:24:24"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use `update` to modify it, or `destroy` to remove it.

---

#### Show Conversation Details

**What this does:** Returns full details for one conversation.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/conversations/:id` |
| **Route name** | `admin.conversations.show` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `conversations.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 1,
        "customer": {
            "id": 3,
            "name": "Davin Gibson",
            "email": "rbednar@example.org"
        },
        "subject": "Need help with my order",
        "status": "Open",
        "created_at": "2026-08-20 14:19:16",
        "closed_at": null,
        "messages": [
            {
                "id": 1,
                "sender": {
                    "id": 3,
                    "name": "Davin Gibson"
                },
                "sender_type": "customer",
                "body": "Hello, when will my technician arrive?",
                "sent_at": "2026-08-20 14:19:16"
            }
        ]
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 1,
        "customer": {
            "id": 105,
            "name": "Ibrahim Price Jr.",
            "email": "arvilla37@example.org"
        },
        "subject": "Need help with my order",
        "status": "Open",
        "created_at": "2026-08-20 14:20:13",
        "closed_at": null,
        "messages": [
            {
                "id": 1,
                "sender": {
                    "id": 105,
                    "name": "Ibrahim Price Jr."
                },
                "sender_type": "customer",
                "body": "Hello, when will my technician arrive?",
                "sent_at": "2026-08-20 14:20:13"
            }
        ]
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 1,
        "customer": {
            "id": 105,
            "name": "Clyde Walker I",
            "email": "ykris@example.net"
        },
        "subject": "Need help with my order",
        "status": "Open",
        "created_at": "2026-08-20 14:24:24",
        "closed_at": null,
        "messages": [
            {
                "id": 1,
                "sender": {
                    "id": 105,
                    "name": "Clyde Walker I"
                },
                "sender_type": "customer",
                "body": "Hello, when will my technician arrive?",
                "sent_at": "2026-08-20 14:24:24"
            }
        ]
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use `update` to modify it, or `destroy` to remove it.

---

#### Reply Contact message

**What this does:** Sends a reply to a public contact-form submission and marks it replied.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contact-messages/:id/reply` |
| **Route name** | `admin.contact-messages.reply` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contact-messages.reply` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `reply`
- **Description:** Reply
- **Type:** `string`
- **Required:** required
- **Example:** `Thank you for reaching out. We will address your concern shortly.`
- **Validation rules:** `required|string|max:5000`
- `required` — must be provided.
- `string` — must be text.
- `max:5000` — must not exceed 5000.

**Example Request Body:**
```json
{
    "reply": "Thank you for reaching out, a standard visit costs 150 SAR."
}
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Reply sent successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Reply sent successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Reply sent successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a reply message.",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a reply message.",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a reply message.",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** The sender receives the reply via whatever out-of-band channel the reply mechanism uses (email, typically) — check the captured response/notes for delivery specifics.

---

#### Close Conversation

**What this does:** Marks a support conversation `closed`.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/conversations/:id/close` |
| **Route name** | `admin.conversations.close` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `conversations.close` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`

**Payload:**
Example payload is included in the request body. No FormRequest validation rules were detected.
### `key`
- **Description:** Key
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `not specified`
- `not specified` — no validation rule was declared.

**Example Request Body:**
```json
{
    "key": "value"
}
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Conversation closed successfully",
    "data": {
        "id": 1,
        "customer": {
            "id": 3,
            "name": "Davin Gibson",
            "email": "rbednar@example.org"
        },
        "subject": "Need help with my order",
        "status": "Closed",
        "created_at": "2026-08-20 14:19:16",
        "closed_at": "2026-08-20 14:19:16"
    }
}
```

*{ 200 OK — already closed (idempotent, no guard) }*
```json
{
    "status": "success",
    "message": "Conversation closed successfully",
    "data": {
        "id": 1,
        "customer": {
            "id": 3,
            "name": "Davin Gibson",
            "email": "rbednar@example.org"
        },
        "subject": "Need help with my order",
        "status": "Closed",
        "created_at": "2026-08-20 14:19:16",
        "closed_at": "2026-08-20 14:19:16"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Conversation closed successfully",
    "data": {
        "id": 1,
        "customer": {
            "id": 105,
            "name": "Ibrahim Price Jr.",
            "email": "arvilla37@example.org"
        },
        "subject": "Need help with my order",
        "status": "Closed",
        "created_at": "2026-08-20 14:20:13",
        "closed_at": "2026-08-20 14:20:13"
    }
}
```

*{ 200 OK — already closed (idempotent, no guard) }*
```json
{
    "status": "success",
    "message": "Conversation closed successfully",
    "data": {
        "id": 1,
        "customer": {
            "id": 105,
            "name": "Ibrahim Price Jr.",
            "email": "arvilla37@example.org"
        },
        "subject": "Need help with my order",
        "status": "Closed",
        "created_at": "2026-08-20 14:20:13",
        "closed_at": "2026-08-20 14:20:13"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Conversation closed successfully",
    "data": {
        "id": 1,
        "customer": {
            "id": 105,
            "name": "Clyde Walker I",
            "email": "ykris@example.net"
        },
        "subject": "Need help with my order",
        "status": "Closed",
        "created_at": "2026-08-20 14:24:24",
        "closed_at": "2026-08-20 14:24:24"
    }
}
```

*{ 200 OK — already closed (idempotent, no guard) }*
```json
{
    "status": "success",
    "message": "Conversation closed successfully",
    "data": {
        "id": 1,
        "customer": {
            "id": 105,
            "name": "Clyde Walker I",
            "email": "ykris@example.net"
        },
        "subject": "Need help with my order",
        "status": "Closed",
        "created_at": "2026-08-20 14:24:24",
        "closed_at": "2026-08-20 14:24:24"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** No further messages should be expected on it through the normal UI flow, though the history remains readable.

---

#### Reply Conversation

**What this does:** Admin sends a message into a support conversation.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/conversations/:id/reply` |
| **Route name** | `admin.conversations.reply` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `conversations.reply` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `201 Created`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `body`
- **Description:** Reply
- **Type:** `string`
- **Required:** required
- **Example:** `Example message body text.`
- **Validation rules:** `required|string|max:2000`
- `required` — must be provided.
- `string` — must be text.
- `max:2000` — must not exceed 2000.

**Example Request Body:**
```json
{
    "body": "A technician will arrive between 2-4 PM today."
}
```

> **Fixed:** an earlier pass of this doc captured a real `500` here for every scenario — `Message` (like `Conversation`/`InternalNote`) used to `use HasUuids` despite `messages.id` being a plain `BIGINT` auto-increment column, so Eloquent tried to insert a generated UUID string into it (`SQLSTATE[01000]: ... Data truncated for column 'id'`). Fixed by dropping `HasUuids` from `App\Models\Message` (kept only on models whose primary key really is a UUID, like `Order`/`Contract`). Re-verified live via `AdminSupportNotesFlagsDumpTest::test_dump_conversation_endpoints` — see the real `201` below.

**Actual Success Response(s):**

*{ 201 Created — live capture, 2026-08-22 }*
```json
{
    "status": "success",
    "message": "Reply sent successfully",
    "data": {
        "id": 2,
        "sender": {
            "id": 1,
            "name": "Stewart Cummings"
        },
        "sender_type": "staff",
        "body": "A technician will arrive between 2-4 PM today.",
        "sent_at": "2026-08-22 19:34:51"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "The Reply field is required.",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** The customer/company/technician sees it via their own `GET /conversations/{id}` (or `POST .../{id}/messages` to reply back).

---

#### Delete Contact message

**What this does:** Permanently deletes a contact message.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contact-messages/:id` |
| **Route name** | `admin.contact-messages.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contact-messages.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** It no longer appears in `index`.

---

#### Delete Conversation

**What this does:** Permanently deletes a conversation.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/conversations/:id` |
| **Route name** | `admin.conversations.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `conversations.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `id` — Id ID — seeded example: `1`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** It no longer appears in `index`.

---

#### Delete Bulk

**What this does:** Deletes multiple contact messages in one call by an array of ids.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/contact-messages/bulk` |
| **Route name** | `admin.contact-messages.bulk.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `contact-messages.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please select at least one item.",
    "data": null
}
```

*{ 404 Not Found — some ids missing }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please select at least one item.",
    "data": null
}
```

*{ 404 Not Found — some ids missing }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please select at least one item.",
    "data": null
}
```

*{ 404 Not Found — some ids missing }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Re-fetch the index to confirm — deleted contact messages no longer appear.

---

## 13. Audit Logs

#### List All Audit logs

**What this does:** Returns a paginated, filterable, searchable list of audit logs.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/audit-logs?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&model=App\Models\User&actor_id=1&action=created&from=2024-01-01&to=2024-12-31` |
| **Route name** | `admin.audit-logs.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `audit-logs.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `401 Unauthorized` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`
- `Authorization: Bearer {token}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `model` — Filter by model class (optional)
- `actor_id` — Filter by actor user ID (optional)
- `action` — Filter by action: created, updated, deleted (optional)
- `from` — Filter from date (optional)
- `to` — Filter to date (optional)

**Actual Success Response(s):**

*{ 200 OK — list audit logs }*
```json
{
    "status": "success",
    "message": "Audit logs retrieved",
    "data": {
        "current_page": 1,
        "data": [
            {
                "id": 35,
                "auditable_type": "App\\Models\\User",
                "auditable_id": 99,
                "action": "updated",
                "old_values": {
                    "status": "pending"
                },
                "new_values": {
                    "status": "active"
                },
                "actor_id": 99,
                "ip_address": "127.0.0.1",
                "user_agent": "PHPUnit",
                "correlation_id": "45f99f86-8cd7-407d-964f-b3b633d8223c",
                "created_at": "2026-08-20T12:09:45.000000Z",
                "actor": {
                    "id": 99,
                    "name": "Mrs. Aiyana Miller",
                    "email": "prince.kunde@example.org"
                }
            }
        ],
        "first_page_url": "http://localhost/api/v1/admin/audit-logs?page=1",
        "from": 1,
        "last_page": 1,
        "last_page_url": "http://localhost/api/v1/admin/audit-logs?page=1",
        "links": [
            {
                "url": null,
                "label": "&laquo; Previous",
                "page": null,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/audit-logs?page=1",
                "label": "1",
                "page": 1,
                "active": true
            },
            {
                "url": null,
                "label": "Next &raquo;",
                "page": null,
                "active": false
            }
        ],
        "next_page_url": null,
        "path": "http://localhost/api/v1/admin/audit-logs",
        "per_page": 25,
        "prev_page_url": null,
        "to": 1,
        "total": 1
    }
}
```

*{ 200 OK — filter by model }*
```json
{
    "status": "success",
    "message": "Audit logs retrieved",
    "data": {
        "current_page": 1,
        "data": [
            {
                "id": 35,
                "auditable_type": "App\\Models\\User",
                "auditable_id": 99,
                "action": "updated",
                "old_values": {
                    "status": "pending"
                },
                "new_values": {
                    "status": "active"
                },
                "actor_id": 99,
                "ip_address": "127.0.0.1",
                "user_agent": "PHPUnit",
                "correlation_id": "45f99f86-8cd7-407d-964f-b3b633d8223c",
                "created_at": "2026-08-20T12:09:45.000000Z",
                "actor": {
                    "id": 99,
                    "name": "Mrs. Aiyana Miller",
                    "email": "prince.kunde@example.org"
                }
            }
        ],
        "first_page_url": "http://localhost/api/v1/admin/audit-logs?page=1",
        "from": 1,
        "last_page": 1,
        "last_page_url": "http://localhost/api/v1/admin/audit-logs?page=1",
        "links": [
            {
                "url": null,
                "label": "&laquo; Previous",
                "page": null,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/audit-logs?page=1",
                "label": "1",
                "page": 1,
                "active": true
            },
            {
                "url": null,
                "label": "Next &raquo;",
                "page": null,
                "active": false
            }
        ],
        "next_page_url": null,
        "path": "http://localhost/api/v1/admin/audit-logs",
        "per_page": 25,
        "prev_page_url": null,
        "to": 1,
        "total": 1
    }
}
```

*{ 200 OK — date range filter result }*
```json
{
    "status": "success",
    "message": "Audit logs retrieved",
    "data": {
        "current_page": 1,
        "data": [
            {
                "id": 35,
                "auditable_type": "App\\Models\\User",
                "auditable_id": 99,
                "action": "updated",
                "old_values": {
                    "status": "pending"
                },
                "new_values": {
                    "status": "active"
                },
                "actor_id": 99,
                "ip_address": "127.0.0.1",
                "user_agent": "PHPUnit",
                "correlation_id": "45f99f86-8cd7-407d-964f-b3b633d8223c",
                "created_at": "2026-08-20T12:09:45.000000Z",
                "actor": {
                    "id": 99,
                    "name": "Mrs. Aiyana Miller",
                    "email": "prince.kunde@example.org"
                }
            }
        ],
        "first_page_url": "http://localhost/api/v1/admin/audit-logs?page=1",
        "from": 1,
        "last_page": 1,
        "last_page_url": "http://localhost/api/v1/admin/audit-logs?page=1",
        "links": [
            {
                "url": null,
                "label": "&laquo; Previous",
                "page": null,
                "active": false
            },
            {
                "url": "http://localhost/api/v1/admin/audit-logs?page=1",
                "label": "1",
                "page": 1,
                "active": true
            },
            {
                "url": null,
                "label": "Next &raquo;",
                "page": null,
                "active": false
            }
        ],
        "next_page_url": null,
        "path": "http://localhost/api/v1/admin/audit-logs",
        "per_page": 25,
        "prev_page_url": null,
        "to": 1,
        "total": 1
    }
}
```

**Actual Error Response(s):**

*{ 401 Unauthorized — 401 Unauthenticated - no token }*
```json
{
    "status": "fail",
    "message": "Unauthenticated, you have to login first",
    "data": null
}
```

**What happens next:** Use `show` on a specific id for full details.

---

## 14. Dashboard & Reports

#### List All Dashboard

**What this does:** Returns a paginated, filterable, searchable list of dashboard.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/dashboard?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.dashboard.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `dashboard.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `401 Unauthorized` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`
- `Authorization: Bearer {token}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — dashboard metrics }*
```json
{
    "status": "success",
    "message": "Dashboard metrics retrieved",
    "data": {
        "users": {
            "total": 12,
            "active": 11,
            "today": 12,
            "this_week": 12
        },
        "addresses": {
            "total": 0,
            "with_default": 0,
            "top_countries": []
        },
        "system": {
            "php_version": "8.4.24",
            "laravel_version": "13.25.0",
            "environment": "testing"
        }
    }
}
```

**Actual Error Response(s):**

*{ 401 Unauthorized — 401 Unauthenticated - no token }*
```json
{
    "status": "fail",
    "message": "Unauthenticated, you have to login first",
    "data": null
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### Companies Dashboard

**What this does:** Returns aggregate company metrics (counts by status, verification completeness, recent signups) for the admin dashboard.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/dashboard/companies` |
| **Route name** | `admin.dashboard.companies` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `dashboard.companies` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`
- `Authorization: Bearer {token}`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — company dashboard metrics }*
```json
{
    "status": "success",
    "message": "Company dashboard metrics retrieved",
    "data": {
        "total": 2,
        "by_status": {
            "pending": 1,
            "active": 1
        },
        "pending_review": 1,
        "today": 2,
        "this_week": 2,
        "verification_completeness": {
            "with_tax_number": 0,
            "with_commercial_registration_no": 0
        },
        "recent": [
            {
                "id": 98,
                "legal_name": null,
                "email": "bruce15@example.com",
                "account_owner_phone": null,
                "status": "pending",
                "created_at": "2026-08-20T12:09:45.000000Z"
            },
            {
                "id": 97,
                "legal_name": null,
                "email": "estelle.medhurst@example.net",
                "account_owner_phone": null,
                "status": "active",
                "created_at": "2026-08-20T12:09:45.000000Z"
            }
        ]
    }
}
```

**What happens next:** Drill into a specific company via `GET /admin/companies/{id}`.

---

#### Technicians Dashboard

**What this does:** Returns aggregate technician metrics (availability, ratings, completed-order leaderboards) for the admin dashboard.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/dashboard/technicians` |
| **Route name** | `admin.dashboard.technicians` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `dashboard.technicians` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`
- `Authorization: Bearer {token}`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — technician dashboard metrics }*
```json
{
    "status": "success",
    "message": "Technician dashboard metrics retrieved",
    "data": {
        "total": 0,
        "active": 0,
        "by_availability": [],
        "by_category": [],
        "by_employment_type": [],
        "average_rating": 0,
        "top_by_completed_orders": [],
        "top_by_rating": []
    }
}
```

**What happens next:** Drill into a specific technician via `GET /admin/technicians/{id}`.

---

#### Operational Report

**What this does:** Returns the current-state operational snapshot (order counts by status/source/booking-type, risk queues for unassigned/needs-attention/awaiting-confirmation orders) for a date range. This is a snapshot, not a historical time series — see `meta.report_kind`.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/reports/operational?date_from=2026-08-01&date_to=2026-08-31&date_basis=created&timezone=Africa/Cairo&statuses[]=pending&order_sources[]=individual&booking_types[]=scheduled&customer_id=1&technician_id=1&branch_id=1&contract_id=1&needs_attention=true&risk_limit=20` |
| **Route name** | `admin.reports.operational` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `reports.operational` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `date_from` — Inclusive report date (maximum range: 366 days) (supported)
- `date_to` — Inclusive report date (supported)
- `date_basis` — created or scheduled (supported)
- `timezone` — IANA timezone used for date boundaries (supported)
- `statuses[]` — Optional current order status (optional)
- `order_sources[]` — Optional: individual, company, or contract_visit — validated against `OrderSource::values()`, the enum's own case values (not the `job_order` literal the checkout code path writes to the column — see the `OrderSource` row in `README.md`'s Enum Reference) (optional)
- `booking_types[]` — Optional: instant or scheduled (optional)
- `customer_id` — Optional customer ID (optional)
- `technician_id` — Optional technician ID (optional)
- `branch_id` — Optional branch ID (optional)
- `contract_id` — Optional contract ID (optional)
- `needs_attention` — Optional boolean filter (optional)
- `risk_limit` — Rows returned per risk queue (1–50) (optional)

**Actual Success Response(s):**

*{ 200 OK — live capture }*
```json
{
    "status": "success",
    "message": "Operational report retrieved",
    "data": {
        "meta": {
            "metric_version": "operational-v1",
            "report_kind": "current_operations_snapshot",
            "snapshot_semantics": "current_order_state_for_orders_selected_by_date_basis",
            "historical_as_of_state": "not_available",
            "date_basis": "created",
            "timezone": "Africa/Cairo",
            "filters": {
                "date_basis": "created",
                "date_from": "2026-08-01",
                "date_to": "2026-08-31",
                "timezone": "Africa/Cairo",
                "risk_limit": 20
            },
            "filters_hash": "8db36da0b553f7d440dff0638e6bca9ef715dae2dca125fb838fc442aee570a9",
            "generated_at": "2026-08-20T20:04:07+00:00",
            "source_watermark": "2026-08-20T19:55:35+00:00",
            "refresh_after_seconds": 60,
            "risk_queue_scope": "current_order_state_with_selected_filters"
        },
        "metrics": {
            "orders_in_selected_period": 22,
            "scheduled_orders": 10,
            "unassigned_pending": 10,
            "pending_assigned_awaiting_acceptance": 0,
            "needs_attention_orders": 0,
            "active_in_field": 4,
            "technically_finished_awaiting_customer": 5,
            "customer_confirmed": 1,
            "cancelled_orders": 0,
            "contract_orders": 0,
            "non_contract_orders": 22
        },
        "distributions": {
            "by_status": [
                {
                    "value": "accepted",
                    "orders": 2
                },
                {
                    "value": "confirmed",
                    "orders": 1
                },
                {
                    "value": "finish",
                    "orders": 5
                },
                {
                    "value": "on_the_way",
                    "orders": 1
                },
                {
                    "value": "pending",
                    "orders": 10
                },
                {
                    "value": "start",
                    "orders": 3
                }
            ],
            "by_order_source": [
                {
                    "value": "company",
                    "orders": 16
                },
                {
                    "value": "individual",
                    "orders": 6
                }
            ],
            "by_booking_type": [
                {
                    "value": "instant",
                    "orders": 13
                },
                {
                    "value": "scheduled",
                    "orders": 9
                }
            ]
        },
        "risk_queues": {
            "unassigned_pending": [
                {
                    "id": "460aab99-cc79-44ad-ac56-b71b385c37a4",
                    "order_number": "ORD-260820-OBNC",
                    "status": "pending",
                    "order_source": "individual",
                    "scheduled_date": null,
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:28"
                },
                {
                    "id": "599c2e9b-6e86-4a14-8bb4-0c08bcd4325d",
                    "order_number": "ORD-260820-TDWW",
                    "status": "pending",
                    "order_source": "company",
                    "scheduled_date": null,
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:29"
                },
                {
                    "id": "0739dc4d-f9cb-4bfd-95f3-5375d200134e",
                    "order_number": "ORD-260820-AUGY",
                    "status": "pending",
                    "order_source": "company",
                    "scheduled_date": null,
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:29"
                },
                {
                    "id": "f2d17fe0-a83d-4424-8262-fce1bf937bf5",
                    "order_number": "ORD-260820-SKPG",
                    "status": "pending",
                    "order_source": "company",
                    "scheduled_date": null,
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:29"
                },
                {
                    "id": "26fccf91-6e4c-4553-bc23-f9cddcfba40b",
                    "order_number": "ORD-260820-OHEL",
                    "status": "pending",
                    "order_source": "company",
                    "scheduled_date": null,
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:29"
                },
                {
                    "id": "0e60967c-e182-4d35-b6d1-0e87ed5717f6",
                    "order_number": "ORD-260820-HQPC",
                    "status": "pending",
                    "order_source": "company",
                    "scheduled_date": null,
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:29"
                },
                {
                    "id": "5299ef16-3978-4808-b7f3-1c0b92fa2cea",
                    "order_number": "ORD-260820-SDWO",
                    "status": "pending",
                    "order_source": "company",
                    "scheduled_date": null,
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:29"
                },
                {
                    "id": "275f9554-5be0-428c-b564-a71ed0435fec",
                    "order_number": "ORD-260820-OQNI",
                    "status": "pending",
                    "order_source": "company",
                    "scheduled_date": "2026-08-26",
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:29"
                },
                {
                    "id": "0c83e0f3-63c5-4a5c-aceb-7b75af0a7372",
                    "order_number": "ORD-260820-KZSV",
                    "status": "pending",
                    "order_source": "company",
                    "scheduled_date": "2026-08-29",
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:29"
                },
                {
                    "id": "0356c11f-6c66-4f89-93b3-fa917f1edb7c",
                    "order_number": "ORD-260820-PXLS",
                    "status": "pending",
                    "order_source": "company",
                    "scheduled_date": "2026-09-01",
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:29"
                }
            ],
            "needs_attention": [],
            "awaiting_customer_confirmation": [
                {
                    "id": "7ee82712-5701-4a64-b0e1-993ffefad020",
                    "order_number": "ORD-260820-KQBH",
                    "status": "finish",
                    "order_source": "company",
                    "scheduled_date": null,
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:29"
                },
                {
                    "id": "6b4ac484-712a-41bd-919e-6d9768df1c78",
                    "order_number": "ORD-260820-OWIZ",
                    "status": "finish",
                    "order_source": "individual",
                    "scheduled_date": null,
                    "technician_name": "Fahad Al-Otaibi",
                    "needs_attention": false,
                    "created_at": "2026-08-20 19:44:02"
                },
                {
                    "id": "4f467f5c-4606-435b-9ffe-a410e3b503f7",
                    "order_number": "ORD-260820-UMAS",
                    "status": "finish",
                    "order_source": "company",
                    "scheduled_date": "2026-08-23",
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:29"
                },
                {
                    "id": "d171afaa-f57f-457c-a027-34f2beb0051f",
                    "order_number": "ORD-260820-OKSH",
                    "status": "finish",
                    "order_source": "individual",
                    "scheduled_date": "2026-08-28",
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:28"
                },
                {
                    "id": "9f167f39-a1df-4679-824d-c4a4efa035a2",
                    "order_number": "ORD-260820-HFFE",
                    "status": "finish",
                    "order_source": "individual",
                    "scheduled_date": "2026-08-29",
                    "technician_name": null,
                    "needs_attention": false,
                    "created_at": "2026-08-20 18:37:28"
                }
            ]
        }
    }
}

```

**What happens next:** Use `risk_queues.unassigned_pending` / `.needs_attention` entries to identify orders needing `admin.orders.assign-technician` next.

---

## 15. Roles, Permissions & Supervisors

#### List All Permissions

**What this does:** Returns a paginated, filterable, searchable list of permissions.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/permissions?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.permissions.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `permissions.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Permissions retrieved",
    "data": [
        {
            "id": 70,
            "name": "destroy-audit-logs",
            "display_name": "Destroy Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.destroy",
            "resource": "audit-logs",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 66,
            "name": "index-audit-logs",
            "display_name": "Index Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.index",
            "resource": "audit-logs",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 67,
            "name": "show-audit-logs",
            "display_name": "Show Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.show",
            "resource": "audit-logs",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 68,
            "name": "store-audit-logs",
            "display_name": "Store Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.store",
            "resource": "audit-logs",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 69,
            "name": "update-audit-logs",
            "display_name": "Update Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.update",
            "resource": "audit-logs",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 25,
            "name": "destroy-categories",
            "display_name": "Destroy Categories",
            "group": "categories",
            "route_name": "admin.categories.destroy",
            "resource": "categories",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 21,
            "name": "index-categories",
            "display_name": "Index Categories",
            "group": "categories",
            "route_name": "admin.categories.index",
            "resource": "categories",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 22,
            "name": "show-categories",
            "display_name": "Show Categories",
            "group": "categories",
            "route_name": "admin.categories.show",
            "resource": "categories",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 23,
            "name": "store-categories",
            "display_name": "Store Categories",
            "group": "categories",
            "route_name": "admin.categories.store",
            "resource": "categories",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 24,
            "name": "update-categories",
            "display_name": "Update Categories",
            "group": "categories",
            "route_name": "admin.categories.update",
            "resource": "categories",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 75,
            "name": "destroy-contact-messages",
            "display_name": "Destroy Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.destroy",
            "resource": "contact-messages",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 71,
            "name": "index-contact-messages",
            "display_name": "Index Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.index",
            "resource": "contact-messages",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 72,
            "name": "show-contact-messages",
            "display_name": "Show Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.show",
            "resource": "contact-messages",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 73,
            "name": "store-contact-messages",
            "display_name": "Store Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.store",
            "resource": "contact-messages",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 74,
            "name": "update-contact-messages",
            "display_name": "Update Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.update",
            "resource": "contact-messages",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 90,
            "name": "destroy-conversations",
            "display_name": "Destroy Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.destroy",
            "resource": "conversations",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 86,
            "name": "index-conversations",
            "display_name": "Index Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.index",
            "resource": "conversations",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 87,
            "name": "show-conversations",
            "display_name": "Show Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.show",
            "resource": "conversations",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 88,
            "name": "store-conversations",
            "display_name": "Store Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.store",
            "resource": "conversations",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 89,
            "name": "update-conversations",
            "display_name": "Update Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.update",
            "resource": "conversations",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 5,
            "name": "destroy-countries",
            "display_name": "Destroy Countries",
            "group": "countries",
            "route_name": "admin.countries.destroy",
            "resource": "countries",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 1,
            "name": "index-countries",
            "display_name": "Index Countries",
            "group": "countries",
            "route_name": "admin.countries.index",
            "resource": "countries",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 2,
            "name": "show-countries",
            "display_name": "Show Countries",
            "group": "countries",
            "route_name": "admin.countries.show",
            "resource": "countries",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 3,
            "name": "store-countries",
            "display_name": "Store Countries",
            "group": "countries",
            "route_name": "admin.countries.store",
            "resource": "countries",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 4,
            "name": "update-countries",
            "display_name": "Update Countries",
            "group": "countries",
            "route_name": "admin.countries.update",
            "resource": "countries",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 85,
            "name": "destroy-dashboard-home",
            "display_name": "Destroy Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.destroy",
            "resource": "dashboard-home",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 81,
            "name": "index-dashboard-home",
            "display_name": "Index Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.index",
            "resource": "dashboard-home",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 82,
            "name": "show-dashboard-home",
            "display_name": "Show Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.show",
            "resource": "dashboard-home",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 83,
            "name": "store-dashboard-home",
            "display_name": "Store Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.store",
            "resource": "dashboard-home",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 84,
            "name": "update-dashboard-home",
            "display_name": "Update Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.update",
            "resource": "dashboard-home",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 30,
            "name": "destroy-faqs",
            "display_name": "Destroy Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.destroy",
            "resource": "faqs",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 26,
            "name": "index-faqs",
            "display_name": "Index Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.index",
            "resource": "faqs",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 27,
            "name": "show-faqs",
            "display_name": "Show Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.show",
            "resource": "faqs",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 28,
            "name": "store-faqs",
            "display_name": "Store Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.store",
            "resource": "faqs",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 29,
            "name": "update-faqs",
            "display_name": "Update Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.update",
            "resource": "faqs",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 65,
            "name": "destroy-feature-flags",
            "display_name": "Destroy Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.destroy",
            "resource": "feature-flags",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 61,
            "name": "index-feature-flags",
            "display_name": "Index Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.index",
            "resource": "feature-flags",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 62,
            "name": "show-feature-flags",
            "display_name": "Show Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.show",
            "resource": "feature-flags",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 63,
            "name": "store-feature-flags",
            "display_name": "Store Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.store",
            "resource": "feature-flags",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 64,
            "name": "update-feature-flags",
            "display_name": "Update Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.update",
            "resource": "feature-flags",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 10,
            "name": "destroy-governorates",
            "display_name": "Destroy Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.destroy",
            "resource": "governorates",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 6,
            "name": "index-governorates",
            "display_name": "Index Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.index",
            "resource": "governorates",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 7,
            "name": "show-governorates",
            "display_name": "Show Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.show",
            "resource": "governorates",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 8,
            "name": "store-governorates",
            "display_name": "Store Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.store",
            "resource": "governorates",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 9,
            "name": "update-governorates",
            "display_name": "Update Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.update",
            "resource": "governorates",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 95,
            "name": "destroy-internal-notes",
            "display_name": "Destroy Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.destroy",
            "resource": "internal-notes",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 91,
            "name": "index-internal-notes",
            "display_name": "Index Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.index",
            "resource": "internal-notes",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 92,
            "name": "show-internal-notes",
            "display_name": "Show Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.show",
            "resource": "internal-notes",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 93,
            "name": "store-internal-notes",
            "display_name": "Store Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.store",
            "resource": "internal-notes",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 94,
            "name": "update-internal-notes",
            "display_name": "Update Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.update",
            "resource": "internal-notes",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 80,
            "name": "destroy-notifications",
            "display_name": "Destroy Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.destroy",
            "resource": "notifications",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 76,
            "name": "index-notifications",
            "display_name": "Index Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.index",
            "resource": "notifications",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 77,
            "name": "show-notifications",
            "display_name": "Show Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.show",
            "resource": "notifications",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 78,
            "name": "store-notifications",
            "display_name": "Store Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.store",
            "resource": "notifications",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 79,
            "name": "update-notifications",
            "display_name": "Update Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.update",
            "resource": "notifications",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 15,
            "name": "destroy-regions",
            "display_name": "Destroy Regions",
            "group": "regions",
            "route_name": "admin.regions.destroy",
            "resource": "regions",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 11,
            "name": "index-regions",
            "display_name": "Index Regions",
            "group": "regions",
            "route_name": "admin.regions.index",
            "resource": "regions",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 12,
            "name": "show-regions",
            "display_name": "Show Regions",
            "group": "regions",
            "route_name": "admin.regions.show",
            "resource": "regions",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 13,
            "name": "store-regions",
            "display_name": "Store Regions",
            "group": "regions",
            "route_name": "admin.regions.store",
            "resource": "regions",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 14,
            "name": "update-regions",
            "display_name": "Update Regions",
            "group": "regions",
            "route_name": "admin.regions.update",
            "resource": "regions",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 55,
            "name": "destroy-roles",
            "display_name": "Destroy Roles",
            "group": "roles",
            "route_name": "admin.roles.destroy",
            "resource": "roles",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 51,
            "name": "index-roles",
            "display_name": "Index Roles",
            "group": "roles",
            "route_name": "admin.roles.index",
            "resource": "roles",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 52,
            "name": "show-roles",
            "display_name": "Show Roles",
            "group": "roles",
            "route_name": "admin.roles.show",
            "resource": "roles",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 53,
            "name": "store-roles",
            "display_name": "Store Roles",
            "group": "roles",
            "route_name": "admin.roles.store",
            "resource": "roles",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 54,
            "name": "update-roles",
            "display_name": "Update Roles",
            "group": "roles",
            "route_name": "admin.roles.update",
            "resource": "roles",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 60,
            "name": "destroy-settings",
            "display_name": "Destroy Settings",
            "group": "settings",
            "route_name": "admin.settings.destroy",
            "resource": "settings",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 56,
            "name": "index-settings",
            "display_name": "Index Settings",
            "group": "settings",
            "route_name": "admin.settings.index",
            "resource": "settings",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 57,
            "name": "show-settings",
            "display_name": "Show Settings",
            "group": "settings",
            "route_name": "admin.settings.show",
            "resource": "settings",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 58,
            "name": "store-settings",
            "display_name": "Store Settings",
            "group": "settings",
            "route_name": "admin.settings.store",
            "resource": "settings",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 59,
            "name": "update-settings",
            "display_name": "Update Settings",
            "group": "settings",
            "route_name": "admin.settings.update",
            "resource": "settings",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 20,
            "name": "destroy-shipping-zones",
            "display_name": "Destroy Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.destroy",
            "resource": "shipping-zones",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 16,
            "name": "index-shipping-zones",
            "display_name": "Index Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.index",
            "resource": "shipping-zones",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 17,
            "name": "show-shipping-zones",
            "display_name": "Show Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.show",
            "resource": "shipping-zones",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 18,
            "name": "store-shipping-zones",
            "display_name": "Store Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.store",
            "resource": "shipping-zones",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 19,
            "name": "update-shipping-zones",
            "display_name": "Update Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.update",
            "resource": "shipping-zones",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 40,
            "name": "destroy-sliders",
            "display_name": "Destroy Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.destroy",
            "resource": "sliders",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 36,
            "name": "index-sliders",
            "display_name": "Index Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.index",
            "resource": "sliders",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 37,
            "name": "show-sliders",
            "display_name": "Show Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.show",
            "resource": "sliders",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 38,
            "name": "store-sliders",
            "display_name": "Store Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.store",
            "resource": "sliders",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 39,
            "name": "update-sliders",
            "display_name": "Update Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.update",
            "resource": "sliders",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 35,
            "name": "destroy-static-pages",
            "display_name": "Destroy Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.destroy",
            "resource": "static-pages",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 31,
            "name": "index-static-pages",
            "display_name": "Index Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.index",
            "resource": "static-pages",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 32,
            "name": "show-static-pages",
            "display_name": "Show Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.show",
            "resource": "static-pages",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 33,
            "name": "store-static-pages",
            "display_name": "Store Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.store",
            "resource": "static-pages",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 34,
            "name": "update-static-pages",
            "display_name": "Update Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.update",
            "resource": "static-pages",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 50,
            "name": "destroy-supervisors",
            "display_name": "Destroy Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.destroy",
            "resource": "supervisors",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 46,
            "name": "index-supervisors",
            "display_name": "Index Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.index",
            "resource": "supervisors",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 47,
            "name": "show-supervisors",
            "display_name": "Show Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.show",
            "resource": "supervisors",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 48,
            "name": "store-supervisors",
            "display_name": "Store Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.store",
            "resource": "supervisors",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 49,
            "name": "update-supervisors",
            "display_name": "Update Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.update",
            "resource": "supervisors",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 45,
            "name": "destroy-users",
            "display_name": "Destroy Users",
            "group": "users",
            "route_name": "admin.users.destroy",
            "resource": "users",
            "action": "destroy",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 41,
            "name": "index-users",
            "display_name": "Index Users",
            "group": "users",
            "route_name": "admin.users.index",
            "resource": "users",
            "action": "index",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 42,
            "name": "show-users",
            "display_name": "Show Users",
            "group": "users",
            "route_name": "admin.users.show",
            "resource": "users",
            "action": "show",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 43,
            "name": "store-users",
            "display_name": "Store Users",
            "group": "users",
            "route_name": "admin.users.store",
            "resource": "users",
            "action": "store",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        },
        {
            "id": 44,
            "name": "update-users",
            "display_name": "Update Users",
            "group": "users",
            "route_name": "admin.users.update",
            "resource": "users",
            "action": "update",
            "created_at": "2026-08-20T12:07:53.000000Z",
            "updated_at": "2026-08-20T12:07:53.000000Z",
            "title": null
        }
    ]
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Permissions retrieved",
    "data": [
        {
            "id": 70,
            "name": "destroy-audit-logs",
            "display_name": "Destroy Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.destroy",
            "resource": "audit-logs",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 66,
            "name": "index-audit-logs",
            "display_name": "Index Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.index",
            "resource": "audit-logs",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 67,
            "name": "show-audit-logs",
            "display_name": "Show Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.show",
            "resource": "audit-logs",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 68,
            "name": "store-audit-logs",
            "display_name": "Store Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.store",
            "resource": "audit-logs",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 69,
            "name": "update-audit-logs",
            "display_name": "Update Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.update",
            "resource": "audit-logs",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 25,
            "name": "destroy-categories",
            "display_name": "Destroy Categories",
            "group": "categories",
            "route_name": "admin.categories.destroy",
            "resource": "categories",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 21,
            "name": "index-categories",
            "display_name": "Index Categories",
            "group": "categories",
            "route_name": "admin.categories.index",
            "resource": "categories",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 22,
            "name": "show-categories",
            "display_name": "Show Categories",
            "group": "categories",
            "route_name": "admin.categories.show",
            "resource": "categories",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 23,
            "name": "store-categories",
            "display_name": "Store Categories",
            "group": "categories",
            "route_name": "admin.categories.store",
            "resource": "categories",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 24,
            "name": "update-categories",
            "display_name": "Update Categories",
            "group": "categories",
            "route_name": "admin.categories.update",
            "resource": "categories",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 75,
            "name": "destroy-contact-messages",
            "display_name": "Destroy Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.destroy",
            "resource": "contact-messages",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 71,
            "name": "index-contact-messages",
            "display_name": "Index Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.index",
            "resource": "contact-messages",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 72,
            "name": "show-contact-messages",
            "display_name": "Show Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.show",
            "resource": "contact-messages",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 73,
            "name": "store-contact-messages",
            "display_name": "Store Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.store",
            "resource": "contact-messages",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 74,
            "name": "update-contact-messages",
            "display_name": "Update Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.update",
            "resource": "contact-messages",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 90,
            "name": "destroy-conversations",
            "display_name": "Destroy Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.destroy",
            "resource": "conversations",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 86,
            "name": "index-conversations",
            "display_name": "Index Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.index",
            "resource": "conversations",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 87,
            "name": "show-conversations",
            "display_name": "Show Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.show",
            "resource": "conversations",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 88,
            "name": "store-conversations",
            "display_name": "Store Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.store",
            "resource": "conversations",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 89,
            "name": "update-conversations",
            "display_name": "Update Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.update",
            "resource": "conversations",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 5,
            "name": "destroy-countries",
            "display_name": "Destroy Countries",
            "group": "countries",
            "route_name": "admin.countries.destroy",
            "resource": "countries",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 1,
            "name": "index-countries",
            "display_name": "Index Countries",
            "group": "countries",
            "route_name": "admin.countries.index",
            "resource": "countries",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 2,
            "name": "show-countries",
            "display_name": "Show Countries",
            "group": "countries",
            "route_name": "admin.countries.show",
            "resource": "countries",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 3,
            "name": "store-countries",
            "display_name": "Store Countries",
            "group": "countries",
            "route_name": "admin.countries.store",
            "resource": "countries",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 4,
            "name": "update-countries",
            "display_name": "Update Countries",
            "group": "countries",
            "route_name": "admin.countries.update",
            "resource": "countries",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 85,
            "name": "destroy-dashboard-home",
            "display_name": "Destroy Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.destroy",
            "resource": "dashboard-home",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 81,
            "name": "index-dashboard-home",
            "display_name": "Index Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.index",
            "resource": "dashboard-home",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 82,
            "name": "show-dashboard-home",
            "display_name": "Show Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.show",
            "resource": "dashboard-home",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 83,
            "name": "store-dashboard-home",
            "display_name": "Store Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.store",
            "resource": "dashboard-home",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 84,
            "name": "update-dashboard-home",
            "display_name": "Update Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.update",
            "resource": "dashboard-home",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 30,
            "name": "destroy-faqs",
            "display_name": "Destroy Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.destroy",
            "resource": "faqs",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 26,
            "name": "index-faqs",
            "display_name": "Index Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.index",
            "resource": "faqs",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 27,
            "name": "show-faqs",
            "display_name": "Show Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.show",
            "resource": "faqs",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 28,
            "name": "store-faqs",
            "display_name": "Store Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.store",
            "resource": "faqs",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 29,
            "name": "update-faqs",
            "display_name": "Update Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.update",
            "resource": "faqs",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 65,
            "name": "destroy-feature-flags",
            "display_name": "Destroy Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.destroy",
            "resource": "feature-flags",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 61,
            "name": "index-feature-flags",
            "display_name": "Index Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.index",
            "resource": "feature-flags",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 62,
            "name": "show-feature-flags",
            "display_name": "Show Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.show",
            "resource": "feature-flags",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 63,
            "name": "store-feature-flags",
            "display_name": "Store Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.store",
            "resource": "feature-flags",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 64,
            "name": "update-feature-flags",
            "display_name": "Update Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.update",
            "resource": "feature-flags",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 10,
            "name": "destroy-governorates",
            "display_name": "Destroy Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.destroy",
            "resource": "governorates",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 6,
            "name": "index-governorates",
            "display_name": "Index Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.index",
            "resource": "governorates",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 7,
            "name": "show-governorates",
            "display_name": "Show Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.show",
            "resource": "governorates",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 8,
            "name": "store-governorates",
            "display_name": "Store Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.store",
            "resource": "governorates",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 9,
            "name": "update-governorates",
            "display_name": "Update Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.update",
            "resource": "governorates",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 95,
            "name": "destroy-internal-notes",
            "display_name": "Destroy Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.destroy",
            "resource": "internal-notes",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 91,
            "name": "index-internal-notes",
            "display_name": "Index Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.index",
            "resource": "internal-notes",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 92,
            "name": "show-internal-notes",
            "display_name": "Show Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.show",
            "resource": "internal-notes",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 93,
            "name": "store-internal-notes",
            "display_name": "Store Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.store",
            "resource": "internal-notes",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 94,
            "name": "update-internal-notes",
            "display_name": "Update Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.update",
            "resource": "internal-notes",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 80,
            "name": "destroy-notifications",
            "display_name": "Destroy Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.destroy",
            "resource": "notifications",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 76,
            "name": "index-notifications",
            "display_name": "Index Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.index",
            "resource": "notifications",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 77,
            "name": "show-notifications",
            "display_name": "Show Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.show",
            "resource": "notifications",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 78,
            "name": "store-notifications",
            "display_name": "Store Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.store",
            "resource": "notifications",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 79,
            "name": "update-notifications",
            "display_name": "Update Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.update",
            "resource": "notifications",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 15,
            "name": "destroy-regions",
            "display_name": "Destroy Regions",
            "group": "regions",
            "route_name": "admin.regions.destroy",
            "resource": "regions",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 11,
            "name": "index-regions",
            "display_name": "Index Regions",
            "group": "regions",
            "route_name": "admin.regions.index",
            "resource": "regions",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 12,
            "name": "show-regions",
            "display_name": "Show Regions",
            "group": "regions",
            "route_name": "admin.regions.show",
            "resource": "regions",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 13,
            "name": "store-regions",
            "display_name": "Store Regions",
            "group": "regions",
            "route_name": "admin.regions.store",
            "resource": "regions",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 14,
            "name": "update-regions",
            "display_name": "Update Regions",
            "group": "regions",
            "route_name": "admin.regions.update",
            "resource": "regions",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 55,
            "name": "destroy-roles",
            "display_name": "Destroy Roles",
            "group": "roles",
            "route_name": "admin.roles.destroy",
            "resource": "roles",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 51,
            "name": "index-roles",
            "display_name": "Index Roles",
            "group": "roles",
            "route_name": "admin.roles.index",
            "resource": "roles",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 52,
            "name": "show-roles",
            "display_name": "Show Roles",
            "group": "roles",
            "route_name": "admin.roles.show",
            "resource": "roles",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 53,
            "name": "store-roles",
            "display_name": "Store Roles",
            "group": "roles",
            "route_name": "admin.roles.store",
            "resource": "roles",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 54,
            "name": "update-roles",
            "display_name": "Update Roles",
            "group": "roles",
            "route_name": "admin.roles.update",
            "resource": "roles",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 60,
            "name": "destroy-settings",
            "display_name": "Destroy Settings",
            "group": "settings",
            "route_name": "admin.settings.destroy",
            "resource": "settings",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 56,
            "name": "index-settings",
            "display_name": "Index Settings",
            "group": "settings",
            "route_name": "admin.settings.index",
            "resource": "settings",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 57,
            "name": "show-settings",
            "display_name": "Show Settings",
            "group": "settings",
            "route_name": "admin.settings.show",
            "resource": "settings",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 58,
            "name": "store-settings",
            "display_name": "Store Settings",
            "group": "settings",
            "route_name": "admin.settings.store",
            "resource": "settings",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 59,
            "name": "update-settings",
            "display_name": "Update Settings",
            "group": "settings",
            "route_name": "admin.settings.update",
            "resource": "settings",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 20,
            "name": "destroy-shipping-zones",
            "display_name": "Destroy Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.destroy",
            "resource": "shipping-zones",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 16,
            "name": "index-shipping-zones",
            "display_name": "Index Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.index",
            "resource": "shipping-zones",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 17,
            "name": "show-shipping-zones",
            "display_name": "Show Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.show",
            "resource": "shipping-zones",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 18,
            "name": "store-shipping-zones",
            "display_name": "Store Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.store",
            "resource": "shipping-zones",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 19,
            "name": "update-shipping-zones",
            "display_name": "Update Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.update",
            "resource": "shipping-zones",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 40,
            "name": "destroy-sliders",
            "display_name": "Destroy Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.destroy",
            "resource": "sliders",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 36,
            "name": "index-sliders",
            "display_name": "Index Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.index",
            "resource": "sliders",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 37,
            "name": "show-sliders",
            "display_name": "Show Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.show",
            "resource": "sliders",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 38,
            "name": "store-sliders",
            "display_name": "Store Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.store",
            "resource": "sliders",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 39,
            "name": "update-sliders",
            "display_name": "Update Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.update",
            "resource": "sliders",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 35,
            "name": "destroy-static-pages",
            "display_name": "Destroy Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.destroy",
            "resource": "static-pages",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 31,
            "name": "index-static-pages",
            "display_name": "Index Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.index",
            "resource": "static-pages",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 32,
            "name": "show-static-pages",
            "display_name": "Show Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.show",
            "resource": "static-pages",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 33,
            "name": "store-static-pages",
            "display_name": "Store Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.store",
            "resource": "static-pages",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 34,
            "name": "update-static-pages",
            "display_name": "Update Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.update",
            "resource": "static-pages",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 50,
            "name": "destroy-supervisors",
            "display_name": "Destroy Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.destroy",
            "resource": "supervisors",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 46,
            "name": "index-supervisors",
            "display_name": "Index Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.index",
            "resource": "supervisors",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 47,
            "name": "show-supervisors",
            "display_name": "Show Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.show",
            "resource": "supervisors",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 48,
            "name": "store-supervisors",
            "display_name": "Store Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.store",
            "resource": "supervisors",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 49,
            "name": "update-supervisors",
            "display_name": "Update Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.update",
            "resource": "supervisors",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 45,
            "name": "destroy-users",
            "display_name": "Destroy Users",
            "group": "users",
            "route_name": "admin.users.destroy",
            "resource": "users",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 41,
            "name": "index-users",
            "display_name": "Index Users",
            "group": "users",
            "route_name": "admin.users.index",
            "resource": "users",
            "action": "index",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 42,
            "name": "show-users",
            "display_name": "Show Users",
            "group": "users",
            "route_name": "admin.users.show",
            "resource": "users",
            "action": "show",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 43,
            "name": "store-users",
            "display_name": "Store Users",
            "group": "users",
            "route_name": "admin.users.store",
            "resource": "users",
            "action": "store",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        },
        {
            "id": 44,
            "name": "update-users",
            "display_name": "Update Users",
            "group": "users",
            "route_name": "admin.users.update",
            "resource": "users",
            "action": "update",
            "created_at": "2026-08-20T12:09:25.000000Z",
            "updated_at": "2026-08-20T12:09:25.000000Z",
            "title": null
        }
    ]
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Permissions retrieved",
    "data": [
        {
            "id": 70,
            "name": "destroy-audit-logs",
            "display_name": "Destroy Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.destroy",
            "resource": "audit-logs",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 66,
            "name": "index-audit-logs",
            "display_name": "Index Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.index",
            "resource": "audit-logs",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 67,
            "name": "show-audit-logs",
            "display_name": "Show Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.show",
            "resource": "audit-logs",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 68,
            "name": "store-audit-logs",
            "display_name": "Store Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.store",
            "resource": "audit-logs",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 69,
            "name": "update-audit-logs",
            "display_name": "Update Audit logs",
            "group": "audit-logs",
            "route_name": "admin.audit-logs.update",
            "resource": "audit-logs",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 25,
            "name": "destroy-categories",
            "display_name": "Destroy Categories",
            "group": "categories",
            "route_name": "admin.categories.destroy",
            "resource": "categories",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 21,
            "name": "index-categories",
            "display_name": "Index Categories",
            "group": "categories",
            "route_name": "admin.categories.index",
            "resource": "categories",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 22,
            "name": "show-categories",
            "display_name": "Show Categories",
            "group": "categories",
            "route_name": "admin.categories.show",
            "resource": "categories",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 23,
            "name": "store-categories",
            "display_name": "Store Categories",
            "group": "categories",
            "route_name": "admin.categories.store",
            "resource": "categories",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 24,
            "name": "update-categories",
            "display_name": "Update Categories",
            "group": "categories",
            "route_name": "admin.categories.update",
            "resource": "categories",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 75,
            "name": "destroy-contact-messages",
            "display_name": "Destroy Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.destroy",
            "resource": "contact-messages",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 71,
            "name": "index-contact-messages",
            "display_name": "Index Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.index",
            "resource": "contact-messages",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 72,
            "name": "show-contact-messages",
            "display_name": "Show Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.show",
            "resource": "contact-messages",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 73,
            "name": "store-contact-messages",
            "display_name": "Store Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.store",
            "resource": "contact-messages",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 74,
            "name": "update-contact-messages",
            "display_name": "Update Contact messages",
            "group": "contact-messages",
            "route_name": "admin.contact-messages.update",
            "resource": "contact-messages",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 90,
            "name": "destroy-conversations",
            "display_name": "Destroy Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.destroy",
            "resource": "conversations",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 86,
            "name": "index-conversations",
            "display_name": "Index Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.index",
            "resource": "conversations",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 87,
            "name": "show-conversations",
            "display_name": "Show Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.show",
            "resource": "conversations",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 88,
            "name": "store-conversations",
            "display_name": "Store Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.store",
            "resource": "conversations",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 89,
            "name": "update-conversations",
            "display_name": "Update Conversations",
            "group": "conversations",
            "route_name": "admin.conversations.update",
            "resource": "conversations",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 5,
            "name": "destroy-countries",
            "display_name": "Destroy Countries",
            "group": "countries",
            "route_name": "admin.countries.destroy",
            "resource": "countries",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 1,
            "name": "index-countries",
            "display_name": "Index Countries",
            "group": "countries",
            "route_name": "admin.countries.index",
            "resource": "countries",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 2,
            "name": "show-countries",
            "display_name": "Show Countries",
            "group": "countries",
            "route_name": "admin.countries.show",
            "resource": "countries",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 3,
            "name": "store-countries",
            "display_name": "Store Countries",
            "group": "countries",
            "route_name": "admin.countries.store",
            "resource": "countries",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 4,
            "name": "update-countries",
            "display_name": "Update Countries",
            "group": "countries",
            "route_name": "admin.countries.update",
            "resource": "countries",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 85,
            "name": "destroy-dashboard-home",
            "display_name": "Destroy Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.destroy",
            "resource": "dashboard-home",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 81,
            "name": "index-dashboard-home",
            "display_name": "Index Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.index",
            "resource": "dashboard-home",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 82,
            "name": "show-dashboard-home",
            "display_name": "Show Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.show",
            "resource": "dashboard-home",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 83,
            "name": "store-dashboard-home",
            "display_name": "Store Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.store",
            "resource": "dashboard-home",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 84,
            "name": "update-dashboard-home",
            "display_name": "Update Dashboard home",
            "group": "dashboard-home",
            "route_name": "admin.dashboard-home.update",
            "resource": "dashboard-home",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 30,
            "name": "destroy-faqs",
            "display_name": "Destroy Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.destroy",
            "resource": "faqs",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 26,
            "name": "index-faqs",
            "display_name": "Index Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.index",
            "resource": "faqs",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 27,
            "name": "show-faqs",
            "display_name": "Show Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.show",
            "resource": "faqs",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 28,
            "name": "store-faqs",
            "display_name": "Store Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.store",
            "resource": "faqs",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 29,
            "name": "update-faqs",
            "display_name": "Update Faqs",
            "group": "faqs",
            "route_name": "admin.faqs.update",
            "resource": "faqs",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 65,
            "name": "destroy-feature-flags",
            "display_name": "Destroy Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.destroy",
            "resource": "feature-flags",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 61,
            "name": "index-feature-flags",
            "display_name": "Index Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.index",
            "resource": "feature-flags",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 62,
            "name": "show-feature-flags",
            "display_name": "Show Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.show",
            "resource": "feature-flags",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 63,
            "name": "store-feature-flags",
            "display_name": "Store Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.store",
            "resource": "feature-flags",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 64,
            "name": "update-feature-flags",
            "display_name": "Update Feature flags",
            "group": "feature-flags",
            "route_name": "admin.feature-flags.update",
            "resource": "feature-flags",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 10,
            "name": "destroy-governorates",
            "display_name": "Destroy Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.destroy",
            "resource": "governorates",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 6,
            "name": "index-governorates",
            "display_name": "Index Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.index",
            "resource": "governorates",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 7,
            "name": "show-governorates",
            "display_name": "Show Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.show",
            "resource": "governorates",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 8,
            "name": "store-governorates",
            "display_name": "Store Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.store",
            "resource": "governorates",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 9,
            "name": "update-governorates",
            "display_name": "Update Governorates",
            "group": "governorates",
            "route_name": "admin.governorates.update",
            "resource": "governorates",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 95,
            "name": "destroy-internal-notes",
            "display_name": "Destroy Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.destroy",
            "resource": "internal-notes",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 91,
            "name": "index-internal-notes",
            "display_name": "Index Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.index",
            "resource": "internal-notes",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 92,
            "name": "show-internal-notes",
            "display_name": "Show Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.show",
            "resource": "internal-notes",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 93,
            "name": "store-internal-notes",
            "display_name": "Store Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.store",
            "resource": "internal-notes",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 94,
            "name": "update-internal-notes",
            "display_name": "Update Internal notes",
            "group": "internal-notes",
            "route_name": "admin.internal-notes.update",
            "resource": "internal-notes",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 80,
            "name": "destroy-notifications",
            "display_name": "Destroy Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.destroy",
            "resource": "notifications",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 76,
            "name": "index-notifications",
            "display_name": "Index Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.index",
            "resource": "notifications",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 77,
            "name": "show-notifications",
            "display_name": "Show Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.show",
            "resource": "notifications",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 78,
            "name": "store-notifications",
            "display_name": "Store Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.store",
            "resource": "notifications",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 79,
            "name": "update-notifications",
            "display_name": "Update Notifications",
            "group": "notifications",
            "route_name": "admin.notifications.update",
            "resource": "notifications",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 15,
            "name": "destroy-regions",
            "display_name": "Destroy Regions",
            "group": "regions",
            "route_name": "admin.regions.destroy",
            "resource": "regions",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 11,
            "name": "index-regions",
            "display_name": "Index Regions",
            "group": "regions",
            "route_name": "admin.regions.index",
            "resource": "regions",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 12,
            "name": "show-regions",
            "display_name": "Show Regions",
            "group": "regions",
            "route_name": "admin.regions.show",
            "resource": "regions",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 13,
            "name": "store-regions",
            "display_name": "Store Regions",
            "group": "regions",
            "route_name": "admin.regions.store",
            "resource": "regions",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 14,
            "name": "update-regions",
            "display_name": "Update Regions",
            "group": "regions",
            "route_name": "admin.regions.update",
            "resource": "regions",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 55,
            "name": "destroy-roles",
            "display_name": "Destroy Roles",
            "group": "roles",
            "route_name": "admin.roles.destroy",
            "resource": "roles",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 51,
            "name": "index-roles",
            "display_name": "Index Roles",
            "group": "roles",
            "route_name": "admin.roles.index",
            "resource": "roles",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 52,
            "name": "show-roles",
            "display_name": "Show Roles",
            "group": "roles",
            "route_name": "admin.roles.show",
            "resource": "roles",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 53,
            "name": "store-roles",
            "display_name": "Store Roles",
            "group": "roles",
            "route_name": "admin.roles.store",
            "resource": "roles",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 54,
            "name": "update-roles",
            "display_name": "Update Roles",
            "group": "roles",
            "route_name": "admin.roles.update",
            "resource": "roles",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 60,
            "name": "destroy-settings",
            "display_name": "Destroy Settings",
            "group": "settings",
            "route_name": "admin.settings.destroy",
            "resource": "settings",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 56,
            "name": "index-settings",
            "display_name": "Index Settings",
            "group": "settings",
            "route_name": "admin.settings.index",
            "resource": "settings",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 57,
            "name": "show-settings",
            "display_name": "Show Settings",
            "group": "settings",
            "route_name": "admin.settings.show",
            "resource": "settings",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 58,
            "name": "store-settings",
            "display_name": "Store Settings",
            "group": "settings",
            "route_name": "admin.settings.store",
            "resource": "settings",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 59,
            "name": "update-settings",
            "display_name": "Update Settings",
            "group": "settings",
            "route_name": "admin.settings.update",
            "resource": "settings",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 20,
            "name": "destroy-shipping-zones",
            "display_name": "Destroy Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.destroy",
            "resource": "shipping-zones",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 16,
            "name": "index-shipping-zones",
            "display_name": "Index Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.index",
            "resource": "shipping-zones",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 17,
            "name": "show-shipping-zones",
            "display_name": "Show Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.show",
            "resource": "shipping-zones",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 18,
            "name": "store-shipping-zones",
            "display_name": "Store Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.store",
            "resource": "shipping-zones",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 19,
            "name": "update-shipping-zones",
            "display_name": "Update Shipping zones",
            "group": "shipping-zones",
            "route_name": "admin.shipping-zones.update",
            "resource": "shipping-zones",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 40,
            "name": "destroy-sliders",
            "display_name": "Destroy Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.destroy",
            "resource": "sliders",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 36,
            "name": "index-sliders",
            "display_name": "Index Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.index",
            "resource": "sliders",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 37,
            "name": "show-sliders",
            "display_name": "Show Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.show",
            "resource": "sliders",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 38,
            "name": "store-sliders",
            "display_name": "Store Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.store",
            "resource": "sliders",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 39,
            "name": "update-sliders",
            "display_name": "Update Sliders",
            "group": "sliders",
            "route_name": "admin.sliders.update",
            "resource": "sliders",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 35,
            "name": "destroy-static-pages",
            "display_name": "Destroy Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.destroy",
            "resource": "static-pages",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 31,
            "name": "index-static-pages",
            "display_name": "Index Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.index",
            "resource": "static-pages",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 32,
            "name": "show-static-pages",
            "display_name": "Show Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.show",
            "resource": "static-pages",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 33,
            "name": "store-static-pages",
            "display_name": "Store Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.store",
            "resource": "static-pages",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 34,
            "name": "update-static-pages",
            "display_name": "Update Static pages",
            "group": "static-pages",
            "route_name": "admin.static-pages.update",
            "resource": "static-pages",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 50,
            "name": "destroy-supervisors",
            "display_name": "Destroy Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.destroy",
            "resource": "supervisors",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 46,
            "name": "index-supervisors",
            "display_name": "Index Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.index",
            "resource": "supervisors",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 47,
            "name": "show-supervisors",
            "display_name": "Show Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.show",
            "resource": "supervisors",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 48,
            "name": "store-supervisors",
            "display_name": "Store Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.store",
            "resource": "supervisors",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 49,
            "name": "update-supervisors",
            "display_name": "Update Supervisors",
            "group": "supervisors",
            "route_name": "admin.supervisors.update",
            "resource": "supervisors",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 45,
            "name": "destroy-users",
            "display_name": "Destroy Users",
            "group": "users",
            "route_name": "admin.users.destroy",
            "resource": "users",
            "action": "destroy",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 41,
            "name": "index-users",
            "display_name": "Index Users",
            "group": "users",
            "route_name": "admin.users.index",
            "resource": "users",
            "action": "index",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 42,
            "name": "show-users",
            "display_name": "Show Users",
            "group": "users",
            "route_name": "admin.users.show",
            "resource": "users",
            "action": "show",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 43,
            "name": "store-users",
            "display_name": "Store Users",
            "group": "users",
            "route_name": "admin.users.store",
            "resource": "users",
            "action": "store",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        },
        {
            "id": 44,
            "name": "update-users",
            "display_name": "Update Users",
            "group": "users",
            "route_name": "admin.users.update",
            "resource": "users",
            "action": "update",
            "created_at": "2026-08-20T12:09:46.000000Z",
            "updated_at": "2026-08-20T12:09:46.000000Z",
            "title": null
        }
    ]
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### List All Roles

**What this does:** Returns a paginated, filterable, searchable list of roles.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/roles?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.roles.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `roles.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status (optional)

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "roles": [
            {
                "id": 1,
                "name": "Existing Role",
                "slug": "existing-role-6a86ee1977aba",
                "parent_id": null,
                "level": 0,
                "is_active": true,
                "permissions": [],
                "created_at": "2026-08-20 12:07:53"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/roles?page=1",
            "last": "http://localhost/api/v1/admin/roles?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/roles?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/roles",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "roles": [
            {
                "id": 1,
                "name": "Existing Role",
                "slug": "existing-role-6a86ee759cae6",
                "parent_id": null,
                "level": 0,
                "is_active": true,
                "permissions": [],
                "created_at": "2026-08-20 12:09:25"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/roles?page=1",
            "last": "http://localhost/api/v1/admin/roles?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/roles?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/roles",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "roles": [
            {
                "id": 1,
                "name": "Existing Role",
                "slug": "existing-role-6a86ee8abc050",
                "parent_id": null,
                "level": 0,
                "is_active": true,
                "permissions": [],
                "created_at": "2026-08-20 12:09:46"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/roles?page=1",
            "last": "http://localhost/api/v1/admin/roles?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/roles?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/roles",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### List All Supervisors

**What this does:** Returns a paginated, filterable, searchable list of supervisors.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/supervisors?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.supervisors.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `supervisors.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "users": [
            {
                "id": 28,
                "full_name": "Mrs. Alexandrine Waelchi",
                "email": "vena01@example.com",
                "phone": "1175962205",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "Admin",
                "is_active": true,
                "roles": [
                    {
                        "id": 6,
                        "name": "Supervisor Role",
                        "slug": "supervisor-role-6a86ee198c8c8"
                    }
                ],
                "created_at": "2026-08-20 12:07:53"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/supervisors?page=1",
            "last": "http://localhost/api/v1/admin/supervisors?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/supervisors?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/supervisors",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "users": [
            {
                "id": 138,
                "full_name": "Eryn Terry DVM",
                "email": "stanton.phyllis@example.org",
                "phone": "1513388058",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "Admin",
                "is_active": true,
                "roles": [
                    {
                        "id": 6,
                        "name": "Supervisor Role",
                        "slug": "supervisor-role-6a86ee75bad47"
                    }
                ],
                "created_at": "2026-08-20 12:09:25"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/supervisors?page=1",
            "last": "http://localhost/api/v1/admin/supervisors?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/supervisors?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/supervisors",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "users": [
            {
                "id": 138,
                "full_name": "Jeromy Kautzer",
                "email": "lcorwin@example.org",
                "phone": "1570935034",
                "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
                "user_type": "Admin",
                "is_active": true,
                "roles": [
                    {
                        "id": 6,
                        "name": "Supervisor Role",
                        "slug": "supervisor-role-6a86ee8adabae"
                    }
                ],
                "created_at": "2026-08-20 12:09:46"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/supervisors?page=1",
            "last": "http://localhost/api/v1/admin/supervisors?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/supervisors?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/supervisors",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### Show Role Details

**What this does:** Returns full details for one role.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/roles/:role` |
| **Route name** | `admin.roles.show` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `roles.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `role` — Role ID — seeded example: `3`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 2,
        "name": "Support Agent",
        "slug": "support-agent-6a86ee1979f23",
        "parent_id": null,
        "level": 0,
        "is_active": true,
        "permissions": [
            {
                "id": 25,
                "name": "destroy-categories",
                "slug": null,
                "action": "destroy",
                "resource": "categories"
            },
            {
                "id": 70,
                "name": "destroy-audit-logs",
                "slug": null,
                "action": "destroy",
                "resource": "audit-logs"
            },
            {
                "id": 75,
                "name": "destroy-contact-messages",
                "slug": null,
                "action": "destroy",
                "resource": "contact-messages"
            }
        ],
        "created_at": "2026-08-20 12:07:53",
        "updated_at": "2026-08-20 12:07:53",
        "en": {
            "name": "Support Agent"
        },
        "ar": {
            "name": "موظف دعم"
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 2,
        "name": "Support Agent",
        "slug": "support-agent-6a86ee75a03cf",
        "parent_id": null,
        "level": 0,
        "is_active": true,
        "permissions": [
            {
                "id": 25,
                "name": "destroy-categories",
                "slug": null,
                "action": "destroy",
                "resource": "categories"
            },
            {
                "id": 70,
                "name": "destroy-audit-logs",
                "slug": null,
                "action": "destroy",
                "resource": "audit-logs"
            },
            {
                "id": 75,
                "name": "destroy-contact-messages",
                "slug": null,
                "action": "destroy",
                "resource": "contact-messages"
            }
        ],
        "created_at": "2026-08-20 12:09:25",
        "updated_at": "2026-08-20 12:09:25",
        "en": {
            "name": "Support Agent"
        },
        "ar": {
            "name": "موظف دعم"
        }
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 2,
        "name": "Support Agent",
        "slug": "support-agent-6a86ee8abecc3",
        "parent_id": null,
        "level": 0,
        "is_active": true,
        "permissions": [
            {
                "id": 25,
                "name": "destroy-categories",
                "slug": null,
                "action": "destroy",
                "resource": "categories"
            },
            {
                "id": 70,
                "name": "destroy-audit-logs",
                "slug": null,
                "action": "destroy",
                "resource": "audit-logs"
            },
            {
                "id": 75,
                "name": "destroy-contact-messages",
                "slug": null,
                "action": "destroy",
                "resource": "contact-messages"
            }
        ],
        "created_at": "2026-08-20 12:09:46",
        "updated_at": "2026-08-20 12:09:46",
        "en": {
            "name": "Support Agent"
        },
        "ar": {
            "name": "موظف دعم"
        }
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use `update` to modify it, or `destroy` to remove it.

---

#### Show Supervisor Details

**What this does:** Returns full details for one supervisor.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/supervisors/:supervisor` |
| **Route name** | `admin.supervisors.show` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `supervisors.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `supervisor` — Supervisor ID — seeded example: `2`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 29,
        "full_name": "New Supervisor",
        "email": "supervisor.store@example.com",
        "phone": "1077700001",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "Admin",
        "is_active": true,
        "roles": [
            {
                "id": 6,
                "name": "Supervisor Role",
                "slug": "supervisor-role-6a86ee198c8c8"
            }
        ],
        "created_at": "2026-08-20 12:07:53",
        "permissions": [],
        "updated_at": "2026-08-20 12:07:53"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 139,
        "full_name": "New Supervisor",
        "email": "supervisor.store@example.com",
        "phone": "1077700001",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "Admin",
        "is_active": true,
        "roles": [
            {
                "id": 6,
                "name": "Supervisor Role",
                "slug": "supervisor-role-6a86ee75bad47"
            }
        ],
        "created_at": "2026-08-20 12:09:25",
        "permissions": [],
        "updated_at": "2026-08-20 12:09:25"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 139,
        "full_name": "New Supervisor",
        "email": "supervisor.store@example.com",
        "phone": "1077700001",
        "image": "https://ui-avatars.com/api/?name=U&background=dbeafe&color=1d4ed8&size=200",
        "user_type": "Admin",
        "is_active": true,
        "roles": [
            {
                "id": 6,
                "name": "Supervisor Role",
                "slug": "supervisor-role-6a86ee8adabae"
            }
        ],
        "created_at": "2026-08-20 12:09:46",
        "permissions": [],
        "updated_at": "2026-08-20 12:09:46"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use `update` to modify it, or `destroy` to remove it.

---

#### Create New Role

**What this does:** Creates a new role.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/roles` |
| **Route name** | `admin.roles.store` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `roles.create` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `201 Created`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `slug`
- **Description:** Slug
- **Type:** `string`
- **Required:** required
- **Example:** `example-slug`
- **Validation rules:** `required|string|max:50|unique:roles,slug,NULL,id`
- `required` — must be provided.
- `string` — must be text.
- `max:50` — must not exceed 50.
- `unique:roles,slug,NULL,id` — must be unique (roles, slug, NULL, id).
### `is_active`
- **Description:** Is Active
- **Type:** `boolean`
- **Required:** optional
- **Example:** `true`
- **Validation rules:** `sometimes|boolean`
- `sometimes` — validated only when the field is present.
- `boolean` — must be true, false, 1, or 0.
### `parent_id`
- **Description:** Parent Role
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|exists:roles,id`
- `nullable` — may be null.
- `exists:roles,id` — must reference an existing record (roles, id).
### `permissions`
- **Description:** Permissions
- **Type:** `array`
- **Required:** optional
- **Example:** `[1]`
- **Validation rules:** `nullable|array`
- `nullable` — may be null.
- `array` — must be an array.
### `permissions.*`
- **Description:** Permission
- **Type:** `integer`
- **Required:** optional
- **Example:** `4`
- **Validation rules:** `exists:permissions,id`
- `exists:permissions,id` — must reference an existing record (permissions, id).
### `en.name`
- **Description:** Name (en)
- **Type:** `string`
- **Required:** required
- **Example:** `Example Name`
- **Validation rules:** `required|string|max:255`
- `required` — must be provided.
- `string` — must be text.
- `max:255` — must not exceed 255.
### `ar.name`
- **Description:** Name (ar)
- **Type:** `string`
- **Required:** required
- **Example:** `Example Name`
- **Validation rules:** `required|string|max:255`
- `required` — must be provided.
- `string` — must be text.
- `max:255` — must not exceed 255.

**Example Request Body:**
```json
{
    "slug": "support-agent-6a86ee1979f23",
    "is_active": true,
    "permissions": [
        4,
        25,
        75
    ],
    "en": {
        "name": "Support Agent"
    },
    "ar": {
        "name": "موظف دعم"
    }
}
```

**Actual Success Response(s):**

*{ 201 Created — Created }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 2,
        "slug": "support-agent-6a86ee1979f23",
        "description": null,
        "parent_id": null,
        "level": 0,
        "is_active": true,
        "created_at": "2026-08-20T12:07:53.000000Z",
        "updated_at": "2026-08-20T12:07:53.000000Z",
        "name": "Support Agent"
    }
}
```

*{ 201 Created — Created }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 2,
        "slug": "support-agent-6a86ee75a03cf",
        "description": null,
        "parent_id": null,
        "level": 0,
        "is_active": true,
        "created_at": "2026-08-20T12:09:25.000000Z",
        "updated_at": "2026-08-20T12:09:25.000000Z",
        "name": "Support Agent"
    }
}
```

*{ 201 Created — Created }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 2,
        "slug": "support-agent-6a86ee8abecc3",
        "description": null,
        "parent_id": null,
        "level": 0,
        "is_active": true,
        "created_at": "2026-08-20T12:09:46.000000Z",
        "updated_at": "2026-08-20T12:09:46.000000Z",
        "name": "Support Agent"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "The Slug field is required.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - duplicate slug }*
```json
{
    "status": "fail",
    "message": "This slug is already in use.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "The Slug field is required.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - duplicate slug }*
```json
{
    "status": "fail",
    "message": "This slug is already in use.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "The Slug field is required.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - duplicate slug }*
```json
{
    "status": "fail",
    "message": "This slug is already in use.",
    "data": null
}
```

**What happens next:** Use the returned id with `show`/`update`/`destroy` for this role.

---

#### Create New Supervisor

**What this does:** Creates a new supervisor.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/supervisors` |
| **Route name** | `admin.supervisors.store` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `supervisors.create` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `201 Created`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `full_name`
- **Description:** Full Name
- **Type:** `string`
- **Required:** required
- **Example:** `Example Name`
- **Validation rules:** `required|string|max:255`
- `required` — must be provided.
- `string` — must be text.
- `max:255` — must not exceed 255.
### `email`
- **Description:** Email
- **Type:** `string`
- **Required:** required
- **Example:** `user@example.com`
- **Validation rules:** `required|email|max:255|unique:users,email,NULL,id`
- `required` — must be provided.
- `email` — must be a valid email address.
- `max:255` — must not exceed 255.
- `unique:users,email,NULL,id` — must be unique (users, email, NULL, id).
### `phone`
- **Description:** Phone
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `nullable|string|max:20|unique:users,phone,NULL,id`
- `nullable` — may be null.
- `string` — must be text.
- `max:20` — must not exceed 20.
- `unique:users,phone,NULL,id` — must be unique (users, phone, NULL, id).
### `password`
- **Description:** Password
- **Type:** `string`
- **Required:** required
- **Example:** `Password123!`
- **Validation rules:** `required|nullable|string|min:8`
- `required` — must be provided.
- `nullable` — may be null.
- `string` — must be text.
- `min:8` — must be at least 8.
### `is_active`
- **Description:** Is Active
- **Type:** `boolean`
- **Required:** optional
- **Example:** `true`
- **Validation rules:** `sometimes|boolean`
- `sometimes` — validated only when the field is present.
- `boolean` — must be true, false, 1, or 0.
### `role_id`
- **Description:** Role
- **Type:** `integer`
- **Required:** required
- **Example:** `3`
- **Validation rules:** `required|exists:roles,id`
- `required` — must be provided.
- `exists:roles,id` — must reference an existing record (roles, id).
### `image`
- **Description:** Image
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `nullable|string|custom:MediaExists`
- `nullable` — may be null.
- `string` — must be text.
- `custom:MediaExists` — custom validation rule.

**Example Request Body:**
```json
{
    "full_name": "New Supervisor",
    "email": "supervisor.store@example.com",
    "phone": "1077700001",
    "password": "password123",
    "is_active": true,
    "role_id": 3
}
```

**Actual Success Response(s):**

*{ 201 Created — Created }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 29,
        "name": "New Supervisor",
        "email": "supervisor.store@example.com",
        "phone": "1077700001",
        "username": null,
        "user_type": "admin",
        "status": "active",
        "email_verified_at": null,
        "phone_verified_at": null,
        "locale": "ar",
        "allow_notifications": true,
        "timezone": "Asia/Riyadh",
        "avatar_path": null,
        "last_login_at": null,
        "suspended_at": null,
        "suspension_reason": null,
        "created_at": "2026-08-20T12:07:53.000000Z",
        "updated_at": "2026-08-20T12:07:53.000000Z",
        "deleted_at": null
    }
}
```

*{ 201 Created — Created }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 139,
        "name": "New Supervisor",
        "email": "supervisor.store@example.com",
        "phone": "1077700001",
        "username": null,
        "user_type": "admin",
        "status": "active",
        "email_verified_at": null,
        "phone_verified_at": null,
        "locale": "ar",
        "allow_notifications": true,
        "timezone": "Asia/Riyadh",
        "avatar_path": null,
        "last_login_at": null,
        "suspended_at": null,
        "suspension_reason": null,
        "created_at": "2026-08-20T12:09:25.000000Z",
        "updated_at": "2026-08-20T12:09:25.000000Z",
        "deleted_at": null
    }
}
```

*{ 201 Created — Created }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 139,
        "name": "New Supervisor",
        "email": "supervisor.store@example.com",
        "phone": "1077700001",
        "username": null,
        "user_type": "admin",
        "status": "active",
        "email_verified_at": null,
        "phone_verified_at": null,
        "locale": "ar",
        "allow_notifications": true,
        "timezone": "Asia/Riyadh",
        "avatar_path": null,
        "last_login_at": null,
        "suspended_at": null,
        "suspension_reason": null,
        "created_at": "2026-08-20T12:09:46.000000Z",
        "updated_at": "2026-08-20T12:09:46.000000Z",
        "deleted_at": null
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter your full name.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - invalid role_id }*
```json
{
    "status": "fail",
    "message": "The selected role does not exist.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter your full name.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - invalid role_id }*
```json
{
    "status": "fail",
    "message": "The selected role does not exist.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter your full name.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - invalid role_id }*
```json
{
    "status": "fail",
    "message": "The selected role does not exist.",
    "data": null
}
```

**What happens next:** Use the returned id with `show`/`update`/`destroy` for this supervisor.

---

#### Update Role

**What this does:** Updates an existing role.

| | |
|---|---|
| **Method** | `PUT` |
| **Endpoint** | `{{base_url}}/api/v1/admin/roles/:role` |
| **Route name** | `admin.roles.update` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `roles.update` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `role` — Role ID — seeded example: `3`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `slug`
- **Description:** Slug
- **Type:** `string`
- **Required:** optional
- **Example:** `example-slug`
- **Validation rules:** `sometimes|string|max:50|unique:roles,slug,NULL,id`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:50` — must not exceed 50.
- `unique:roles,slug,NULL,id` — must be unique (roles, slug, NULL, id).
### `is_active`
- **Description:** Is Active
- **Type:** `boolean`
- **Required:** optional
- **Example:** `true`
- **Validation rules:** `sometimes|boolean`
- `sometimes` — validated only when the field is present.
- `boolean` — must be true, false, 1, or 0.
### `parent_id`
- **Description:** Parent Role
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|exists:roles,id`
- `nullable` — may be null.
- `exists:roles,id` — must reference an existing record (roles, id).
### `permissions`
- **Description:** Permissions
- **Type:** `array`
- **Required:** optional
- **Example:** `[1]`
- **Validation rules:** `nullable|array`
- `nullable` — may be null.
- `array` — must be an array.
### `permissions.*`
- **Description:** Permission
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `exists:permissions,id`
- `exists:permissions,id` — must reference an existing record (permissions, id).
### `en.name`
- **Description:** Name (en)
- **Type:** `string`
- **Required:** optional
- **Example:** `Example Name`
- **Validation rules:** `sometimes|string|max:255`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:255` — must not exceed 255.
### `ar.name`
- **Description:** Name (ar)
- **Type:** `string`
- **Required:** optional
- **Example:** `Example Name`
- **Validation rules:** `sometimes|string|max:255`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:255` — must not exceed 255.

**Example Request Body:**
```json
{
    "en": {
        "name": "Support Agent (Updated)"
    },
    "ar": {
        "name": "موظف دعم (محدث)"
    }
}
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 2,
        "slug": "support-agent-6a86ee1979f23",
        "description": null,
        "parent_id": null,
        "level": 0,
        "is_active": true,
        "created_at": "2026-08-20T12:07:53.000000Z",
        "updated_at": "2026-08-20T12:07:53.000000Z",
        "name": "Support Agent (Updated)"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 2,
        "slug": "support-agent-6a86ee75a03cf",
        "description": null,
        "parent_id": null,
        "level": 0,
        "is_active": true,
        "created_at": "2026-08-20T12:09:25.000000Z",
        "updated_at": "2026-08-20T12:09:25.000000Z",
        "name": "Support Agent (Updated)"
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 2,
        "slug": "support-agent-6a86ee8abecc3",
        "description": null,
        "parent_id": null,
        "level": 0,
        "is_active": true,
        "created_at": "2026-08-20T12:09:46.000000Z",
        "updated_at": "2026-08-20T12:09:46.000000Z",
        "name": "Support Agent (Updated)"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error - invalid permission id }*
```json
{
    "status": "fail",
    "message": "The selected Permission is invalid.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - invalid permission id }*
```json
{
    "status": "fail",
    "message": "The selected Permission is invalid.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error - invalid permission id }*
```json
{
    "status": "fail",
    "message": "The selected Permission is invalid.",
    "data": null
}
```

**What happens next:** Fetch `show` to confirm the change.

---

#### Update Supervisor

**What this does:** Updates an existing supervisor.

| | |
|---|---|
| **Method** | `PUT` |
| **Endpoint** | `{{base_url}}/api/v1/admin/supervisors/:supervisor` |
| **Route name** | `admin.supervisors.update` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `supervisors.update` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `supervisor` — Supervisor ID — seeded example: `2`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `full_name`
- **Description:** Full Name
- **Type:** `string`
- **Required:** optional
- **Example:** `Example Name`
- **Validation rules:** `sometimes|string|max:255`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:255` — must not exceed 255.
### `email`
- **Description:** Email
- **Type:** `string`
- **Required:** optional
- **Example:** `user@example.com`
- **Validation rules:** `sometimes|email|max:255|unique:users,email,NULL,id`
- `sometimes` — validated only when the field is present.
- `email` — must be a valid email address.
- `max:255` — must not exceed 255.
- `unique:users,email,NULL,id` — must be unique (users, email, NULL, id).
### `phone`
- **Description:** Phone
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `nullable|string|max:20|unique:users,phone,NULL,id`
- `nullable` — may be null.
- `string` — must be text.
- `max:20` — must not exceed 20.
- `unique:users,phone,NULL,id` — must be unique (users, phone, NULL, id).
### `password`
- **Description:** Password
- **Type:** `string`
- **Required:** optional
- **Example:** `Password123!`
- **Validation rules:** `sometimes|nullable|string|min:8`
- `sometimes` — validated only when the field is present.
- `nullable` — may be null.
- `string` — must be text.
- `min:8` — must be at least 8.
### `is_active`
- **Description:** Is Active
- **Type:** `boolean`
- **Required:** optional
- **Example:** `true`
- **Validation rules:** `sometimes|boolean`
- `sometimes` — validated only when the field is present.
- `boolean` — must be true, false, 1, or 0.
### `role_id`
- **Description:** Role
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `sometimes|exists:roles,id`
- `sometimes` — validated only when the field is present.
- `exists:roles,id` — must reference an existing record (roles, id).
### `image`
- **Description:** Image
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `nullable|string|custom:MediaExists`
- `nullable` — may be null.
- `string` — must be text.
- `custom:MediaExists` — custom validation rule.

**Example Request Body:**
```json
{
    "full_name": "Updated Supervisor Name",
    "is_active": false
}
```

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 29,
        "name": "Updated Supervisor Name",
        "email": "supervisor.store@example.com",
        "phone": "1077700001",
        "username": null,
        "user_type": "admin",
        "status": "suspended",
        "email_verified_at": null,
        "phone_verified_at": null,
        "locale": "ar",
        "allow_notifications": true,
        "timezone": "Asia/Riyadh",
        "avatar_path": null,
        "last_login_at": null,
        "suspended_at": null,
        "suspension_reason": null,
        "created_at": "2026-08-20T12:07:53.000000Z",
        "updated_at": "2026-08-20T12:07:53.000000Z",
        "deleted_at": null
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 139,
        "name": "Updated Supervisor Name",
        "email": "supervisor.store@example.com",
        "phone": "1077700001",
        "username": null,
        "user_type": "admin",
        "status": "suspended",
        "email_verified_at": null,
        "phone_verified_at": null,
        "locale": "ar",
        "allow_notifications": true,
        "timezone": "Asia/Riyadh",
        "avatar_path": null,
        "last_login_at": null,
        "suspended_at": null,
        "suspension_reason": null,
        "created_at": "2026-08-20T12:09:25.000000Z",
        "updated_at": "2026-08-20T12:09:25.000000Z",
        "deleted_at": null
    }
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 139,
        "name": "Updated Supervisor Name",
        "email": "supervisor.store@example.com",
        "phone": "1077700001",
        "username": null,
        "user_type": "admin",
        "status": "suspended",
        "email_verified_at": null,
        "phone_verified_at": null,
        "locale": "ar",
        "allow_notifications": true,
        "timezone": "Asia/Riyadh",
        "avatar_path": null,
        "last_login_at": null,
        "suspended_at": null,
        "suspension_reason": null,
        "created_at": "2026-08-20T12:09:46.000000Z",
        "updated_at": "2026-08-20T12:09:46.000000Z",
        "deleted_at": null
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a valid email address.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a valid email address.",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "Please enter a valid email address.",
    "data": null
}
```

**What happens next:** Fetch `show` to confirm the change.

---

#### Delete Role

**What this does:** Permanently deletes a role.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/roles/:role` |
| **Route name** | `admin.roles.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `roles.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `role` — Role ID — seeded example: `3`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — already deleted }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — already deleted }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — already deleted }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** It no longer appears in `index`.

---

#### Delete Supervisor

**What this does:** Permanently deletes a supervisor.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/supervisors/:supervisor` |
| **Route name** | `admin.supervisors.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `supervisors.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `supervisor` — Supervisor ID — seeded example: `2`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — already deleted }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — already deleted }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — already deleted }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** It no longer appears in `index`.

---

#### Delete Bulk

**What this does:** Deletes multiple roles in one call by an array of ids.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/roles/bulk` |
| **Route name** | `admin.roles.bulk.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `roles.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — unknown id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — unknown id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — unknown id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Re-fetch the index to confirm — deleted roles no longer appear.

---

#### Delete Bulk

**What this does:** Deletes multiple supervisors in one call by an array of ids.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/supervisors/bulk` |
| **Route name** | `admin.supervisors.bulk.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `supervisors.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

*{ 200 OK — OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — unknown id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — unknown id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — unknown id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Re-fetch the index to confirm — deleted supervisors no longer appear.

---

## 16. Addresses (Reference)

#### List All Addresses

**What this does:** Returns a paginated, filterable, searchable list of addresses.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/addresses?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.addresses.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `addresses.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — 200 - OK }*
```json
{
    "status": "success",
    "message": "Addresses retrieved",
    "data": {
        "data": [
            {
                "id": 1,
                "title": "Home",
                "address": "10 Corniche Street",
                "is_default": true,
                "user": {
                    "id": 8,
                    "name": "Ed Turcotte",
                    "email": "walter.carmella@example.org",
                    "user_type": "individual"
                },
                "country": {
                    "id": 1,
                    "name": null
                },
                "governorate": {
                    "id": 1,
                    "name": "Cairo"
                },
                "region": {
                    "id": 1,
                    "name": "Maadi"
                },
                "created_at": "2026-08-20 12:09:42"
            }
        ],
        "links": {
            "first": "http://localhost/api/v1/admin/addresses?page=1",
            "last": "http://localhost/api/v1/admin/addresses?page=1",
            "prev": null,
            "next": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 1,
            "links": [
                {
                    "url": null,
                    "label": "&laquo; Previous",
                    "page": null,
                    "active": false
                },
                {
                    "url": "http://localhost/api/v1/admin/addresses?page=1",
                    "label": "1",
                    "page": 1,
                    "active": true
                },
                {
                    "url": null,
                    "label": "Next &raquo;",
                    "page": null,
                    "active": false
                }
            ],
            "path": "http://localhost/api/v1/admin/addresses",
            "per_page": 15,
            "to": 1,
            "total": 1
        }
    }
}
```

**What happens next:** Use `show` on a specific id for full details.

---

#### Show Address Details

**What this does:** Returns full details for one address.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/addresses/:address` |
| **Route name** | `admin.addresses.show` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `addresses.view` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `address` — Address ID — chained from an earlier request in this flow ({{address_id}})

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — 200 - OK }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": {
        "id": 1,
        "title": "Home",
        "address": "10 Corniche Street",
        "is_default": true,
        "user": {
            "id": 8,
            "name": "Ed Turcotte",
            "email": "walter.carmella@example.org",
            "user_type": "individual"
        },
        "country": {
            "id": 1,
            "name": null
        },
        "governorate": {
            "id": 1,
            "name": "Cairo"
        },
        "region": {
            "id": 1,
            "name": "Maadi"
        },
        "created_at": "2026-08-20 12:09:42",
        "lat": 30.05,
        "lng": 31.24,
        "phone": "1000000001",
        "phone_code": "20",
        "notes": null,
        "updated_at": "2026-08-20 12:09:42"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — 404 - Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Use `update` to modify it, or `destroy` to remove it.

---

#### Create New Address

**What this does:** Creates a new address.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/addresses` |
| **Route name** | `admin.addresses.store` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `addresses.create` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `201 Created`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `user_id`
- **Description:** Customer
- **Type:** `integer`
- **Required:** required
- **Example:** `1`
- **Validation rules:** `required|exists:users,id`
- `required` — must be provided.
- `exists:users,id` — must reference an existing record (users, id).
### `title`
- **Description:** Title
- **Type:** `string`
- **Required:** required
- **Example:** `Example Title`
- **Validation rules:** `required|string|max:100`
- `required` — must be provided.
- `string` — must be text.
- `max:100` — must not exceed 100.
### `address`
- **Description:** Address
- **Type:** `string`
- **Required:** required
- **Example:** `123 Main Street, Building A`
- **Validation rules:** `required|string|max:500`
- `required` — must be provided.
- `string` — must be text.
- `max:500` — must not exceed 500.
### `country_id`
- **Description:** Country
- **Type:** `integer`
- **Required:** required
- **Example:** `1`
- **Validation rules:** `required|exists:countries,id`
- `required` — must be provided.
- `exists:countries,id` — must reference an existing record (countries, id).
### `governorate_id`
- **Description:** Governorate
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|exists:governorates,id`
- `nullable` — may be null.
- `exists:governorates,id` — must reference an existing record (governorates, id).
### `region_id`
- **Description:** Region
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|exists:regions,id`
- `nullable` — may be null.
- `exists:regions,id` — must reference an existing record (regions, id).
### `lat`
- **Description:** Latitude
- **Type:** `number`
- **Required:** required
- **Example:** `10`
- **Validation rules:** `required|numeric|between:-90,90`
- `required` — must be provided.
- `numeric` — must be numeric.
- `between:-90,90` — must be between -90, 90.
### `lng`
- **Description:** Longitude
- **Type:** `number`
- **Required:** required
- **Example:** `10`
- **Validation rules:** `required|numeric|between:-180,180`
- `required` — must be provided.
- `numeric` — must be numeric.
- `between:-180,180` — must be between -180, 180.
### `phone`
- **Description:** Phone
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `nullable|string|max:20`
- `nullable` — may be null.
- `string` — must be text.
- `max:20` — must not exceed 20.
### `phone_code`
- **Description:** Phone code
- **Type:** `string`
- **Required:** optional
- **Example:** `20`
- **Validation rules:** `nullable|string|max:5`
- `nullable` — may be null.
- `string` — must be text.
- `max:5` — must not exceed 5.
### `notes`
- **Description:** Notes
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `nullable|string|max:500`
- `nullable` — may be null.
- `string` — must be text.
- `max:500` — must not exceed 500.
### `is_default`
- **Description:** Default
- **Type:** `boolean`
- **Required:** optional
- **Example:** `true`
- **Validation rules:** `sometimes|boolean`
- `sometimes` — validated only when the field is present.
- `boolean` — must be true, false, 1, or 0.

**Example Request Body:**
```json
{
    "user_id": 8,
    "title": "Home",
    "address": "10 Corniche Street",
    "country_id": 1,
    "governorate_id": 1,
    "region_id": 1,
    "lat": 30.05,
    "lng": 31.24,
    "phone": "1000000001",
    "phone_code": "20",
    "is_default": true
}
```

**Actual Success Response(s):**

*{ 201 Created — 201 - OK }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 1,
        "title": "Home",
        "address": "10 Corniche Street",
        "is_default": true,
        "user": {
            "id": 8,
            "name": "Ed Turcotte",
            "email": "walter.carmella@example.org",
            "user_type": "individual"
        },
        "country": {
            "id": 1,
            "name": null
        },
        "governorate": {
            "id": 1,
            "name": "Cairo"
        },
        "region": {
            "id": 1,
            "name": "Maadi"
        },
        "created_at": "2026-08-20 12:09:42",
        "lat": 30.05,
        "lng": 31.24,
        "phone": "1000000001",
        "phone_code": "20",
        "notes": null,
        "updated_at": "2026-08-20 12:09:42"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 - Validation Error }*
```json
{
    "status": "fail",
    "message": "Please specify a user.",
    "data": null
}
```

**What happens next:** Use the returned id with `show`/`update`/`destroy` for this address.

---

#### Update Address

**What this does:** Updates an existing address.

| | |
|---|---|
| **Method** | `PUT` |
| **Endpoint** | `{{base_url}}/api/v1/admin/addresses/:address` |
| **Route name** | `admin.addresses.update` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `addresses.update` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `address` — Address ID — chained from an earlier request in this flow ({{address_id}})

**Payload:**
Send as `application/json`.

**Field documentation:**
### `user_id`
- **Description:** Customer
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `sometimes|exists:users,id`
- `sometimes` — validated only when the field is present.
- `exists:users,id` — must reference an existing record (users, id).
### `title`
- **Description:** Title
- **Type:** `string`
- **Required:** optional
- **Example:** `Example Title`
- **Validation rules:** `sometimes|string|max:100`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:100` — must not exceed 100.
### `address`
- **Description:** Address
- **Type:** `string`
- **Required:** optional
- **Example:** `123 Main Street, Building A`
- **Validation rules:** `sometimes|string|max:500`
- `sometimes` — validated only when the field is present.
- `string` — must be text.
- `max:500` — must not exceed 500.
### `country_id`
- **Description:** Country
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `sometimes|exists:countries,id`
- `sometimes` — validated only when the field is present.
- `exists:countries,id` — must reference an existing record (countries, id).
### `governorate_id`
- **Description:** Governorate
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|exists:governorates,id`
- `nullable` — may be null.
- `exists:governorates,id` — must reference an existing record (governorates, id).
### `region_id`
- **Description:** Region
- **Type:** `integer`
- **Required:** optional
- **Example:** `1`
- **Validation rules:** `nullable|exists:regions,id`
- `nullable` — may be null.
- `exists:regions,id` — must reference an existing record (regions, id).
### `lat`
- **Description:** Latitude
- **Type:** `number`
- **Required:** optional
- **Example:** `10`
- **Validation rules:** `sometimes|numeric|between:-90,90`
- `sometimes` — validated only when the field is present.
- `numeric` — must be numeric.
- `between:-90,90` — must be between -90, 90.
### `lng`
- **Description:** Longitude
- **Type:** `number`
- **Required:** optional
- **Example:** `10`
- **Validation rules:** `sometimes|numeric|between:-180,180`
- `sometimes` — validated only when the field is present.
- `numeric` — must be numeric.
- `between:-180,180` — must be between -180, 180.
### `phone`
- **Description:** Phone
- **Type:** `string`
- **Required:** optional
- **Example:** `1234567890`
- **Validation rules:** `nullable|string|max:20`
- `nullable` — may be null.
- `string` — must be text.
- `max:20` — must not exceed 20.
### `phone_code`
- **Description:** Phone code
- **Type:** `string`
- **Required:** optional
- **Example:** `20`
- **Validation rules:** `nullable|string|max:5`
- `nullable` — may be null.
- `string` — must be text.
- `max:5` — must not exceed 5.
### `notes`
- **Description:** Notes
- **Type:** `string`
- **Required:** optional
- **Example:** `value`
- **Validation rules:** `nullable|string|max:500`
- `nullable` — may be null.
- `string` — must be text.
- `max:500` — must not exceed 500.
### `is_default`
- **Description:** Default
- **Type:** `boolean`
- **Required:** optional
- **Example:** `true`
- **Validation rules:** `sometimes|boolean`
- `sometimes` — validated only when the field is present.
- `boolean` — must be true, false, 1, or 0.

**Example Request Body:**
```json
{
    "title": "Office",
    "address": "20 Corniche Street Updated"
}
```

**Actual Success Response(s):**

*{ 200 OK — 200 - OK }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 1,
        "title": "Office",
        "address": "20 Corniche Street Updated",
        "is_default": true,
        "user": {
            "id": 8,
            "name": "Ed Turcotte",
            "email": "walter.carmella@example.org",
            "user_type": "individual"
        },
        "country": {
            "id": 1,
            "name": null
        },
        "governorate": {
            "id": 1,
            "name": "Cairo"
        },
        "region": {
            "id": 1,
            "name": "Maadi"
        },
        "created_at": "2026-08-20 12:09:42",
        "lat": 30.05,
        "lng": 31.24,
        "phone": "1000000001",
        "phone_code": "20",
        "notes": null,
        "updated_at": "2026-08-20 12:09:42"
    }
}
```

**Actual Error Response(s):**

*{ 404 Not Found — 404 - Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Fetch `show` to confirm the change.

---

#### Delete Address

**What this does:** Permanently deletes a address.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/addresses/:address` |
| **Route name** | `admin.addresses.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `addresses.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `address` — Address ID — chained from an earlier request in this flow ({{address_id}})

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — 200 - OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — 404 - Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** It no longer appears in `index`.

---

#### Delete Bulk

**What this does:** Deletes multiple addresses in one call by an array of ids.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/addresses/bulk` |
| **Route name** | `admin.addresses.bulk.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `addresses.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Success Response(s):**

*{ 200 OK — 200 - OK }*
```json
{
    "status": "success",
    "message": "Data removed successfully",
    "data": null
}
```

**Actual Error Response(s):**

*{ 404 Not Found — 404 - Not Found }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 422 Unprocessable Entity — 422 - Validation Error }*
```json
{
    "status": "fail",
    "message": "Please select at least one item.",
    "data": null
}
```

**What happens next:** Re-fetch the index to confirm — deleted addresses no longer appear.

---

## 17. Internal Notes

#### List All Internal notes

**What this does:** Lists internal (staff-only) notes attached to one entity — `:entityType` is `order`, `contract`, or `user`, `:entityId` its numeric id.

| | |
|---|---|
| **Method** | `GET` |
| **Endpoint** | `{{base_url}}/api/v1/admin/:entityType/:entityId/notes?page=1&per_page=15&search=&sort[created_at]=desc&paginate=false&filters[is_active]=1` |
| **Route name** | `admin.internal-notes.index` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `internal-notes.index` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `200 OK`, `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `entityType` — EntityType ID — seeded example: `order`
- `entityId` — EntityId ID — seeded example: `1`

**Payload:**
No request body. Use the documented path and query parameters.

**Query parameters:**
- `page` — Page number (supported)
- `per_page` — Items per page (max: 100) (optional)
- `search` — Search term (searches across searchable fields) (optional)
- `sort[created_at]` — Sort by field: asc or desc (optional)
- `paginate` — Set to false to disable pagination (optional)
- `filters[is_active]` — Filter by active status: 1 or 0 (optional)

**Actual Success Response(s):**

*{ 200 OK — empty - order }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — still empty due to store bug - order }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — empty - contract }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — still empty due to store bug - contract }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — empty - user }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — still empty due to store bug - user }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — empty - order }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — still empty due to store bug - order }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — empty - contract }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — still empty due to store bug - contract }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — empty - user }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — still empty due to store bug - user }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — empty - order }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — still empty due to store bug - order }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — empty - contract }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — still empty due to store bug - contract }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — empty - user }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

*{ 200 OK — still empty due to store bug - user }*
```json
{
    "status": "success",
    "message": "Data retrieved successfully",
    "data": []
}
```

**Actual Error Response(s):**

*{ 404 Not Found — unknown order id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — invalid entityType (route constraint) }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — unknown order id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — invalid entityType (route constraint) }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — unknown order id }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — invalid entityType (route constraint) }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** Add another note with the `store` action on the same path.

---

#### Create New Internal note

**What this does:** Adds an internal note to an order/contract/user, visible only to admin staff.

| | |
|---|---|
| **Method** | `POST` |
| **Endpoint** | `{{base_url}}/api/v1/admin/:entityType/:entityId/notes` |
| **Route name** | `admin.internal-notes.store` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `internal-notes.create` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `201 Created`, `422 Unprocessable Entity` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `entityType` — EntityType ID — seeded example: `order`
- `entityId` — EntityId ID — seeded example: `1`

**Payload:**
Send as `application/json`.

**Field documentation:**
### `note`
- **Description:** Note
- **Type:** `string`
- **Required:** required
- **Example:** `value`
- **Validation rules:** `required|string|max:2000`
- `required` — must be provided.
- `string` — must be text.
- `max:2000` — must not exceed 2000.

**Example Request Body:**
```json
{
    "note": "Follow-up needed for this order."
}
```

> **Fixed:** an earlier pass of this doc captured a real `500` here for `order`/`contract`/`user` alike — `InternalNote` (like `Conversation`/`Message`) used to `use HasUuids` despite `internal_notes.id` being a plain `BIGINT` auto-increment column, so Eloquent tried to insert a generated UUID string into it (`SQLSTATE[01000]: ... Data truncated for column 'id'`). Fixed by dropping `HasUuids` from `App\Models\InternalNote`. Re-verified live via `AdminSupportNotesFlagsDumpTest::test_dump_internal_note_endpoints` — see the real `201`s below, one per `entityType`.

**Actual Success Response(s):**

*{ 201 Created — order, live capture 2026-08-22 }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 1,
        "note": "Follow-up needed for this order.",
        "author": {
            "id": 1,
            "name": "Taya Brekke"
        },
        "created_at": "2026-08-22 19:34:51"
    }
}
```

*{ 201 Created — contract, live capture 2026-08-22 }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 2,
        "note": "Follow-up needed for this contract.",
        "author": {
            "id": 1,
            "name": "Taya Brekke"
        },
        "created_at": "2026-08-22 19:34:51"
    }
}
```

*{ 201 Created — user, live capture 2026-08-22 }*
```json
{
    "status": "success",
    "message": "Data saved successfully",
    "data": {
        "id": 3,
        "note": "Follow-up needed for this user.",
        "author": {
            "id": 1,
            "name": "Taya Brekke"
        },
        "created_at": "2026-08-22 19:34:51"
    }
}
```

**Actual Error Response(s):**

*{ 422 Unprocessable Entity — 422 Validation Error }*
```json
{
    "status": "fail",
    "message": "The Note field is required.",
    "data": null
}
```

**What happens next:** Retrieve the full thread via the matching `index` action.

---

#### Delete Internal note

**What this does:** Permanently deletes a internal note.

| | |
|---|---|
| **Method** | `DELETE` |
| **Endpoint** | `{{base_url}}/api/v1/admin/:entityType/:entityId/notes/:id` |
| **Route name** | `admin.internal-notes.destroy` |
| **Guard** | JWT bearer (`auth:api`); account must be `active`; RBAC permission `internal-notes.delete` required (`rbac.auto` — bypassed in `local`/`testing` environments, see [AUTH.md](../AUTH.md)) |
| **Allowed roles** | Admin / Super Admin (`user_type: admin` or `super_admin`) |
| **Status codes** | `404 Not Found` |

**Headers:**
- `Accept: application/json`
- `Content-Type: application/json`
- `Accept-Language: {{locale}}`

**Path Parameters:**
- `entityType` — EntityType ID — seeded example: `order`
- `entityId` — EntityId ID — seeded example: `1`
- `id` — Id ID — seeded example: `1`

**Payload:**
No request body. Use the documented path and query parameters.

**Actual Error Response(s):**

*{ 404 Not Found — order }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — contract }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — user }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — order }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — contract }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — user }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — order }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — contract }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

*{ 404 Not Found — user }*
```json
{
    "status": "fail",
    "message": "Resource not found",
    "data": null
}
```

**What happens next:** It no longer appears in `index`.

---
