Case Study

IssueHub API — Ticketing Backend Built with Laravel and Sanctum

IssueHub API is a backend-focused portfolio project built with Laravel 13, PHP 8.5 and Sanctum. The goal was to design a clean and realistic REST API for managing tickets and comments, while practicing the backend patterns commonly expected in modern Laravel applications: token-based authentication, authorization, request validation, structured API responses, filtering and automated testing.

Portfolio backend demo
Role: Backend Laravel Developer Laravel 13 · PHP 8.5 · Sanctum · Pest · MySQL / SQLite

Overview

IssueHub API was designed as a compact backend project centered around a familiar product pattern: tickets owned by authenticated users, with comments attached to each ticket and a small set of useful filters for retrieval. Although the scope was intentionally limited, the structure aimed to reflect the way a real Laravel API is commonly organized in production-oriented applications.

The main objective was not simply to expose CRUD endpoints, but to practice how backend concerns should be separated properly. Authentication was handled through Sanctum, authorization through Policies, validation through Form Requests, response formatting through API Resources and core behavior was reinforced with feature tests written in Pest.

System Architecture

Core Domain

The application revolves around two main entities: Ticket and TicketComment. A ticket belongs to a user and stores a title, description, status and priority. Each ticket can also have multiple comments, which are linked both to the ticket itself and to the user who authored them. This kept the domain small, but expressive enough to model a realistic issue-tracking flow.

API-First Structure

Instead of building a monolithic server-rendered interface, this project focused entirely on the backend layer. Controllers were kept thin, with request validation extracted into dedicated Form Request classes and response formatting handled through API Resources. This helped keep each concern explicit and easier to extend as the API grew.

User Ownership and Authorization

A key part of the structure was making sure users could only access or modify their own tickets. That rule was enforced through Laravel Policies rather than through ad-hoc checks scattered across the controllers. This made the authorization layer more readable and aligned the project with common Laravel best practices for resource ownership.

Query Filtering

The ticket listing endpoint was extended with lightweight filters for status, priority and title search. While simple, these query capabilities make the API feel much closer to something a frontend could use in practice, rather than a minimal CRUD exercise with fixed responses.

Key principle: keep the API small in scope, but structured around the same backend concerns used in real applications — authentication, authorization, validation, ownership and test coverage.

Technical Decisions

  • Sanctum for token-based authentication: Sanctum provided a straightforward way to protect API endpoints without introducing unnecessary complexity. It allowed the project to focus on authenticated resource access while remaining lightweight and practical.
  • Policies instead of controller-level ownership checks: authorization rules were moved into a dedicated policy layer so ticket access could remain centralized, explicit and easier to maintain.
  • Form Requests for validation: both ticket creation and updates use dedicated request classes, reducing controller noise and keeping validation rules isolated where they belong.
  • API Resources for consistent responses: instead of returning raw model payloads, resources were used to shape ticket and comment responses in a cleaner and more predictable way.
  • Feature testing with Pest: the project includes tests for authentication-protected actions, CRUD operations, authorization boundaries, filters and nested ticket comments, helping confirm that the API behaves correctly beyond manual testing.

API Workflow

The user flow begins with authentication through Sanctum. Once authenticated, the user can create tickets by submitting a title, description and optional priority. Each new ticket is automatically associated with the authenticated user and starts with a default open status.

From there, tickets can be listed, filtered, viewed individually, updated or deleted. The listing endpoint supports lightweight query parameters such as status, priority and search, making the API more practical for future frontend consumption.

Each ticket also supports a nested comment flow. Authenticated users can retrieve comments for a ticket and add new ones through dedicated nested endpoints. This small extension makes the project feel closer to a real ticketing product, where a record is not only stored, but also discussed and tracked over time.

Lessons Learned

Building this project reinforced how much stronger an API becomes when common Laravel patterns are applied consistently. Even with a limited domain, separating validation, authorization and response formatting makes the codebase easier to understand and easier to grow.

Another important takeaway was the value of automated testing in backend work. The project was not only a way to expose endpoints, but also a way to practice verifying behavior such as protected access, user ownership, filtering logic and nested resources in a repeatable way.

Future Improvements

Future iterations could introduce API versioning, improved pagination metadata, stronger filtering options, enum-based status handling, rate limiting for authentication endpoints and generated API documentation such as a Postman collection or OpenAPI schema. It would also be natural to expand the domain with features such as assignees, labels or activity history, depending on whether the project evolved toward a larger issue-tracking system.