Skip to main content
PATCH
/
api
/
tasks
/
:id
Update Task
curl --request PATCH \
  --url https://api.example.com/api/tasks/:id \
  --header 'Content-Type: application/json' \
  --data '
{
  "title": "<string>",
  "description": "<string>",
  "completed": true,
  "categoryId": "<string>"
}
'
{
  "_id": "<string>",
  "title": "<string>",
  "description": "<string>",
  "completed": true,
  "categoryId": "<string>",
  "createdAt": "<string>",
  "updatedAt": "<string>",
  "finishedAt": {}
}

Endpoint

PATCH /api/tasks/:id
Performs a partial update on an existing task. Only the fields you include in the request body will be updated. The API automatically manages the updatedAt timestamp and finishedAt timestamp based on changes to the completed field.

Path Parameters

id
string
required
The unique identifier (UUID) of the task to update.Example: 550e8400-e29b-41d4-a716-446655440000

Request Body

All fields are optional - include only the fields you want to update.
title
string
Updated task title.Validation:
  • Minimum length: 3 characters
  • Maximum length: 25 characters
  • Automatically trimmed
Example: "Updated task title"
description
string
Updated task description.Validation:
  • Maximum length: 25 characters
  • Automatically trimmed
Example: "Updated description"
completed
boolean
Updated completion status.Automatic Behavior:
  • When changed from false to true: finishedAt is automatically set to current timestamp
  • When changed from true to false: finishedAt is automatically removed
Example: true
categoryId
string
Updated category assignment.Special Values:
  • Empty string ("") assigns task to "uncategorized"
  • Valid UUID assigns task to that category
Example: "550e8400-e29b-41d4-a716-446655440000" or ""
Do not include _id, createdAt, updatedAt, or finishedAt in your request. These fields are managed automatically by the API. Any attempt to set them will be ignored.

Response

Returns the complete updated task object with all fields.
_id
string
The task’s unique identifier (unchanged).
title
string
The task title (updated if provided in request).
description
string
The task description (updated if provided in request).
completed
boolean
The completion status (updated if provided in request).
categoryId
string
The category ID (updated if provided in request).
createdAt
string
The original creation timestamp (unchanged).
updatedAt
string
Automatically set to current timestamp.
finishedAt
string | null
Automatically managed based on completed status changes.

Status Codes

  • 200 OK - Task successfully updated
  • 400 Bad Request - Validation failed on provided fields
  • 404 Not Found - No task exists with the provided ID

Examples

curl -X PATCH http://localhost:3000/api/tasks/550e8400-e29b-41d4-a716-446655440000 \
  -H "Content-Type: application/json" \
  -d '{"completed":true}'

Request Examples

{
  "completed": true
}

Response Examples

{
  "_id": "550e8400-e29b-41d4-a716-446655440000",
  "title": "Write API documentation",
  "description": "Create comprehensive docs",
  "completed": true,
  "categoryId": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d",
  "createdAt": "2026-03-11T10:00:00.000Z",
  "updatedAt": "2026-03-11T16:00:00.000Z",
  "finishedAt": "2026-03-11T16:00:00.000Z"
}

Automatic Field Management

updatedAt Timestamp

The updatedAt field is always set to the current timestamp on every update, regardless of which fields you modify.

finishedAt Timestamp Logic

When completed changes from false to true:Before:
{
  "completed": false
  // finishedAt not present
}
Request:
{ "completed": true }
After:
{
  "completed": true,
  "finishedAt": "2026-03-11T16:00:00.000Z"
}

Common Use Cases

Toggle Task Completion

async function toggleTaskCompletion(taskId) {
  // First, get the current task
  const getResponse = await fetch(`http://localhost:3000/api/tasks/${taskId}`);
  const task = await getResponse.json();
  
  // Toggle the completion status
  const updateResponse = await fetch(`http://localhost:3000/api/tasks/${taskId}`, {
    method: 'PATCH',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ completed: !task.completed })
  });
  
  return await updateResponse.json();
}

Move Task to Different Category

async function moveTaskToCategory(taskId, newCategoryId) {
  const response = await fetch(`http://localhost:3000/api/tasks/${taskId}`, {
    method: 'PATCH',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ categoryId: newCategoryId })
  });
  
  if (response.ok) {
    const updatedTask = await response.json();
    console.log(`Task moved to category: ${updatedTask.categoryId}`);
    return updatedTask;
  }
}

Rename Task

async function renameTask(taskId, newTitle) {
  const response = await fetch(`http://localhost:3000/api/tasks/${taskId}`, {
    method: 'PATCH',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ title: newTitle })
  });
  
  return await response.json();
}

Update Task Description

async function updateDescription(taskId, newDescription) {
  const response = await fetch(`http://localhost:3000/api/tasks/${taskId}`, {
    method: 'PATCH',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ description: newDescription })
  });
  
  return await response.json();
}

Usage Notes

Partial Updates: This is a PATCH endpoint, which means you only need to include fields you want to change. Unspecified fields remain unchanged.
Optimistic UI Updates: You can update your UI immediately when the user makes changes, then sync with the API in the background for better perceived performance.
Category Validation: The API does not validate whether the categoryId you provide exists. Make sure you’re using valid category UUIDs.
Empty String Behavior: Setting categoryId to an empty string ("") will assign the task to "uncategorized". This is equivalent to removing the category assignment.

Build docs developers (and LLMs) love