# CRUD API Endpoints

Complete reference for Tasks, Events, and Projects API endpoints.

## Overview

All CRUD endpoints follow standard REST conventions and require authentication. They support:

- Full CRUD operations (Create, Read, Update, Delete)
- Workspace-scoped isolation
- Pagination and filtering
- Activity logging for audit trails

## Authentication

All endpoints require Bearer token authentication:

```http
Authorization: Bearer {session_token}
```

The workspace context is extracted from the authenticated user's session.

## Tasks API

### Endpoints

```
GET    /api/tasks           # List tasks
GET    /api/tasks/:id       # Get single task
POST   /api/tasks           # Create task
PATCH  /api/tasks/:id       # Update task
DELETE /api/tasks/:id       # Delete task
```

### List Tasks

```http
GET /api/tasks?status=IN_PROGRESS&page=1&limit=20
```

**Query Parameters:**

- `workspaceId` (UUID, required) — Workspace ID
- `status` (enum, optional) — `NOT_STARTED`, `IN_PROGRESS`, `PAUSED`, `COMPLETED`, `ARCHIVED`
- `priority` (enum, optional) — `LOW`, `MEDIUM`, `HIGH`
- `assigneeId` (UUID, optional) — Filter by assigned user
- `projectId` (UUID, optional) — Filter by project
- `parentId` (UUID, optional) — Filter by parent task (for subtasks)
- `dueDateFrom` (ISO 8601, optional) — Filter tasks due after this date
- `dueDateTo` (ISO 8601, optional) — Filter tasks due before this date
- `page` (integer, optional) — Page number (default: 1)
- `limit` (integer, optional) — Items per page (default: 50, max: 100)

**Response:**

```json
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440003",
      "workspaceId": "550e8400-e29b-41d4-a716-446655440001",
      "title": "Complete API documentation",
      "description": "Write comprehensive docs for CRUD endpoints",
      "status": "IN_PROGRESS",
      "priority": "HIGH",
      "dueDate": "2026-02-01T00:00:00.000Z",
      "assigneeId": "550e8400-e29b-41d4-a716-446655440002",
      "creatorId": "550e8400-e29b-41d4-a716-446655440002",
      "projectId": null,
      "parentId": null,
      "sortOrder": 0,
      "metadata": {},
      "createdAt": "2026-01-28T18:00:00.000Z",
      "updatedAt": "2026-01-28T18:00:00.000Z",
      "completedAt": null,
      "assignee": {
        "id": "550e8400-e29b-41d4-a716-446655440002",
        "name": "John Doe",
        "email": "john@example.com"
      },
      "creator": {
        "id": "550e8400-e29b-41d4-a716-446655440002",
        "name": "John Doe",
        "email": "john@example.com"
      },
      "project": null
    }
  ],
  "meta": {
    "total": 42,
    "page": 1,
    "limit": 20,
    "totalPages": 3
  }
}
```

### Get Single Task

```http
GET /api/tasks/:id
```

**Response:** Same as task object above, plus `subtasks` array.

### Create Task

```http
POST /api/tasks
Content-Type: application/json

{
  "title": "Complete API documentation",
  "description": "Write comprehensive docs for CRUD endpoints",
  "status": "IN_PROGRESS",
  "priority": "HIGH",
  "dueDate": "2026-02-01T00:00:00.000Z",
  "assigneeId": "550e8400-e29b-41d4-a716-446655440002",
  "projectId": null,
  "parentId": null,
  "sortOrder": 0,
  "metadata": {}
}
```

**Fields:**

- `title` (string, required, 1-255 chars) — Task title
- `description` (string, optional, max 10000 chars) — Detailed description
- `status` (enum, optional) — Default: `NOT_STARTED`
- `priority` (enum, optional) — Default: `MEDIUM`
- `dueDate` (ISO 8601, optional) — Target completion date
- `assigneeId` (UUID, optional) — Assigned user
- `projectId` (UUID, optional) — Associated project
- `parentId` (UUID, optional) — Parent task (for subtasks)
- `sortOrder` (integer, optional, min: 0) — Display order
- `metadata` (object, optional) — Custom metadata

**Response (200):** Created task object

**Activity Log:** Automatically logs `CREATED` action for task entity.

### Update Task

```http
PATCH /api/tasks/:id
Content-Type: application/json

{
  "status": "COMPLETED"
}
```

All fields are optional for partial updates. Setting `status` to `COMPLETED` automatically sets `completedAt` timestamp.

**Response (200):** Updated task object

**Activity Logs:**

- `UPDATED` — Always logged
- `COMPLETED` — Logged when status changes to `COMPLETED`
- `ASSIGNED` — Logged when `assigneeId` changes

### Delete Task

```http
DELETE /api/tasks/:id
```

**Response (200):** Empty

**Activity Log:** Logs `DELETED` action with task title in details.

**Note:** Deleting a task with subtasks will cascade delete all subtasks.

---

## Events API

### Endpoints

```
GET    /api/events           # List events
GET    /api/events/:id       # Get single event
POST   /api/events           # Create event
PATCH  /api/events/:id       # Update event
DELETE /api/events/:id       # Delete event
```

### List Events

```http
GET /api/events?startFrom=2026-02-01&startTo=2026-02-28
```

**Query Parameters:**

- `workspaceId` (UUID, required) — Workspace ID
- `projectId` (UUID, optional) — Filter by project
- `startFrom` (ISO 8601, optional) — Events starting after this date
- `startTo` (ISO 8601, optional) — Events starting before this date
- `allDay` (boolean, optional) — Filter all-day events
- `page` (integer, optional) — Page number
- `limit` (integer, optional) — Items per page

**Response:**

```json
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440004",
      "workspaceId": "550e8400-e29b-41d4-a716-446655440001",
      "title": "Team Meeting",
      "description": "Weekly sync",
      "startTime": "2026-02-01T10:00:00.000Z",
      "endTime": "2026-02-01T11:00:00.000Z",
      "allDay": false,
      "location": "Conference Room A",
      "recurrence": null,
      "creatorId": "550e8400-e29b-41d4-a716-446655440002",
      "projectId": null,
      "metadata": {},
      "createdAt": "2026-01-28T18:00:00.000Z",
      "updatedAt": "2026-01-28T18:00:00.000Z",
      "creator": {
        "id": "550e8400-e29b-41d4-a716-446655440002",
        "name": "John Doe",
        "email": "john@example.com"
      },
      "project": null
    }
  ],
  "meta": {
    "total": 15,
    "page": 1,
    "limit": 50,
    "totalPages": 1
  }
}
```

### Create Event

```http
POST /api/events
Content-Type: application/json

{
  "title": "Team Meeting",
  "description": "Weekly sync",
  "startTime": "2026-02-01T10:00:00.000Z",
  "endTime": "2026-02-01T11:00:00.000Z",
  "allDay": false,
  "location": "Conference Room A",
  "recurrence": null,
  "projectId": null,
  "metadata": {}
}
```

**Fields:**

- `title` (string, required, 1-255 chars) — Event title
- `description` (string, optional, max 10000 chars) — Description
- `startTime` (ISO 8601, required) — Event start time
- `endTime` (ISO 8601, optional) — Event end time
- `allDay` (boolean, optional) — Default: false
- `location` (string, optional, max 500 chars) — Location
- `recurrence` (object, optional) — Recurrence rules (RRULE format)
- `projectId` (UUID, optional) — Associated project
- `metadata` (object, optional) — Custom metadata

### Update Event

```http
PATCH /api/events/:id
Content-Type: application/json

{
  "location": "Conference Room B"
}
```

All fields optional for partial updates.

### Delete Event

```http
DELETE /api/events/:id
```

---

## Projects API

### Endpoints

```
GET    /api/projects           # List projects
GET    /api/projects/:id       # Get single project
POST   /api/projects           # Create project
PATCH  /api/projects/:id       # Update project
DELETE /api/projects/:id       # Delete project
```

### List Projects

```http
GET /api/projects?status=ACTIVE
```

**Query Parameters:**

- `workspaceId` (UUID, required) — Workspace ID
- `status` (enum, optional) — `PLANNING`, `ACTIVE`, `PAUSED`, `COMPLETED`, `ARCHIVED`
- `startDateFrom` (ISO 8601, optional) — Projects starting after this date
- `startDateTo` (ISO 8601, optional) — Projects starting before this date
- `page` (integer, optional) — Page number
- `limit` (integer, optional) — Items per page

**Response:**

```json
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440005",
      "workspaceId": "550e8400-e29b-41d4-a716-446655440001",
      "name": "API Development",
      "description": "Build CRUD APIs",
      "status": "ACTIVE",
      "startDate": "2026-01-15",
      "endDate": "2026-02-15",
      "creatorId": "550e8400-e29b-41d4-a716-446655440002",
      "color": "#FF5733",
      "metadata": {},
      "createdAt": "2026-01-28T18:00:00.000Z",
      "updatedAt": "2026-01-28T18:00:00.000Z",
      "creator": {
        "id": "550e8400-e29b-41d4-a716-446655440002",
        "name": "John Doe",
        "email": "john@example.com"
      },
      "_count": {
        "tasks": 12,
        "events": 3
      }
    }
  ],
  "meta": {
    "total": 5,
    "page": 1,
    "limit": 50,
    "totalPages": 1
  }
}
```

### Get Single Project

```http
GET /api/projects/:id
```

Returns project with embedded tasks and events arrays.

### Create Project

```http
POST /api/projects
Content-Type: application/json

{
  "name": "API Development",
  "description": "Build CRUD APIs",
  "status": "ACTIVE",
  "startDate": "2026-01-15",
  "endDate": "2026-02-15",
  "color": "#FF5733",
  "metadata": {}
}
```

**Fields:**

- `name` (string, required, 1-255 chars) — Project name
- `description` (string, optional, max 10000 chars) — Description
- `status` (enum, optional) — Default: `PLANNING`
- `startDate` (ISO 8601 date, optional) — Project start date
- `endDate` (ISO 8601 date, optional) — Project end date
- `color` (string, optional) — Hex color code (e.g., `#FF5733`)
- `metadata` (object, optional) — Custom metadata

### Update Project

```http
PATCH /api/projects/:id
Content-Type: application/json

{
  "status": "COMPLETED"
}
```

All fields optional for partial updates.

### Delete Project

```http
DELETE /api/projects/:id
```

**Note:** Deleting a project sets `projectId` to `null` for all associated tasks and events (does NOT cascade delete).

---

## Error Responses

### 400 Bad Request

Invalid request format or parameters.

```json
{
  "statusCode": 400,
  "message": "Validation failed",
  "error": "Bad Request"
}
```

### 401 Unauthorized

Missing or invalid authentication token.

```json
{
  "statusCode": 401,
  "message": "No authentication token provided",
  "error": "Unauthorized"
}
```

### 404 Not Found

Resource not found or not accessible in workspace.

```json
{
  "statusCode": 404,
  "message": "Task with ID 550e8400-e29b-41d4-a716-446655440003 not found",
  "error": "Not Found"
}
```

### 422 Unprocessable Entity

Validation errors in request body.

```json
{
  "statusCode": 422,
  "message": ["title must not be empty", "priority must be a valid TaskPriority"],
  "error": "Unprocessable Entity"
}
```

## Activity Logging

All CRUD operations automatically create activity log entries for audit trails:

- **Tasks:** `CREATED`, `UPDATED`, `DELETED`, `COMPLETED`, `ASSIGNED`
- **Events:** `CREATED`, `UPDATED`, `DELETED`
- **Projects:** `CREATED`, `UPDATED`, `DELETED`

See [Activity Logging API](../3-activity-logging/README.md) for querying audit trails.

## Examples

### Create Task with Project Association

```bash
curl -X POST http://localhost:3001/api/tasks \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -d '{
    "title": "Design database schema",
    "description": "Create ERD for new features",
    "priority": "HIGH",
    "projectId": "550e8400-e29b-41d4-a716-446655440005",
    "dueDate": "2026-02-05T00:00:00.000Z"
  }'
```

### Filter Tasks by Multiple Criteria

```bash
curl "http://localhost:3001/api/tasks?\
workspaceId=550e8400-e29b-41d4-a716-446655440001&\
status=IN_PROGRESS&\
priority=HIGH&\
dueDateFrom=2026-02-01&\
dueDateTo=2026-02-28&\
page=1&\
limit=20" \
  -H "Authorization: Bearer ${TOKEN}"
```

### Update Task Status to Completed

```bash
curl -X PATCH http://localhost:3001/api/tasks/550e8400-e29b-41d4-a716-446655440003 \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -d '{
    "status": "COMPLETED"
  }'
```

### Create Recurring Event

```bash
curl -X POST http://localhost:3001/api/events \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -d '{
    "title": "Weekly Team Sync",
    "startTime": "2026-02-03T10:00:00.000Z",
    "endTime": "2026-02-03T11:00:00.000Z",
    "recurrence": {
      "freq": "WEEKLY",
      "interval": 1,
      "byweekday": ["MO"]
    },
    "location": "Zoom"
  }'
```

## Next Steps

- [Activity Logging API](../3-activity-logging/README.md)
- [Authentication](../2-authentication/1-endpoints.md)
- [API Conventions](../1-conventions/1-endpoints.md)
