The TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing.
- Desktop only
- Disabled by default
- Started when Obsidian starts and TaskNotes API is enabled
- Not available on mobile
Enable it in Settings -> TaskNotes -> Integrations -> HTTP API.
http://localhost:{PORT}
Default port is 8080.
Authentication is optional.
- If
apiAuthTokenis empty, all API requests are accepted. - If
apiAuthTokenis set, sendAuthorization: Bearer <token>.
Example:
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8080/api/healthSuccess:
{
"success": true,
"data": {}
}Error:
{
"success": false,
"error": "Error message"
}GET /api/healthGET /api/docsGET /api/docs/uiPOST /api/nlp/parsePOST /api/nlp/create
GET /api/tasksPOST /api/tasksGET /api/tasks/:idPUT /api/tasks/:idDELETE /api/tasks/:idPOST /api/tasks/:id/toggle-statusPOST /api/tasks/:id/archivePOST /api/tasks/:id/complete-instancePOST /api/tasks/queryGET /api/filter-optionsGET /api/stats
POST /api/tasks/:id/time/startPOST /api/tasks/:id/time/start-with-descriptionPOST /api/tasks/:id/time/stopGET /api/tasks/:id/timeGET /api/time/activeGET /api/time/summary
POST /api/pomodoro/startPOST /api/pomodoro/stopPOST /api/pomodoro/pausePOST /api/pomodoro/resumeGET /api/pomodoro/statusGET /api/pomodoro/sessionsGET /api/pomodoro/stats
GET /api/calendarsGET /api/calendars/googleGET /api/calendars/microsoftGET /api/calendars/subscriptionsGET /api/calendars/events
POST /api/webhooksGET /api/webhooksDELETE /api/webhooks/:idGET /api/webhooks/deliveries
See docs/webhooks.md for event and transform details.
Returns service state plus vault metadata.
curl http://localhost:8080/api/healthBasic task listing with pagination only.
Query params:
limit(default50, max200)offset(default0)
Important:
- Filtering params such as
status,priority,tag,project,due_before,due_after,overdue,completed,archived, andsortare rejected on this endpoint with HTTP400. - Use
POST /api/tasks/queryfor filtering.
Example:
curl "http://localhost:8080/api/tasks?limit=25&offset=0"Response fields:
data.tasksdata.paginationwithtotal,offset,limit,hasMoredata.vaultdata.note
Create one task.
Required:
title
Common optional fields:
details,status,priority,due,scheduledtags,contexts,projectsrecurrence,timeEstimate
curl -X POST http://localhost:8080/api/tasks \
-H "Content-Type: application/json" \
-d '{"title":"Review docs","priority":"high"}'Returns HTTP 201 with created task data.
Get one task by path id.
:idmust be URL-encoded task path.
curl "http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md"Update task with partial payload.
curl -X PUT "http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md" \
-H "Content-Type: application/json" \
-d '{"status":"in-progress"}'Delete task file.
Toggle task status via configured workflow.
Toggle archive state.
Complete recurring instance.
Request body:
- Optional
date(ISO string). If omitted, uses current date context.
Advanced filtering.
Request body is a FilterQuery object. Root object is a group with:
type: "group"idconjunction: "and" | "or"children(conditions or groups)
Optional top-level query options:
sortKey,sortDirectiongroupKey,subgroupKey
Example:
{
"type": "group",
"id": "root",
"conjunction": "and",
"children": [
{
"type": "condition",
"id": "c1",
"property": "status",
"operator": "is",
"value": "open"
}
],
"sortKey": "due",
"sortDirection": "asc"
}Response:
data.tasksdata.totaldata.filtereddata.vault
Returns filter options for UI builders.
Returns summary counts:
total,completed,active,overdue,archived,withTimeTracking
Starts a new active time entry for that task.
Starts time tracking and writes description on the new active entry.
Request body:
{
"description": "Implementation"
}Stops active time entry for that task.
Returns per-task time summary and entries.
Returns currently active sessions across tasks.
Important:
- Multiple active sessions can exist across different tasks.
Returns aggregate time summary.
Query params:
period(for exampletoday,week,month,all)from(ISO date)to(ISO date)
Example:
curl "http://localhost:8080/api/time/summary?period=week"Starts a session.
Optional request fields:
taskId(URL path of task)duration(number)
Stops and resets current session.
Pauses running session.
Resumes paused session.
Returns current state plus computed totals (totalPomodoros, currentStreak, totalMinutesToday).
Returns history.
Query params:
limitdate(YYYY-MM-DD)
Returns stats for today or provided date.
Query params:
date(YYYY-MM-DD)
Returns provider connectivity overview and subscription counts.
Returns Google provider details.
- If disconnected, returns
{ "connected": false }.
Returns Microsoft provider details.
- If disconnected, returns
{ "connected": false }.
Returns ICS subscriptions with runtime fields such as lastFetched and lastError.
Returns merged event list from connected providers and ICS subscriptions.
Query params:
start(ISO date/datetime)end(ISO date/datetime)
Response includes:
eventstotalsources(counts by provider)
Registers webhook.
Required fields:
urlevents(non-empty array)
Optional fields:
idsecretactivetransformFilecorsHeaders
Lists registered webhooks. Stored secrets are not returned.
Deletes webhook.
Returns last 100 delivery records.
Returns OpenAPI JSON generated from registered controllers.
Returns Swagger UI.
Common status codes:
400invalid request or invalid state401missing/invalid bearer token (when auth token is configured)404missing task/webhook/resource500internal error
Current behavior:
- CORS allows all origins (
*). - Transport is HTTP only (no TLS).
- Node server is started with
server.listen(port)and does not explicitly bind to127.0.0.1.
Practical guidance:
- Set an auth token.
- Treat API port as sensitive and keep it firewalled.
- If you expose this port outside localhost, route through a trusted reverse proxy and TLS.
- Confirm API is enabled in settings.
- Confirm Obsidian is running.
- Confirm selected port is free.
- Reload plugin or restart Obsidian after changing API enable/port.
- Check token value.
- Check
Bearerprefix. - Remove whitespace around token.
If you pass filters to GET /api/tasks, the endpoint returns 400 by design. Use POST /api/tasks/query.