Files

14 KiB

name, description, version, trigger, profile
name description version trigger profile
jotty-notes-api Operate Jotty Notes self-hosted instances via REST API. Three instances — Rob (10.0.0.235), Zoe (10.0.0.212), Jennifer (10.0.0.213). Use for checklists, notes, tasks (Kanban), categories, user info, exports, or audit logs. 1.1.0
jotty
jotty notes
jotty checklist
jotty task
my checklist
my note
my task
add to my list
check off
10.0.0.213
213:3000
10.0.0.212
212:3000
10.0.0.235
235:3000
ck_d8a1062be432e58b66c453a8f4c39fb4
ck_ca2d142ec7d2adc2574e4aa73ecef3b0
ck_53e7f7af7ece20557458d84eb6f01782
jennifer to do
zoe to do
to-do list
todo list
jotty api
openj

jotty-notes-api — Jotty Notes REST API client

Covers all three self-hosted Jotty instances. All run Jotty v1.25.1. The API is identical across instances — only the base URL, API key, and owner name differ.

Instances

Owner Base URL API Key Admin? Profile
Rob http://10.0.0.235:3000 ck_53e7f7af7ece20557458d84eb6f01782 yes general
Zoe http://10.0.0.212:3000 ck_ca2d142ec7d2adc2574e4aa73ecef3b0 no openz
Jennifer http://10.0.0.213:3000 ck_d8a1062be432e58b66c453a8f4c39fb4 superadmin openj

Instance selection rule: When the user says "jotty" or "my notes" without specifying, use the instance matching the active profile. When the user names a person ("Zoe's jotty", "Jennifer's checklist"), use that person's instance.

Configuration

# Rob
JOTTY_BASE_URL=http://10.0.0.235:3000
JOTTY_API_KEY=ck_53e7f7af7ece20557458d84eb6f01782
JOTTY_OWNER=Rob

# Zoe
JOTTY_BASE_URL=http://10.0.0.212:3000
JOTTY_API_KEY=ck_ca2d142ec7d2adc2574e4aa73ecef3b0
JOTTY_OWNER=Zoe

# Jennifer
JOTTY_BASE_URL=http://10.0.0.213:3000
JOTTY_API_KEY=ck_d8a1062be432e58b66c453a8f4c39fb4
JOTTY_OWNER=Jennifer

Rob and Jennifer have admin/superadmin access, so admin-only endpoints (logs stats, rebuild-index, export-all, querying other users' summary) are available on their instances. Zoe's key is user-tier — admin endpoints will 403.

Authentication

Every authenticated request uses a single header:

x-api-key: ck_d8a1062be432e58b66c453a8f4c39fb4

API keys are permanent and do not expire. The key provides full access to the owner's account (and, because Jennifer is super-admin, to all users).

Verified live response shapes

These are real shapes captured by hitting the live server, not theory from the docs.

GET /api/health

{"status":"healthy","version":"1.25.1","timestamp":"2026-07-04T15:28:52.527Z"}

GET /api/user

{"user":{"username":"Jennifer","isAdmin":true,"isSuperAdmin":true}}

GET /api/summary

{"summary":{"username":"Jennifer","notes":{"total":1,"categories":{"Uncategorized":1}},
"checklists":{"total":1,"categories":{"Uncategorized":1},"types":{"simple":1}},
"items":{"total":3,"completed":0,"pending":3,"completionRate":0},
"tasks":{"total":0,"completed":0,"inProgress":0,"todo":0,"completionRate":0}}}

GET /api/categories

{"categories":{"notes":[{"name":"Uncategorized","path":"Uncategorized","count":1,"level":0}],
"checklists":[{"name":"Uncategorized","path":"Uncategorized","count":1,"level":0}]}}

Checklist item shape (real, from GET /api/checklists):

{"id":"Jennifer-to-do-list-1783178716552","index":0,"text":"Give Rob loveing.",
 "completed":false,"createdBy":"Jennifer","createdAt":"2026-07-04T15:25:16.552Z",
 "lastModifiedBy":"Jennifer","lastModifiedAt":"2026-07-04T15:25:16.552Z"}

Note that real items include id, createdBy, lastModifiedBy, lastModifiedAt beyond what the docs show — when presenting data to Jennifer, use these extra fields.

Conventions to follow when talking to the user

  • 0-based item indices everywhere (first item is 0).
  • Item references in URLs use dot-paths for nesting: 0, 0.1, 2.0.1.
  • Timestamps are ISO 8601 UTC (createdAt, updatedAt, etc.).
  • createdAt for some seed data is the epoch (1970-01-01T00:00:00.000Z) — that's an upstream quirk, not an error. Prefer updatedAt for "last touched" answers.
  • Default category for new items is Uncategorized if not specified.
  • Default checklist type is simple; use task for Kanban with statuses + time tracking.
  • "Checked off" = PUT /api/checklists/{listId}/items/{idx}/check (which sets completed: true).
  • Errors return {"error":"..."} with HTTP 400/401/403/404/500.

Endpoint quick reference

All paths are prefixed with /api. Auth required unless marked public.

Public

  • GET /api/health — health + version, no auth

Identity & overview

  • GET /api/user — current user (username, isAdmin, isSuperAdmin)
  • GET /api/user/{username} — full profile if self/admin, public fields otherwise
  • GET /api/summary[?username=...] — counts: notes, checklists, items, tasks. Admin can pass username.
  • GET /api/categories — categories used by notes and checklists (excludes archived)

Checklists (simple = checkbox to-do lists)

  • GET /api/checklists[?category=...&type=simple|task&q=...] — list all
  • POST /api/checklists{title, category?, type?} → returns {success, data:{id,...}}
  • PUT /api/checklists/{listId}{title?, category?}
  • DELETE /api/checklists/{listId}
  • POST /api/checklists/{listId}/items{text} or for task type: {text, status?, time?}; use parentIndex: "0.1" for nested
  • PATCH /api/checklists/{listId}/items/{itemIndex} — partial update of text, description, priority (critical/high/medium/low/none), score, startDate, targetDate, estimatedTime
  • PUT /api/checklists/{listId}/items/{idx}/check
  • PUT /api/checklists/{listId}/items/{idx}/uncheck
  • DELETE /api/checklists/{listId}/items/{idx}

Notes

  • GET /api/notes[?category=...&q=...]
  • POST /api/notes{title, content?, category?}
  • PUT /api/notes/{noteId}{title, content?, category?, originalCategory?} (originalCategory is used to locate the existing note)
  • DELETE /api/notes/{noteId}

Tasks (Kanban — task-type checklists)

  • GET /api/tasks[?category=...&status=...&q=...]
  • POST /api/tasks{title, category?, statuses?} (statuses default to todo/in_progress/completed; can supply custom columns with id, label, color, order)
  • GET /api/tasks/{taskId}
  • PUT /api/tasks/{taskId}{title?, category?}
  • DELETE /api/tasks/{taskId}
  • GET /api/tasks/{taskId}/statuses
  • POST /api/tasks/{taskId}/statuses{id, label, color?, order?}
  • PUT /api/tasks/{taskId}/statuses/{statusId}{label?, color?, order?}
  • DELETE /api/tasks/{taskId}/statuses/{statusId} — items in that column auto-move to first available status
  • POST /api/tasks/{taskId}/items{text, status?, parentIndex?}
  • GET /api/tasks/{taskId}/items/{itemIndex} — returns item + nested children
  • PUT /api/tasks/{taskId}/items/{idx}/status{status} (moves between Kanban columns)
  • DELETE /api/tasks/{taskId}/items/{idx}

Admin (Jennifer has access)

  • POST /api/admin/rebuild-index{username} — rebuilds internal link index

Exports

  • POST /api/exports{type, username?} where type is all_checklists_notes | user_checklists_notes | all_users_data | whole_data_folder; returns {success, downloadUrl}
  • GET /api/exports — current export progress {progress, message}

Audit logs (admin can see all; non-admin see own)

  • GET /api/logs?username&action&category&level&startDate&endDate&success&limit&offset (categories: auth, user, checklist, note, sharing, settings, encryption, api, system, file, upload)
  • POST /api/logs/export{format:"json"|"csv", filters?} returns downloadable file
  • GET /api/logs/stats — admin only — aggregated counts by level, category, top actions, top users, recent activity
  • POST /api/logs/cleanup — admin only — deletes logs past retention; returns {success, deletedFiles}

Common action patterns

These are the patterns the agent will most often need. They were all verified against the live server.

Quick health check

curl -s -H "x-api-key: $JOTTY_API_KEY" "$JOTTY_BASE_URL/api/health"

List everything Jennifer owns

curl -s -H "x-api-key: $JOTTY_API_KEY" "$JOTTY_BASE_URL/api/checklists" \
  | python3 -c "import json,sys;d=json.load(sys.stdin);[print(c['title'],c['id'],len(c['items']),'items') for c in d['checklists']]"
curl -s -H "x-api-key: $JOTTY_API_KEY" "$JOTTY_BASE_URL/api/notes" \
  | python3 -c "import json,sys;d=json.load(sys.stdin);[print(n['title'],n['id']) for n in d['notes']]"

Add an item to a checklist

curl -X POST -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
  -d '{"text":"Buy milk"}' \
  "$JOTTY_BASE_URL/api/checklists/<listId>/items"

Check off an item (mark complete)

curl -X PUT -H "x-api-key: $JOTTY_API_KEY" \
  "$JOTTY_BASE_URL/api/checklists/<listId>/items/0/check"

Uncheck an item

curl -X PUT -H "x-api-key: $JOTTY_API_KEY" \
  "$JOTTY_BASE_URL/api/checklists/<listId>/items/0/uncheck"

Create a new simple checklist

curl -X POST -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
  -d '{"title":"Groceries","category":"Shopping","type":"simple"}' \
  "$JOTTY_BASE_URL/api/checklists"

Create a new task board (Kanban)

curl -X POST -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
  -d '{"title":"House Projects","category":"Home","statuses":[
        {"id":"todo","label":"To Do","order":0},
        {"id":"doing","label":"Doing","order":1,"color":"#f59e0b"},
        {"id":"done","label":"Done","order":2}
      ]}' \
  "$JOTTY_BASE_URL/api/tasks"

Add a task item to a specific column

curl -X POST -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
  -d '{"text":"Stain deck","status":"todo"}' \
  "$JOTTY_BASE_URL/api/tasks/<taskId>/items"

Move a task item to another column

curl -X PUT -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
  -d '{"status":"doing"}' \
  "$JOTTY_BASE_URL/api/tasks/<taskId>/items/0/status"

Create a note

curl -X POST -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
  -d '{"title":"Recipes","content":"# Family recipes\n- ..."}' \
  "$JOTTY_BASE_URL/api/notes"

Update a note

curl -X PUT -H "x-api-key: $JOTTY_API_KEY" -H "Content-Type: application/json" \
  -d '{"title":"Recipes v2","content":"# Family recipes\n- ...","category":"Kitchen","originalCategory":"Uncategorized"}' \
  "$JOTTY_BASE_URL/api/notes/<noteId>"
curl -s -H "x-api-key: $JOTTY_API_KEY" \
  "$JOTTY_BASE_URL/api/checklists?q=meeting"
curl -s -H "x-api-key: $JOTTY_API_KEY" \
  "$JOTTY_BASE_URL/api/notes?q=recipe"

Decision rules for the agent

When Jennifer asks to:

  • "add X to my list" / "put X on my to-do" → find a matching checklist (or the default Jennifer-to-do-list) and POST to /api/checklists/{listId}/items. If no obvious list exists, ask which list or create a new one.
  • "check off X" / "mark X done" → GET /api/checklists to find the list, then PUT .../items/{idx}/check. Use search (?q=) if needed.
  • "show my notes" / "what notes do I have" → GET /api/notes and pretty-print titles.
  • "create a new board for X" / "kanban for X" → POST /api/tasks with custom statuses.
  • "move X to doing" → PUT /api/tasks/{taskId}/items/{idx}/status with {"status":"doing"}.
  • "what's on my plate" / "summary" → GET /api/summary and summarize.
  • "delete X" → confirm with Jennifer first; then DELETE the appropriate resource.

Pitfalls

  • Item indices shift after delete. Always re-fetch the list before acting on an index if anything might have changed.
  • PUT /api/notes/{noteId} requires originalCategory to locate the note when categories differ from the requested category — supply it whenever the note is not in Uncategorized.
  • createdAt is the epoch (1970-01-01T00:00:00.000Z) for many existing items; never claim an item is "from 1970" — use updatedAt or lastModifiedAt.
  • Status IDs on task boards are user-defined (default: todo/in_progress/completed). When in doubt, GET /api/tasks/{id}/statuses first to learn the actual column IDs.
  • Custom statuses are only available on the POST /api/tasks creation call; you can't change the column set of a simple checklist, you have to make a task-type board.
  • DELETE /api/tasks/{taskId}/statuses/{statusId} auto-reassigns items in that column to the first available status — safe but irreversible.
  • Jennifer is isSuperAdmin: true, so admin endpoints work, but still scope queries to her own data when possible (/api/summary without ?username=) to avoid leaking other users' totals in chat.
  • The web UI (/api, /docs) at 10.0.0.213:3000 returns the login HTML — those paths are for the browser, not API clients. Stick to /api/* paths.
  • "Audit log" queries can be heavy. Default limit=50; cap to ≤100 unless explicitly asked for more.

Verification

Run these in order to confirm the skill is wired up:

# 1. Health
curl -s -H "x-api-key: ck_d8a1062be432e58b66c453a8f4c39fb4" \
  http://10.0.0.213:3000/api/health
# expect: {"status":"healthy","version":"1.25.1",...}

# 2. Identity
curl -s -H "x-api-key: ck_d8a1062be432e58b66c453a8f4c39fb4" \
  http://10.0.0.213:3000/api/user
# expect: {"user":{"username":"Jennifer","isAdmin":true,"isSuperAdmin":true}}

If either fails with HTTP 307 → /auth/login, the key is wrong or the server is misconfigured. Re-check JOTTY_API_KEY.

Source

API behavior verified against Jotty v1.25.1 on 2026-07-04 from this profile. Docs mirrored from https://github.com/fccview/jotty/blob/main/howto/API.md (last commit 3307091, Jun 14 2026). If the server upgrades past v1.25.1, re-run the two verification curls and update the version field.