A clean, RESTful Task Management API built with Laravel 13
Taskify is a production-ready task management API with token-based authentication, per-user task & project isolation, filtering, and rate limiting β fully documented with interactive OpenAPI docs.
- π Sanctum token auth β 24-hour token expiry, revocable via logout
- π Full CRUD with soft delete & restore
- π Smart filtering β exact
status/priorityfilters + case-insensitive search - π€ Per-user isolation β tasks and projects are private to their owner
- π Projects β organize tasks into color-coded projects with full CRUD, soft delete & restore
- π¦ Rate limiting β auth (5/min) & API (60/min)
- π Interactive docs via Scramble
- ποΈ PostgreSQL + Docker setup included
- Requirements
- Installation
- Running Tests
- Project Structure
- API Reference
- Authentication
- Tasks
- Projects
- Status Codes
- Rate Limits
- Documentation
- Deployment
- License
- Developed By
| Tool | Version |
|---|---|
| PHP | 8.3+ |
| Composer | latest |
| PostgreSQL | 16 (or any Laravel-supported DB) |
| Node.js | optional (frontend assets only) |
git clone https://github.com/MahdiiMax/taskify.git taskify
cd taskify
composer install
cp .env.example .env
php artisan key:generate
php artisan migrate
php artisan serveπ‘ Tip: run
composer run setupto do all of the above automatically.
A docker-compose.yaml spins up PostgreSQL (db taskify, user/password admin/admin) and pgAdmin at http://localhost:5050 (login: admin@admin.com / admin):
docker compose up -dThen configure .env:
DB_CONNECTION=pgsql
DB_DATABASE=taskify
DB_USERNAME=admin
DB_PASSWORD=admin
AUTH_GUARD=sanctum
SANCTUM_EXPIRATION=1440| Key | Purpose |
|---|---|
AUTH_GUARD=sanctum |
Makes $request->user() resolve API tokens |
SANCTUM_EXPIRATION=1440 |
Token lifetime in minutes (24h) |
composer test # or: php artisan testThe suite runs on in-memory SQLite β no DB server needed.
If you want to run tests in your own PostgreSQL server:
php artisan test --env=pgsqlapp/
βββ Enums/ # TaskPriority, TaskStatus, ProjectColor
βββ Http/
β βββ Controllers/Api/V1/ # AuthController, TaskController, ProjectController
β βββ Middleware/Api/V1/ # GuestMiddleware
β βββ Requests/Api/V1/ # Auth/, Task/ & Project/ Form Requests
β βββ Resources/Api/V1/ # TaskResource, UserResource, ProjectResource
βββ Models/ # Task, User, Project
βββ Policies/ # TaskPolicy, ProjectPolicy
βββ Providers/ # AppServiceProvider
routes/
βββ api.php # v1 API routes
tests/
βββ Feature/Api/V1/ # AuthTest, TaskTest, ProjectTest
| Base URL | http://localhost:8000/api/v1 |
|---|---|
| Interactive docs | http://localhost:8000/docs/api |
All task and project endpoints require a Bearer token:
Authorization: Bearer {token}
Tokens are issued by login, live 24 hours, and are revoked by logout.
{
"name": "Jane Doe",
"email": "jane@example.com",
"password": "password123",
"password_confirmation": "password123"
}
201β{ "message", "user": { "id", "name", "email", "created_at" } }
{
"email": "jane@example.com",
"password": "password123"
}
200β{ "message", "user": {...}, "token": "<plain token>" }
200β{ "message": "logged out successfully" }(revokes the current token)
| Method | Endpoint | Description |
|---|---|---|
| GET | /tasks |
List own tasks (paginated, 10/page) |
| POST | /tasks |
Create a task |
| GET | /tasks/{task} |
Show a task |
| PUT/PATCH | /tasks/{task} |
Update a task |
| DELETE | /tasks/{task} |
Soft delete a task |
| GET | /tasks/trashed |
List soft-deleted tasks |
| POST | /tasks/{task}/restore |
Restore a soft-deleted task |
| Field | Rules |
|---|---|
title |
required Β· string Β· max 255 |
description |
nullable Β· string |
status |
nullable β pending Β· in_progress Β· done |
priority |
nullable β low Β· medium Β· high |
due_date |
nullable Β· date Β· today or later |
project_id |
nullable Β· exists in your projects |
| Query | Example | Behavior |
|---|---|---|
status |
?status=pending |
exact match |
priority |
?priority=high |
exact match |
search |
?search=buy milk |
case-insensitive partial match on title/description |
project_id |
?project_id=3 |
exact match (your projects only) |
Invalid status/priority values β 422.
| Method | Endpoint | Description |
|---|---|---|
| GET | /projects |
List own projects (paginated, 10/page) |
| POST | /projects |
Create a project |
| GET | /projects/{project} |
Show a project |
| PUT/PATCH | /projects/{project} |
Update a project |
| DELETE | /projects/{project} |
Soft delete a project |
| GET | /projects/trashed |
List soft-deleted projects |
| POST | /projects/{project}/restore |
Restore a soft-deleted project |
| Field | Rules |
|---|---|
name |
required Β· string Β· max 255 |
description |
nullable Β· string |
color |
nullable β white Β· black Β· blue Β· pink Β· red Β· green Β· yellow Β· orange |
| Code | Meaning |
|---|---|
200 |
Success |
201 |
Created |
400 |
Already authenticated (on login/register) |
401 |
Unauthenticated / expired or revoked token |
403 |
Forbidden (another user's resource) |
422 |
Validation error |
429 |
Rate limit exceeded |
| Scope | Limit |
|---|---|
| Auth routes (login/register) | 5/min per email + IP |
| All API routes | 60/min per user (or IP) |
Interactive API docs rendered with Stoplight Elements (dark theme):
| Docs UI | http://localhost:8000/docs/api |
|---|---|
| OpenAPI spec | http://localhost:8000/docs/api.json (OpenAPI 3.1, served live) |
Export the spec to a file:
php artisan scramble:export # writes api.jsonapi.json is a standard OpenAPI document β import it into Insomnia or Postman to explore and test the API.
- Run
php artisan config:cache/route:cacheonly in production β in development a stale config cache can serve outdated settings. - Warm the docs cache with
php artisan scramble:cache. - Expired tokens stay in the DB until pruned β schedule
php artisan sanctum:prune-expired(daily viaroutes/console.php+ theschedule:runcron) to keep the table clean.
This project is open-sourced under the MIT License β Β© 2026 Mahdi Sadeghi.
Mahdi Sadeghi
Full-Stack Developer
Built with β€οΈ and β using Laravel