> ## Documentation Index
> Fetch the complete documentation index at: https://theteam-13fc7f49.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# History / Activity log API

#### *History (Audit Log) — Backend Documentation*

## **Overview**

The platform keeps a lightweight **audit trail** of CRUD-style actions in the `history` table. Whenever a controller performs a tracked action it calls the global helper `insert_in_history_table($action, $row_id, $table_name)` (`app/Helpers/helpers.php`), which stamps a row with the acting user, a free-text action label, the affected row id and table name.

This endpoint exposes that trail for reading:

```text theme={null}
GET /api/history
```

**Authentication**: Bearer token required (Laravel Sanctum).

**Middleware**: lives in the main tenant-scoped block — `auth:sanctum`, `check_if_user_is_blocked_middleware`, `company_policy_middleware`.

**Headers** (for all requests):

```text theme={null}
Authorization: Bearer {{token}}
Accept: application/json
```

Handled by `SuperAdminController@index`.

***

## **How It Works**

1. The request hits `SuperAdminController@index`.
2. Query params are validated (pagination, filters, sorting).
3. A `history` ↔ `users` left-join query is built, selecting the entry plus the user's full name and email. Soft-deleted entries (`deleted_at`) are excluded.
4. **Visibility scoping** is applied based on the caller's role:
   * **Admin / Super-Admin** → can see **everyone's** entries, and may filter by `user_id`.
   * **Any other role** (Student, Instructor, Content Manager) → forcibly restricted to **their own** entries; the `user_id` filter is ignored for them.
5. Optional filters (`table_name`, `row_id`, `search`) are applied.
6. Results are sorted and returned as a standard Laravel paginator.

> **Note:** entries are not company-scoped in the query itself — visibility is driven by role + ownership as described above (admins see all rows).

***

## **The** `history `**Table**

| **Column** | **Type** | **Description** |
| :- | :- | :- |
| `id` | bigint | Primary key |
| `user_id` | bigint (FK) | The user who performed the action (FK → `users.id`) |
| `action` | tinyText | Free-text label describing the action |
| `row_id` | bigint | The id of the affected row |
| `table_name` | tinyText | The table the action targeted |
| `created_at` | datetime | When the action happened |
| `updated_at` | datetime | Standard timestamp |
| `archived_at` | datetime | Archive marker (nullable) |
| `deleted_at` | datetime | Soft-delete marker (excluded from results) |

***

## **Query Parameters**

All parameters are **optional**.

| **Param** | **Type** | **Default** | **Description** |
| :- | :- | :- | :- |
| `page` | integer | `1` | Page number (min 1) |
| `per_page` | integer | `20` | Items per page (min 1, **max 100**) |
| `user_id` | integer | — | Filter by user. **Admin/Super-Admin only** — ignored for other roles. Must exist in `users`. |
| `table_name` | string | — | Filter by exact table name (e.g. `trainings`, `users`, `orders`) |
| `row_id` | integer | — | Filter by the affected row id |
| `search` | string | — | `LIKE` match against the `action` text |
| `sort` | string | `created_at` | One of: `created_at`, `action`, `table_name`, `row_id`, `user_id` |
| `direction` | string | `desc` | `asc` or `desc` |

Validation failures return **422** with Laravel's standard validation error shape.

***

## **Response**

Standard Laravel paginator. Each item in `data` includes the joined user info:

```text theme={null}
{
  "current_page": 1,
  "data": [
    {
      "id": 1423,
      "user_id": 7,
      "user_fullname": "Amine Ben Taieb",
      "user_email": "amine@example.com",
      "action": "Created training",
      "row_id": 312,
      "table_name": "trainings",
      "created_at": "2026-06-05 14:22:01",
      "archived_at": null
    }
  ],
  "first_page_url": "http://localhost:8020/api/history?page=1",
  "from": 1,
  "last_page": 8,
  "last_page_url": "http://localhost:8020/api/history?page=8",
  "next_page_url": "http://localhost:8020/api/history?page=2",
  "path": "http://localhost:8020/api/history",
  "per_page": 20,
  "prev_page_url": null,
  "to": 20,
  "total": 154
}
```

| **Field** | **Description** |
| :- | :- |
| `user_fullname` | `CONCAT(first_name, ' ', last_name)` from the joined user |
| `user_email` | The acting user's email |
| `action` | The free-text action label written by the helper |
| `row_id` | Affected row id |
| `table_name` | Target table |
| `archived_at` | Archive marker (usually `null`) |

***

## **Postman Examples**

### **1. Latest activity (defaults)**

```text theme={null}
GET /api/history
Authorization: Bearer {{token}}
```

Returns the 20 most recent entries the caller is allowed to see (own entries for non-admins, everyone's for admins).

### **2. Admin: a specific user's actions**

```text theme={null}
GET /api/history?user_id=7&per_page=50
Authorization: Bearer {{admin_token}}
```

### **3. Filter by table + search the action text**

```text theme={null}
GET /api/history?table_name=orders&search=cancel&sort=created_at&direction=desc
Authorization: Bearer {{token}}
```

### **4. Audit a single record**

```text theme={null}
GET /api/history?table_name=trainings&row_id=312
Authorization: Bearer {{token}}
```

***

## **Notes & Gotchas**

* **Role-based visibility is enforced server-side** — a non-admin cannot read another user's history even by passing `user_id`; that filter only applies to admins/super-admins.
* **Soft-deleted entries are hidden** — rows with a `deleted_at` are never returned.
* `per_page `**is capped at 100** to protect the join query.
* **Entries are write-once** via `insert_in_history_table(...)`; this endpoint is read-only (no create/update/delete routes for history).
* `action` is free-text, so `search` matches whatever label the calling controller chose to log — labels are not standardized across modules.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.