TaskPrio is agent-native. Everything the board does, agents can do over HTTP or the built-in MCP server. One queue, one priority order, top to bottom.
Two ways to authenticate: Bearer token (agents · CLI · curl) or session cookie (the board · set by Google Sign-In). Bearer is the agent path.
Get your token from the account dialog: click Connect on the board → sign in with Google → click your account chip → Copy agent token. Then put it in your shell config — never paste a bearer token into a chat:
# macOS / zsh — paste your real token in place of the placeholder
printf '\nexport PROMPTPRIO_API_TOKEN="REPLACE_ME"\n' >> ~/.zshenv
source ~/.zshenv
All authenticated requests need the header:
Authorization: Bearer $PROMPTPRIO_API_TOKEN
To rotate your token (the old one stops working immediately):
curl -X POST https://promptprio.com/api/auth/token/rotate \
-H "Authorization: Bearer $PROMPTPRIO_API_TOKEN"
# → { "apiToken": "pp_..." }
To check who you are:
curl https://promptprio.com/api/auth/me \
-H "Authorization: Bearer $PROMPTPRIO_API_TOKEN"
# → { "user": { "id": ..., "email": ..., "plan": ..., "apiToken": ... }, "via": "token" }
Note: a 401 response on /api/auth/me means your token is invalid; on any other path it usually means your token is fine but the route doesn't exist (catch-all auth gate fires before 404).
Native to Claude Code · Cursor · ChatGPT. Same tools as the REST API; the agent calls them by name instead of curl.
Open the Account dialog (sidebar foot → your email) → click Install MCP (1 command). Paste the copied command into your terminal. Done.
PROMPTPRIO_API_TOKEN=pp_xxx bash <(curl -fsSL https://promptprio.com/install.sh)
What it does:
/api/auth/me.~/.local/share/promptprio/mcp-server.js.promptprio entry into ~/.claude/mcp.json (preserves your other servers).Re-run any time to update — idempotent. Then restart Claude Code and ask "list my promptprio tasks".
Note: the leading space in the command keeps the token out of ~/.zsh_history on most shells.
If you'd rather edit ~/.claude/mcp.json yourself, use the Copy MCP config button. The snippet is self-installing — first run caches the bundled server, subsequent runs reuse it:
{
"mcpServers": {
"promptprio": {
"command": "bash",
"args": ["-c", "mkdir -p ~/.local/share/promptprio && [ -s ~/.local/share/promptprio/mcp-server.js ] || curl -fsSL https://promptprio.com/mcp-server.js -o ~/.local/share/promptprio/mcp-server.js; exec node ~/.local/share/promptprio/mcp-server.js"],
"env": {
"PROMPTPRIO_API_TOKEN": "pp_…",
"PROMPTPRIO_API_URL": "https://taskprio.com"
}
}
}
}
Clone the repo and run with tsx:
git clone https://gitlab.com/acevault-lab/promptprio-com.git
cd promptprio-com
npm install
PROMPTPRIO_API_TOKEN="$PROMPTPRIO_API_TOKEN" npm run mcp
Then point at src/server/mcp.ts in your MCP config:
{
"mcpServers": {
"promptprio": {
"command": "node",
"args": ["--import", "tsx", "/path/to/promptprio-com/src/server/mcp.ts"],
"env": { "PROMPTPRIO_API_TOKEN": "$PROMPTPRIO_API_TOKEN" }
}
}
}
Tools exposed: get_next_task, list_tasks, search_tasks, export_queue, create_task, triage_task, update_task, reprioritize_task, schedule_task, complete_task, flag_needs_human, add_project.
/api/boardAll non-terminal tasks + projects + organisations + single-select lists, in one round trip. The board UI uses this on load and every 15 s.
curl https://promptprio.com/api/board \
-H "Authorization: Bearer $PROMPTPRIO_API_TOKEN"
# → { tasks: [...], projects: [...], organisations: [...], selectLists: [...] }
/api/nextReturns the single highest-priority actionable task, leased to your agent for 15 minutes. Optional query params: project, agent, count.
Response includes context — the merged system prompt for that task (project Stack/Commands/Don't/Persona/Done/Notes + the task body itself).
curl https://promptprio.com/api/next \
-H "Authorization: Bearer $PROMPTPRIO_API_TOKEN"
# → { task: {...}, priority: 1, context: "# Project: ...\n## Persona\n..." }
# When the queue is empty: { task: null }
Batch mode (multiple tasks at once):
curl 'https://promptprio.com/api/next?count=5&agent=claude-code' \
-H "Authorization: Bearer $PROMPTPRIO_API_TOKEN"
# → { tasks: [...up to 5...] }
/api/tasksCreate a task. place: inbox (default) · top · bottom.
curl -X POST https://promptprio.com/api/tasks \
-H "Authorization: Bearer $PROMPTPRIO_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Refactor the auth middleware",
"body": "Extract token validation into lib/auth.ts and add tests.",
"projectId": "proj_...",
"assignee": "llm",
"place": "top",
"subtasks": [{"title":"Write tests","done":false}]
}'
/api/tasksList ranked tasks. Filter with ?project=... or ?status=....
/api/tasks/{id}Fetch a single task by id.
/api/tasks/{id}Update any of: title, body, assignee, projectId, tags, scheduledFor, dependsOn, attachments, subtasks, status, selectValues.
# set Status property to "Doing" + reassign to your agent
curl -X PATCH https://promptprio.com/api/tasks/$TASK_ID \
-H "Authorization: Bearer $PROMPTPRIO_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "assignee": "llm", "selectValues": { "list_status": "opt_doing" } }'
/api/tasks/{id}Soft-delete (moves to trash; recoverable via POST /api/tasks/{id}/restore).
/api/tasks/{id}/completeMark done. result is required (one-line summary; agents log what they did).
curl -X POST https://promptprio.com/api/tasks/$TASK_ID/complete \
-H "Authorization: Bearer $PROMPTPRIO_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "result": "Extracted to lib/auth.ts. 12 tests added, all green." }'
/api/tasks/{id}/needs-humanPark the task — agent is blocked, operator needs to unblock. question is required.
/api/tasks/{id}/scheduleDefer until scheduledFor (epoch ms). Optional targetPriority for explicit slot on activation.
/api/tasks/{id}/reprioritizeMove within the single global queue. Body: {beforeId} · {afterId} · {top:true} · {bottom:true}.
/api/tasks/{id}/triageMove an Inbox task into the ranked queue. Body: {place: "top"|"bottom"}.
/api/projects · POST /api/projects · PATCH /api/projects/{id} · DELETE /api/projects/{id}Project fields: name, color, workingDir, instructions (Notes), organisationId, plus the structured LLM-context fields stack · commands · repo · dontDo · persona · definitionOfDone.
curl -X POST https://promptprio.com/api/projects \
-H "Authorization: Bearer $PROMPTPRIO_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "myapp",
"stack": "Next.js 14, TypeScript, Tailwind, Drizzle, Postgres",
"commands": "dev: npm run dev\ntest: npm test\ndeploy: npm run deploy",
"repo": "https://gitlab.com/me/myapp",
"dontDo": "Don'\''t touch /legacy. Don'\''t add deps without asking."
}'
/api/projects/reorderReorder columns. Body: {order: ["proj_a", "proj_b", ...]}. Any project not in the array keeps its existing position (appended).
/api/organisations · POST /api/organisations · PATCH · DELETE · POST /api/organisations/reorderGroup projects in the board overview. Every cloud account has at least one ("Personal" by default). Deleting an org reparents its projects to the first remaining org.
/api/select-lists · POST /api/select-lists · PATCH · DELETEReusable single-select lists — e.g. "Status" with options "Todo / Doing / Blocked / Done". Each task assigns one optionId per list.
curl -X POST https://promptprio.com/api/select-lists \
-H "Authorization: Bearer $PROMPTPRIO_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Status",
"options": [{"label":"Todo"},{"label":"Doing"},{"label":"Done"}]
}'
/api/select-lists/{id}/options · PATCH /api/select-lists/{id}/options/{optionId} · DELETEPer-option CRUD. Deleting an option clears it from every task.
/api/export?format=md|jsonWhole queue as markdown (ordered, id-tagged, with property tags inline) or JSON.
/api/search?q=<query>Full-text against title · body · result. Same matching logic as the board search box.
/api/uploadAttach a file to a task. Body: raw bytes. Headers: Content-Type, X-Filename. Limits: 1 MB free · 4 MB Pro. Returns {url, name, type, size} — use the URL in the task's attachments field.
Opt-in outbound webhooks: TaskPrio POSTs a signed JSON payload to your URL when a task changes — the push alternative to the change-feed. HTTPS only; URLs are SSRF-guarded (private / loopback / link-local / cloud-metadata hosts are rejected). Delivery is best-effort with a ~2.5s timeout (no retry yet), so make your endpoint idempotent.
/api/webhooksSubscribe. events defaults to ["*"] (all); valid values: task.created, task.updated, task.completed, task.deleted. The signing secret is returned once, here — store it. Up to 25 webhooks per account.
curl -X POST https://promptprio.com/api/webhooks \
-H "Authorization: Bearer $PROMPTPRIO_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/hook","events":["task.completed"]}'
# -> {"webhook":{"id":"...","url":"...","events":[...],"secret":"whsec_...","recent":[]}}
/api/webhooksList your webhooks. The secret is masked (full value only at create). recent holds the last 20 delivery attempts (status · ok · error).
/api/webhooks/{id}Unsubscribe.
{
"event": "task.completed",
"timestamp": "2026-06-02T09:00:00.000Z",
"data": { "task": { /* full task */ }, "previous": { /* prior task — task.updated only */ } }
}
Headers: X-TaskPrio-Event and X-TaskPrio-Signature: sha256=<hex>.
The signature is HMAC-SHA256(secret, rawRequestBody). Verify it before trusting a delivery:
import crypto from "node:crypto";
// `body` = the RAW request body string; `secret` = this webhook's signing secret
const expected = "sha256=" + crypto.createHmac("sha256", secret).update(body).digest("hex");
const got = req.headers["x-promptprio-signature"] || "";
const ok = got.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected));
if (!ok) return res.status(401).end(); // reject forgeries
/api/changes?since=<epoch-ms>Returns {tasks, now} — every task (any status) updated at or after since, oldest-first, capped at 200. Poll on an interval and pass the previous response's now back as the next since; dedupe by task id. Completions and deletions appear here (with their new status) so a live view can drop them. Lighter than refetching /api/board; the push alternative is webhooks.
curl "https://promptprio.com/api/changes?since=0" \
-H "Authorization: Bearer $PROMPTPRIO_API_TOKEN"
# -> {"tasks":[ ...changed, oldest-first... ],"now":1780000000000}
# next poll: use the returned `now` as ?since=
| Code | Meaning | Common cause |
|---|---|---|
| 200 | OK | — |
| 201 | Created | POST succeeded |
| 400 | Bad request | Missing required field (e.g. title, result, project name) |
| 401 | Unauthorized | Token invalid OR you're hitting a route that doesn't exist (the auth-gate middleware fires before route-not-found) |
| 402 | Payment required | Free-tier cap hit (150 active tasks · 3 projects · 50 daily agent completions) |
| 403 | Forbidden | Token missing a required scope |
| 404 | Not found | Task / project / org / list id doesn't exist for your account |
| 413 | Payload too large | Attachment exceeds size limit |
| 500 | Server | Storage backend transient — retry with exponential backoff |