Skip to main content
Documentation

API Reference

Complete reference for the Todoify REST API. All endpoints return JSON and follow consistent error conventions.

Quick Start

Get up and running in two steps:

  1. Go to your Profile page and click Create API Key. Copy the key (shown only once).
  2. Use it as a Bearer token in your requests:
export TOKEN="tdf_your_key_here"

# List boards
curl -s -H "Authorization: Bearer $TOKEN" https://yourapp.com/api/boards | jq

# Create a todo
curl -s -X POST https://yourapp.com/api/boards/BOARD_ID/todos \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Buy groceries","priority":"high","column":"todo"}' | jq

Authentication

Bearer Token

Most endpoints accept a Bearer token. Create one from your Profile page under API Keys, then include it in the Authorization header:

Authorization: Bearer tdf_abc123...

Cookie Auth

API key management endpoints (/api/api-keys) require cookie-based session authentication from the browser. Bearer tokens cannot be used to create or revoke API keys.

Errors

All errors follow a consistent format:

{
  "error": {
    "code": "NOT_FOUND",
    "message": "Board not found"
  }
}
UNAUTHORIZED401 — Missing or invalid authentication
BAD_REQUEST400 — Invalid or missing request parameters
NOT_FOUND404 — Resource does not exist or is not owned by you
INTERNAL_ERROR500 — Unexpected server error

Boards

GET/api/boards

List all boards for the authenticated user. Includes a todo count for each board.

Response

[
  {
    "id": "board-uuid",
    "name": "Work Tasks",
    "description": "Sprint backlog",
    "userId": "user-uuid",
    "todoCount": 12,
    "createdAt": "2026-03-01T00:00:00.000Z",
    "updatedAt": "2026-03-30T00:00:00.000Z"
  }
]

curl

curl -H "Authorization: Bearer $TOKEN" \
  https://yourapp.com/api/boards

POST/api/boards

Create a new board.

Request Body

{
  "name": "Work Tasks",
  "description": "Optional description"
}

Response

{
  "id": "board-uuid",
  "name": "Work Tasks",
  "description": "Optional description",
  "userId": "user-uuid",
  "createdAt": "2026-04-01T00:00:00.000Z",
  "updatedAt": "2026-04-01T00:00:00.000Z"
}

curl

curl -X POST https://yourapp.com/api/boards \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Work Tasks","description":"Sprint backlog"}'

PATCH/api/boards/:boardId

Update a board. Include only the fields you want to change.

Request Body

{
  "name": "Renamed Board",
  "description": "Updated description"
}

Response

{
  "id": "board-uuid",
  "name": "Renamed Board",
  "description": "Sprint backlog",
  "userId": "user-uuid",
  "createdAt": "2026-03-01T00:00:00.000Z",
  "updatedAt": "2026-04-01T00:00:00.000Z"
}

curl

curl -X PATCH https://yourapp.com/api/boards/BOARD_ID \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Renamed Board","description":"Updated description"}'

DELETE/api/boards/:boardId

Delete a board and all its todos (cascade).

Response

{ "success": true }

curl

curl -X DELETE https://yourapp.com/api/boards/BOARD_ID \
  -H "Authorization: Bearer $TOKEN"

Todos

GET/api/boards/:boardId/todos

List all todos for a board. Supports optional query filters.

Query Parameters

columnFilter by column. Comma-separated: todo,in-progress,pending,completed
priorityFilter by priority: high, medium, or low
categoryFilter by category: work, personal, health, finance, or other
searchCase-insensitive search across title and description

Response

{
  "board": {
    "id": "board-uuid",
    "name": "Work Tasks",
    "description": "Sprint backlog",
    "userId": "user-uuid",
    "createdAt": "2026-03-01T00:00:00.000Z",
    "updatedAt": "2026-03-30T00:00:00.000Z"
  },
  "todos": [
    {
      "id": "todo-uuid",
      "title": "Buy groceries",
      "description": "",
      "priority": "high",
      "category": "personal",
      "tags": ["errands"],
      "column": "todo",
      "order": 1,
      "humanNotes": "",
      "aiNotes": "",
      "actionDay": "2026-04-02",
      "color": null,
      "boardId": "board-uuid",
      "createdAt": "2026-04-01T00:00:00.000Z",
      "updatedAt": "2026-04-01T00:00:00.000Z"
    }
  ]
}

curl

# All todos
curl -H "Authorization: Bearer $TOKEN" \
  https://yourapp.com/api/boards/BOARD_ID/todos

# With filters
curl -H "Authorization: Bearer $TOKEN" \
  "https://yourapp.com/api/boards/BOARD_ID/todos?column=todo,in-progress&priority=high"

POST/api/boards/:boardId/todos

Create a new todo on a board.

Request Body

{
  "title": "Buy groceries",          // required
  "description": "Milk, eggs, bread", // optional, default ""
  "priority": "high",                 // optional: high | medium | low
  "category": "personal",             // optional: work | personal | health | finance | other
  "tags": ["errands"],                // optional, default []
  "column": "todo",                   // optional: todo | in-progress | pending | completed
  "actionDay": "2026-04-02"           // optional, ISO date string
}

Response

{
  "id": "todo-uuid",
  "title": "Buy groceries",
  "description": "Milk, eggs, bread",
  "priority": "high",
  "category": "personal",
  "tags": ["errands"],
  "column": "todo",
  "order": 5,
  "humanNotes": "",
  "aiNotes": "",
  "actionDay": "2026-04-02",
  "color": null,
  "boardId": "board-uuid",
  "createdAt": "2026-04-01T00:00:00.000Z",
  "updatedAt": "2026-04-01T00:00:00.000Z"
}

curl

curl -X POST https://yourapp.com/api/boards/BOARD_ID/todos \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Buy groceries","priority":"high","column":"todo"}'

PATCH/api/boards/:boardId/todos/:todoId

Update any fields on a todo. Only include the fields you want to change.

Request Body

{
  "title": "Updated title",
  "column": "completed",
  "priority": "low"
}

Response

Returns the full updated todo object.

curl

curl -X PATCH https://yourapp.com/api/boards/BOARD_ID/todos/TODO_ID \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"column":"completed"}'

DELETE/api/boards/:boardId/todos/:todoId

Delete a todo.

Response

{ "success": true }

curl

curl -X DELETE https://yourapp.com/api/boards/BOARD_ID/todos/TODO_ID \
  -H "Authorization: Bearer $TOKEN"

PATCH/api/boards/:boardId/todos/reorder

Reorder todos within a board by providing new order values.

Request Body

{
  "updates": [
    { "id": "todo-uuid-1", "order": 1 },
    { "id": "todo-uuid-2", "order": 2 },
    { "id": "todo-uuid-3", "order": 3 }
  ]
}

Response

{ "success": true }

curl

curl -X PATCH https://yourapp.com/api/boards/BOARD_ID/todos/reorder \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"updates":[{"id":"todo-1","order":1},{"id":"todo-2","order":2}]}'

AI Suggestions

POST/api/ai/suggestions

Get AI-powered suggestions for a todo. Requires the OpenRouter integration to be configured on the server.

Request Body

{
  "title": "Build landing page",       // required
  "description": "For the new product", // optional
  "humanNotes": "Keep it minimal",      // optional
  "existingNotes": "..."                // optional, avoids repeating prior suggestions
}

Response

{
  "suggestions": "- Start with wireframes\n- Choose a color scheme\n- Implement responsive design"
}

curl

curl -X POST https://yourapp.com/api/ai/suggestions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Build landing page","description":"For the new product"}'

API Keys

These endpoints require cookie-based session authentication (browser login). Bearer tokens cannot be used to manage API keys.

GET/api/api-keys

List all API keys for the authenticated user. Never returns the raw key or its hash.

Response

[
  {
    "id": "key-uuid",
    "name": "CLI Session",
    "keyPrefix": "tdf_a1b2",
    "lastUsedAt": "2026-03-30T12:00:00.000Z",
    "expiresAt": null,
    "createdAt": "2026-03-01T00:00:00.000Z"
  }
]

POST/api/api-keys

Create a new API key. The raw key is returned only once in the response.

Request Body

{
  "name": "My CLI Key"
}

Response

{
  "id": "key-uuid",
  "name": "My CLI Key",
  "key": "tdf_a1b2c3d4e5f6...",
  "keyPrefix": "tdf_a1b2",
  "createdAt": "2026-04-01T00:00:00.000Z"
}

DELETE/api/api-keys/:keyId

Revoke an API key. The key will immediately stop working for authentication.

Response

{ "success": true }