openapi: 3.1.0 info: # Do not change the title, if the title changes, the import paths will be broken title: Api version: 0.1.0 description: Design Studio OS API servers: - url: /api description: Base API path tags: - name: health description: Health operations - name: projects description: Project management - name: clients description: Client management - name: tasks description: Task management - name: timeEntries description: Time tracking - name: briefs description: Brief templates - name: dashboard description: Dashboard statistics paths: /healthz: get: operationId: healthCheck tags: [health] summary: Health check responses: "200": description: Healthy content: application/json: schema: $ref: "#/components/schemas/HealthStatus" # ─── Projects ─────────────────────────────────────────────────────────────── /projects: get: operationId: listProjects tags: [projects] summary: List all projects parameters: - name: status in: query schema: type: string enum: [briefing, concept, design, review, delivered, archived] - name: clientId in: query schema: type: integer responses: "200": description: List of projects content: application/json: schema: type: array items: $ref: "#/components/schemas/Project" post: operationId: createProject tags: [projects] summary: Create a new project requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateProjectBody" responses: "201": description: Project created content: application/json: schema: $ref: "#/components/schemas/Project" /projects/{id}: get: operationId: getProject tags: [projects] summary: Get a project by ID parameters: - name: id in: path required: true schema: type: integer responses: "200": description: Project details content: application/json: schema: $ref: "#/components/schemas/Project" patch: operationId: updateProject tags: [projects] summary: Update a project parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateProjectBody" responses: "200": description: Updated project content: application/json: schema: $ref: "#/components/schemas/Project" delete: operationId: deleteProject tags: [projects] summary: Delete a project parameters: - name: id in: path required: true schema: type: integer responses: "204": description: Deleted # ─── Clients ──────────────────────────────────────────────────────────────── /clients: get: operationId: listClients tags: [clients] summary: List all clients responses: "200": description: List of clients content: application/json: schema: type: array items: $ref: "#/components/schemas/Client" post: operationId: createClient tags: [clients] summary: Create a client requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateClientBody" responses: "201": description: Client created content: application/json: schema: $ref: "#/components/schemas/Client" /clients/{id}: get: operationId: getClient tags: [clients] summary: Get a client by ID parameters: - name: id in: path required: true schema: type: integer responses: "200": description: Client details content: application/json: schema: $ref: "#/components/schemas/Client" patch: operationId: updateClient tags: [clients] summary: Update a client parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateClientBody" responses: "200": description: Updated client content: application/json: schema: $ref: "#/components/schemas/Client" delete: operationId: deleteClient tags: [clients] summary: Delete a client parameters: - name: id in: path required: true schema: type: integer responses: "204": description: Deleted # ─── Tasks ────────────────────────────────────────────────────────────────── /tasks: get: operationId: listTasks tags: [tasks] summary: List tasks parameters: - name: projectId in: query schema: type: integer - name: done in: query schema: type: boolean responses: "200": description: List of tasks content: application/json: schema: type: array items: $ref: "#/components/schemas/Task" post: operationId: createTask tags: [tasks] summary: Create a task requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateTaskBody" responses: "201": description: Task created content: application/json: schema: $ref: "#/components/schemas/Task" /tasks/{id}: patch: operationId: updateTask tags: [tasks] summary: Update a task parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateTaskBody" responses: "200": description: Updated task content: application/json: schema: $ref: "#/components/schemas/Task" delete: operationId: deleteTask tags: [tasks] summary: Delete a task parameters: - name: id in: path required: true schema: type: integer responses: "204": description: Deleted # ─── Time Entries ──────────────────────────────────────────────────────────── /time-entries: get: operationId: listTimeEntries tags: [timeEntries] summary: List time entries parameters: - name: projectId in: query schema: type: integer responses: "200": description: List of time entries content: application/json: schema: type: array items: $ref: "#/components/schemas/TimeEntry" post: operationId: createTimeEntry tags: [timeEntries] summary: Log time entry requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateTimeEntryBody" responses: "201": description: Time entry created content: application/json: schema: $ref: "#/components/schemas/TimeEntry" /time-entries/{id}: delete: operationId: deleteTimeEntry tags: [timeEntries] summary: Delete a time entry parameters: - name: id in: path required: true schema: type: integer responses: "204": description: Deleted # ─── Briefs ────────────────────────────────────────────────────────────────── /briefs: get: operationId: listBriefs tags: [briefs] summary: List brief templates responses: "200": description: List of briefs content: application/json: schema: type: array items: $ref: "#/components/schemas/Brief" post: operationId: createBrief tags: [briefs] summary: Create a brief template requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateBriefBody" responses: "201": description: Brief created content: application/json: schema: $ref: "#/components/schemas/Brief" /briefs/{id}: patch: operationId: updateBrief tags: [briefs] summary: Update a brief parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateBriefBody" responses: "200": description: Updated brief content: application/json: schema: $ref: "#/components/schemas/Brief" delete: operationId: deleteBrief tags: [briefs] summary: Delete a brief parameters: - name: id in: path required: true schema: type: integer responses: "204": description: Deleted # ─── Dashboard / Wow ───────────────────────────────────────────────────────── /dashboard/stats: get: operationId: getDashboardStats tags: [dashboard] summary: Get dashboard statistics responses: "200": description: Dashboard stats content: application/json: schema: $ref: "#/components/schemas/DashboardStats" /dashboard/activity: get: operationId: getRecentActivity tags: [dashboard] summary: Get recent activity feed parameters: - name: limit in: query schema: type: integer default: 10 responses: "200": description: Recent activity content: application/json: schema: type: array items: $ref: "#/components/schemas/ActivityItem" /dashboard/deadlines: get: operationId: getUpcomingDeadlines tags: [dashboard] summary: Get upcoming deadlines responses: "200": description: Upcoming deadlines content: application/json: schema: type: array items: $ref: "#/components/schemas/Project" components: schemas: HealthStatus: type: object properties: status: type: string required: [status] # ─── Project ──────────────────────────────────────────────────────────── Project: type: object properties: id: type: integer title: type: string description: type: string nullable: true clientId: type: integer nullable: true clientName: type: string nullable: true status: type: string enum: [briefing, concept, design, review, delivered, archived] priority: type: string enum: [low, medium, high] budget: type: number nullable: true deadline: type: string nullable: true driveUrl: type: string nullable: true planUrl: type: string nullable: true totalHours: type: number nullable: true createdAt: type: string updatedAt: type: string required: [id, title, status, priority, createdAt, updatedAt] CreateProjectBody: type: object properties: title: type: string description: type: string nullable: true clientId: type: integer nullable: true status: type: string enum: [briefing, concept, design, review, delivered, archived] default: briefing priority: type: string enum: [low, medium, high] default: medium budget: type: number nullable: true deadline: type: string nullable: true driveUrl: type: string nullable: true planUrl: type: string nullable: true required: [title] UpdateProjectBody: type: object properties: title: type: string description: type: string nullable: true clientId: type: integer nullable: true status: type: string enum: [briefing, concept, design, review, delivered, archived] priority: type: string enum: [low, medium, high] budget: type: number nullable: true deadline: type: string nullable: true driveUrl: type: string nullable: true planUrl: type: string nullable: true # ─── Client ───────────────────────────────────────────────────────────── Client: type: object properties: id: type: integer name: type: string email: type: string nullable: true phone: type: string nullable: true company: type: string nullable: true notes: type: string nullable: true projectCount: type: integer nullable: true createdAt: type: string required: [id, name, createdAt] CreateClientBody: type: object properties: name: type: string email: type: string nullable: true phone: type: string nullable: true company: type: string nullable: true notes: type: string nullable: true required: [name] UpdateClientBody: type: object properties: name: type: string email: type: string nullable: true phone: type: string nullable: true company: type: string nullable: true notes: type: string nullable: true # ─── Task ─────────────────────────────────────────────────────────────── Task: type: object properties: id: type: integer projectId: type: integer title: type: string done: type: boolean dueDate: type: string nullable: true createdAt: type: string required: [id, projectId, title, done, createdAt] CreateTaskBody: type: object properties: projectId: type: integer title: type: string dueDate: type: string nullable: true required: [projectId, title] UpdateTaskBody: type: object properties: title: type: string done: type: boolean dueDate: type: string nullable: true # ─── TimeEntry ────────────────────────────────────────────────────────── TimeEntry: type: object properties: id: type: integer projectId: type: integer description: type: string nullable: true hours: type: number date: type: string createdAt: type: string required: [id, projectId, hours, date, createdAt] CreateTimeEntryBody: type: object properties: projectId: type: integer description: type: string nullable: true hours: type: number date: type: string required: [projectId, hours, date] # ─── Brief ────────────────────────────────────────────────────────────── Brief: type: object properties: id: type: integer title: type: string category: type: string nullable: true content: type: string createdAt: type: string updatedAt: type: string required: [id, title, content, createdAt, updatedAt] CreateBriefBody: type: object properties: title: type: string category: type: string nullable: true content: type: string required: [title, content] UpdateBriefBody: type: object properties: title: type: string category: type: string nullable: true content: type: string # ─── Dashboard ────────────────────────────────────────────────────────── DashboardStats: type: object properties: activeProjects: type: integer totalClients: type: integer hoursThisMonth: type: number pendingTasks: type: integer projectsByStatus: type: array items: type: object properties: status: type: string count: type: integer required: [status, count] revenueThisMonth: type: number required: [activeProjects, totalClients, hoursThisMonth, pendingTasks, projectsByStatus, revenueThisMonth] ActivityItem: type: object properties: id: type: string type: type: string enum: [project_created, project_updated, task_completed, time_logged, client_added] description: type: string entityId: type: integer nullable: true createdAt: type: string required: [id, type, description, createdAt]