Retrieve a paginated list of projects belonging to the authenticated user’s tenant. Supports filtering by status, searching by name or description, and sorting by recent activity, name, or status.
- All endpoints require a valid JWT access token.
- Projects are automatically scoped to the authenticated user’s tenant — a user can only see their own projects.
- ARCHIVED projects are excluded from the default list. To see archived projects, the client must explicitly filter by
status=ARCHIVED. - The
progressfield is included in each project item. It isnullwhen the project status is notBUILDING, and an integer 0-100 when the status isBUILDING.
Limitation (MVP): Progress tracking is a stub — the backend always returns
0for projects inBUILDINGstatus.
sequenceDiagram
actor User
User->>+FE: opens Projects screen
FE->>+BE: GET /api/v1/projects?page=0&size=20&sort=recent <br> Authorization: Bearer {accessToken}
BE->>BE: validate JWT access token
alt access token invalid or missing
BE-->>FE: 401 Unauthorized <br> ErrorResponse
end
BE->>DB: query projects by tenant_id <br> apply filters, search, sort, pagination
BE->>-FE: 200 OK <br> ProjectListResponse
FE->>-User: display project list
User->>+FE: applies filter / search / sort
FE->>+BE: GET /api/v1/projects?status=LIVE&search=bakery&sort=name&page=0&size=20 <br> Authorization: Bearer {accessToken}
BE->>DB: query projects with filters
BE->>-FE: 200 OK <br> ProjectListResponse
FE->>-User: display filtered project list
GET /api/v1/projects (query parameters):
| Parameter | Type | Default | Description |
|---|---|---|---|
| status | string | (none) | Filter by project status (DRAFT, BUILDING, LIVE, UPDATED, PAUSED, ARCHIVED) |
| search | string | (none) | Case-insensitive search in project name and description |
| sort | string | recent | Sort order: recent (updatedAt DESC), name (alphabetical ASC), status (alphabetical ASC) |
| page | int | 0 | Page number (0-based) |
| size | int | 20 | Page size |
200 OK ProjectListResponse:
{
"data": [
{
"id": 1,
"name": "Wildwood Bakery",
"description": "Online ordering for a neighborhood bakery",
"status": "LIVE",
"url": "wildwood-bakery.talkide.app",
"accent": "oklch(0.78 0.15 70)",
"techStack": "Vue + Spring Boot",
"progress": null,
"previewUrl": "http://localhost:5201",
"createdAt": "2026-04-20T10:00:00Z",
"updatedAt": "2026-04-29T14:30:00Z"
},
{
"id": 2,
"name": "Pet Tracker",
"description": "GPS tracking app for pet owners",
"status": "BUILDING",
"url": "pet-tracker.talkide.app",
"accent": "oklch(0.72 0.12 160)",
"techStack": "React + Node.js",
"progress": 0,
"previewUrl": "http://localhost:5202",
"createdAt": "2026-04-25T08:00:00Z",
"updatedAt": "2026-04-29T12:00:00Z"
}
],
"page": 0,
"size": 20,
"totalElements": 2,
"totalPages": 1
}
401 Unauthorized (missing or invalid access token) ErrorResponse:
{
"status": 401,
"code": "AUTHENTICATION_FAILED",
"message": "Access token is missing or invalid"
}
Frontend
Validations
No form inputs — this is a read-only listing. Filter/search/sort parameters are controlled via UI components.
Backend
Validations
| Field | Constraints | Size | Pattern | Note |
|---|---|---|---|---|
| status | (optional) | Must be a valid ProjectStatus enum value if provided | ||
| search | (optional) | 0 - 200 | ||
| sort | (optional) | Must be one of: recent, name, status. Defaults to recent | ||
| page | (optional) | Must be >= 0. Defaults to 0 | ||
| size | (optional) | Must be 1 - 100. Defaults to 20 |
Test Cases
| GIVEN | WHEN | THEN |
|---|---|---|
| authenticated user with 3 projects (DRAFT, LIVE, ARCHIVED) | GET /projects is called (no filters) | 200 OK with 2 projects returned (ARCHIVED excluded) |
| authenticated user with 3 projects | GET /projects?status=ARCHIVED is called | 200 OK with 1 ARCHIVED project returned |
| authenticated user with 3 projects | GET /projects?status=LIVE is called | 200 OK with only LIVE projects returned |
| authenticated user with projects named “Bakery” and “Pet Tracker” | GET /projects?search=bakery is called | 200 OK with only “Bakery” project returned (case-insensitive) |
| authenticated user with multiple projects | GET /projects?sort=name is called | 200 OK with projects sorted alphabetically by name |
| authenticated user with 25 projects | GET /projects?page=0&size=10 is called | 200 OK with 10 projects, totalElements=25, totalPages=3 |
| authenticated user with no projects | GET /projects is called | 200 OK with empty data array, totalElements=0 |
| authenticated user A | GET /projects is called | 200 OK with only user A’s tenant projects (not user B’s) |
| invalid sort value | GET /projects?sort=invalid is called | 400 VALIDATION_ERROR error response is returned |
| no Authorization header | GET /projects is called | 401 AUTHENTICATION_FAILED error response is returned |
Was this page helpful?
Thanks for the feedback.