Skip to main content
GET
/
api
/
projects
List Projects
curl --request GET \
  --url https://api.example.com/api/projects
{
  "projects": [
    {
      "projects[].id": "<string>",
      "projects[].workspaceId": "<string>",
      "projects[].userId": "<string>",
      "projects[].name": "<string>",
      "projects[].styleTemplateId": "<string>",
      "projects[].roomType": {},
      "projects[].thumbnailUrl": {},
      "projects[].status": "<string>",
      "projects[].imageCount": 123,
      "projects[].completedCount": 123,
      "projects[].createdAt": "<string>",
      "projects[].updatedAt": "<string>"
    }
  ]
}

Overview

Retrieves a list of all projects in the authenticated user’s workspace. Projects are returned in reverse chronological order (newest first).

Authentication

Requires an authenticated user session. Only returns projects from the user’s workspace.

Query Parameters

limit
number
Maximum number of projects to return. If not specified, returns all projects.Example: 20
offset
number
Number of projects to skip (for pagination). Use with limit for paginated results.Example: 0
status
string
Filter projects by status.Available values:
  • pending - Projects with no processed images
  • processing - Projects with images currently being processed
  • completed - Projects where all images are completed
  • failed - Projects where all images failed

Request Example

GET /api/projects?limit=10&offset=0&status=completed

Response

Returns an array of project objects ordered by creation date (newest first).
projects
array
required
Array of project objects.
projects[].id
string
required
Unique project identifier (UUID format).
projects[].workspaceId
string
required
The workspace ID this project belongs to.
projects[].userId
string
required
The ID of the user who created the project.
projects[].name
string
required
The project name.
projects[].styleTemplateId
string
required
The style template ID applied to this project.
projects[].roomType
string | null
The room type classification (e.g., living-room, bedroom, kitchen).
projects[].thumbnailUrl
string | null
URL to the project thumbnail image. Typically the first uploaded image.
projects[].status
string
required
Current project status.Values:
  • pending - No images processed yet
  • processing - At least one image is being processed
  • completed - All images completed successfully
  • failed - All images failed to process
projects[].imageCount
number
required
Total number of images in the project.
projects[].completedCount
number
required
Number of successfully processed images.
projects[].createdAt
string
required
ISO 8601 timestamp when the project was created.
projects[].updatedAt
string
required
ISO 8601 timestamp when the project was last updated.

Response Example

[
  {
    "id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
    "workspaceId": "ws_abc123",
    "userId": "user_xyz789",
    "name": "Sunset Villa - Master Bedroom",
    "styleTemplateId": "modern-scandinavian",
    "roomType": "bedroom",
    "thumbnailUrl": "https://storage.example.com/thumbnails/abc123.jpg",
    "status": "completed",
    "imageCount": 5,
    "completedCount": 5,
    "createdAt": "2024-01-15T10:30:00.000Z",
    "updatedAt": "2024-01-15T11:45:00.000Z"
  },
  {
    "id": "b2c3d4e5-6789-01bc-def2-234567890abc",
    "workspaceId": "ws_abc123",
    "userId": "user_xyz789",
    "name": "Downtown Condo - Kitchen Renovation",
    "styleTemplateId": "minimalist-white",
    "roomType": "kitchen",
    "thumbnailUrl": "https://storage.example.com/thumbnails/def456.jpg",
    "status": "processing",
    "imageCount": 8,
    "completedCount": 3,
    "createdAt": "2024-01-14T09:15:00.000Z",
    "updatedAt": "2024-01-14T10:22:00.000Z"
  },
  {
    "id": "c3d4e5f6-7890-12cd-ef34-34567890abcd",
    "workspaceId": "ws_abc123",
    "userId": "user_xyz789",
    "name": "Mountain Retreat - Exterior",
    "styleTemplateId": "rustic-modern",
    "roomType": "exterior",
    "thumbnailUrl": null,
    "status": "pending",
    "imageCount": 0,
    "completedCount": 0,
    "createdAt": "2024-01-13T14:20:00.000Z",
    "updatedAt": "2024-01-13T14:20:00.000Z"
  }
]

Implementation Details

Query Process

  1. Authentication - Validates user session via Better-Auth
  2. Workspace Lookup - Retrieves user’s workspace ID
  3. Database Query - Fetches projects with optional filters
  4. Ordering - Results sorted by createdAt DESC (newest first)

Database Query

SELECT * FROM project
WHERE workspace_id = $workspaceId
  AND ($status IS NULL OR status = $status)
ORDER BY created_at DESC
LIMIT $limit OFFSET $offset;

Performance Considerations

  • Indexed Fields: Queries use indexed workspace_id, status, and created_at columns
  • Denormalized Counts: imageCount and completedCount are pre-calculated for fast reads
  • Pagination: Use limit and offset for large datasets to reduce payload size

Project Statistics

To get aggregated statistics across all projects, use the getProjectStats query:
const stats = await getProjectStats(workspaceId);
// Returns:
{
  totalProjects: 45,
  completedProjects: 38,
  processingProjects: 5,
  totalImages: 342
}

Status Tracking

Project status is automatically updated when image processing completes:
  • pendingprocessing: When first image starts processing
  • processingcompleted: When all images complete successfully
  • processingfailed: When all images fail (and none succeeded)
The status update logic is in /lib/db/queries.ts:updateProjectCounts (lines 404-516).
  • Create new project: See Create Project
  • Get single project with images: See Get Project
  • Delete project: DELETE /api/projects/:id

Source Code Reference

Implemented in:
  • Server Action: /app/dashboard/page.tsx:getProjects (line 30)
  • Database Query: /lib/db/queries.ts:getProjects (lines 279-305)
  • Stats Query: /lib/db/queries.ts:getProjectStats (lines 333-372)
  • Schema: /lib/db/schema.ts:project (lines 164-196)

Build docs developers (and LLMs) love