Files
hermes-skills/jotty-notes-api/SKILL.md
Hermes Agent b0d790be34 Add all 104 active skills from all 16 Hermes profiles
12 unversioned skills now versioned at 1.0.0:
agent-communication, ascii-video, external-reasoning-augmentation,
jotty-notes-api, minecraft-modpack-server, obsidian, pokemon-player,
powerpoint, social-search, songwriting-and-ai-music,
workspace-context-organization, youtube-content

Total repo: 141 skills across all profile scopes
2026-07-04 11:44:04 -05:00

13 KiB

name, description, version, trigger, profile
name description version trigger profile
jotty-notes-api Operate Jennifer's self-hosted Jotty Notes instance via REST API. Use for any task involving her checklists, notes, tasks (Kanban), categories, user info, exports, or audit logs on the jotty server at 10.0.0.213:3000. 1.0.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
ck_d8a1062be432e58b66c453a8f4c39fb4
jennifer to do
to-do list
todo list
jotty api
openj

jotty-notes-api — Jotty Notes REST API client

Profile-scoped skill for the openj (Jennifer) profile. Gives the agent complete, verified reference + working patterns for the Jotty Notes REST API running at 10.0.0.213:3000. All commands below were tested against the live instance with Jennifer's API key on 2026-07-04 against Jotty v1.25.1.

Configuration

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

The API key belongs to user Jennifer who is isAdmin: true and isSuperAdmin: true, so admin-only endpoints (logs stats, rebuild-index, export-all, querying other users' summary) are available.

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.