Skip to main content

Overview

Chronos Calendar provides dedicated endpoints for reordering both todo items and categories. This enables efficient bulk reordering operations, typically triggered by drag-and-drop interactions in the UI. Authentication: All endpoints require authentication via Bearer token.

Reorder Todo Items

POST /todos/reorder

Reorder all todo items in a single operation

Request Body

todoIds
array
required
Array of todo item UUIDs in the desired display order

Response

message
string
Confirmation message: “Reordered”

Example Request

curl -X POST https://api.chronoscalendar.com/todos/reorder \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "todoIds": [
      "abc12345-6789-def0-1234-56789abcdef0",
      "def67890-abcd-1234-5678-90abcdef1234",
      "new12345-6789-abcd-ef01-234567890abc"
    ]
  }'

Example Response

{
  "message": "Reordered"
}

Behavior

Order Assignment: Todos are assigned sequential order values starting from 0.
  • First UUID in array → order: 0
  • Second UUID in array → order: 1
  • Third UUID in array → order: 2
  • And so on…

Use Cases

When a user drags a todo item to a new position, send all visible todo IDs in the new order.
// After user drops item
const reorderedIds = visibleTodos.map(todo => todo.id);
await fetch('/todos/reorder', {
  method: 'POST',
  body: JSON.stringify({ todoIds: reorderedIds })
});
When applying a sort (e.g., by scheduled date or alphabetically), send the sorted IDs to persist the new order.
// Sort by scheduled date
const sorted = todos
  .sort((a, b) => new Date(a.scheduledDate) - new Date(b.scheduledDate))
  .map(todo => todo.id);
await fetch('/todos/reorder', {
  method: 'POST',
  body: JSON.stringify({ todoIds: sorted })
});
Automatically reorder to place completed items at the bottom of the list.
const incomplete = todos.filter(t => !t.completed).map(t => t.id);
const complete = todos.filter(t => t.completed).map(t => t.id);
const reordered = [...incomplete, ...complete];
await fetch('/todos/reorder', {
  method: 'POST',
  body: JSON.stringify({ todoIds: reordered })
});

Reorder Categories

POST /todos/todo-lists/reorder

Reorder all todo list categories in a single operation

Request Body

categoryIds
array
required
Array of category (todo list) UUIDs in the desired display order

Response

message
string
Confirmation message: “Reordered”

Example Request

curl -X POST https://api.chronoscalendar.com/todos/todo-lists/reorder \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "categoryIds": [
      "987fcdeb-51a2-43f1-b123-456789abcdef",
      "123e4567-e89b-12d3-a456-426614174000",
      "456e7890-e12b-34d5-a678-901234567890"
    ]
  }'

Example Response

{
  "message": "Reordered"
}

Behavior

Categories are assigned sequential order values starting from 0, identical to todo item reordering.

Implementation Details

Database Updates

Both reorder endpoints use the same underlying mechanism:
  1. Accept an array of UUIDs in the desired order
  2. Iterate through the array with index enumeration
  3. Update each item’s order field to match its array index
  4. Verify user ownership before updating (security check)
Source: /home/daytona/workspace/source/backend/app/routers/todos.py:64
def reorder_items(supabase, table: str, user_id: str, item_ids: list[UUID]):
    for index, item_id in enumerate(item_ids):
        (
            supabase.table(table)
            .update({"order": index})
            .eq("id", str(item_id))
            .eq("user_id", user_id)
            .execute()
        )

Security

User Isolation: The .eq("user_id", user_id) clause ensures users can only reorder their own items. Attempting to reorder items belonging to other users will silently fail (no update occurs).

Performance Considerations

Batch Operations: Currently, each item is updated individually in a loop. For large lists (100+ items), this may result in slower response times. Consider limiting the number of items reordered in a single operation.

Error Responses

Validation Errors


Best Practices

1

Send Complete List

Always send the complete list of item IDs that should be reordered. Partial lists will only update the included items, potentially creating gaps in the order sequence.
2

Filter by User Context

Only include items owned by the authenticated user. The API will ignore items from other users, but sending them wastes bandwidth.
3

Optimistic UI Updates

Update the UI immediately (optimistically) before the API call completes. Revert on error.
// Optimistic update
const previousOrder = [...todos];
setTodos(newOrder);

try {
  await reorderTodos(newOrder.map(t => t.id));
} catch (error) {
  // Revert on failure
  setTodos(previousOrder);
  showError('Failed to reorder');
}
4

Debounce Rapid Changes

If users can rapidly reorder items (e.g., multiple drag operations), debounce the API calls to avoid overwhelming the server.
const debouncedReorder = debounce(async (ids) => {
  await fetch('/todos/reorder', {
    method: 'POST',
    body: JSON.stringify({ todoIds: ids })
  });
}, 500);

Todo Items

Full CRUD operations for todo items

Todo Lists

Manage categories and lists

Update Todo

Update individual todo order

Update List

Update individual category order

Rate Limiting

All reorder endpoints are subject to the API rate limit configured in application settings. Exceeding the rate limit will return a 429 Too Many Requests response.
To avoid rate limiting during drag-and-drop operations, implement debouncing or only send the reorder request when the user finishes dragging (on drop event, not on every position change).

Build docs developers (and LLMs) love